# Beaver Project 域名配置指引 这份文档说明如何从本机测试域名 `127.0.0.1.nip.io` 切换到正式域名。 核心结论: - DNS 只负责把域名解析到 IP。 - DNS 不负责端口。 - `auth-portal` 和用户实例建议使用不同域名。 - 正式环境建议用外层 Nginx、Caddy、Traefik 或云负载均衡监听 `80/443`。 - `router-proxy` 必须收到原始 `Host` 头,才能按实例域名转发。 ## 1. 默认端口职责 | 端口 | 组件 | 是否建议公网直接暴露 | | --- | --- | --- | | `3081` | `auth-portal`,用户登录和注册入口 | 可以,或由外层代理转发 | | `8088` | `router-proxy`,所有实例统一入口 | 可以,或由外层代理转发 | | `8090` | `deploy-control`,内部部署控制面 | 不建议 | | `19090` | `authz-service`,内部鉴权服务 | 不建议 | 正式部署时,通常由外层入口暴露 `80/443`,再转发到本机端口: ```text portal.example.com -> 127.0.0.1:3081 *.apps.example.com -> 127.0.0.1:8088 ``` ## 2. 推荐域名规划 推荐拆成两个域名空间: ```text https://portal.example.com https://alice.apps.example.com https://bob.apps.example.com ``` 含义: - `portal.example.com` 给 `auth-portal` - `*.apps.example.com` 给 `router-proxy` - 每个实例使用一个子域名,例如 `alice.apps.example.com` 不要把门户和实例混在同一个 Host 上。`router-proxy` 是实例入口,`auth-portal` 是认证入口,两者职责不同。 ## 3. DNS 要怎么配 假设服务器公网 IP 是 `203.0.113.10`。 DNS 记录: ```text portal.example.com A 203.0.113.10 apps.example.com A 203.0.113.10 *.apps.example.com A 203.0.113.10 ``` 如果你的 DNS 服务商支持 CNAME,也可以让通配子域名 CNAME 到一个已有 A 记录,但最终结果仍然必须能解析到服务器入口 IP。 注意: - `*.apps.example.com` 用于实例子域名。 - `apps.example.com` 本身不是必须给用户访问,但建议也解析到同一入口,方便证书和排查。 - DNS 不会决定 `3081`、`8088`、`443` 这些端口。 ## 4. 外层反向代理要做什么 外层代理负责: - 监听公网 `80/443` - 处理 TLS 证书 - 按 Host 转发请求 - 透传原始 Host - 支持 WebSocket upgrade 最小映射: ```text portal.example.com -> http://127.0.0.1:3081 *.apps.example.com -> http://127.0.0.1:8088 ``` `*.apps.example.com` 转发到 `router-proxy` 时必须保留原始 Host,例如: ```nginx proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; ``` 否则 `router-proxy` 无法知道请求属于哪个实例。 ## 5. 项目内部要改哪些变量 实例公网地址由 `deploy-control` 里的这些变量决定: | 变量 | 含义 | | --- | --- | | `DEPLOY_PUBLIC_SCHEME` | 对外协议,`http` 或 `https` | | `DEPLOY_PUBLIC_BASE_DOMAIN` | 实例基域名,例如 `apps.example.com` | | `DEPLOY_PUBLIC_HOST_TEMPLATE` | Host 生成模板,默认 `{slug}.{base_domain}` | | `DEPLOY_PUBLIC_PORT` | 对外端口,`80` / `443` 会在生成 URL 时省略 | 本机测试: ```bash export BEAVER_BASE_DOMAIN=127.0.0.1.nip.io ``` `deploy-control`: ```bash -e DEPLOY_PUBLIC_SCHEME="http" \ -e DEPLOY_PUBLIC_BASE_DOMAIN="$BEAVER_BASE_DOMAIN" \ -e DEPLOY_PUBLIC_PORT="8088" \ ``` 生成实例地址: ```text http://alice.127.0.0.1.nip.io:8088 ``` 正式 HTTPS: ```bash export BEAVER_BASE_DOMAIN=apps.example.com ``` `deploy-control`: ```bash -e DEPLOY_PUBLIC_SCHEME="https" \ -e DEPLOY_PUBLIC_BASE_DOMAIN="apps.example.com" \ -e DEPLOY_PUBLIC_PORT="443" \ ``` 生成实例地址: ```text https://alice.apps.example.com ``` 前提是外层代理已经把 `*.apps.example.com:443` 转发到 `router-proxy:8088`。 ## 6. 什么时候 URL 里可以不带端口 浏览器默认端口: - `http` 默认 `80` - `https` 默认 `443` 所以: ```bash DEPLOY_PUBLIC_SCHEME=https DEPLOY_PUBLIC_PORT=443 ``` 生成: ```text https://alice.apps.example.com ``` 而不是: ```text https://alice.apps.example.com:443 ``` 如果你设置: ```bash DEPLOY_PUBLIC_SCHEME=http DEPLOY_PUBLIC_PORT=8088 ``` 生成: ```text http://alice.apps.example.com:8088 ``` 因为 `8088` 不是 HTTP 默认端口。 ## 7. 一套推荐生产配置 假设: - 门户域名:`portal.example.com` - 实例基域名:`apps.example.com` - 外层代理负责 HTTPS - 项目基础容器仍在同一台机器上通过 Docker 运行 部署变量: ```bash export BEAVER_BASE_DOMAIN=apps.example.com export BEAVER_AUTHZ_URL='http://beaver-authz-service:19090' export BEAVER_DEPLOY_URL='http://beaver-deploy-control:8090' ``` `deploy-control`: ```bash -e DEPLOY_PUBLIC_SCHEME="https" \ -e DEPLOY_PUBLIC_BASE_DOMAIN="apps.example.com" \ -e DEPLOY_PUBLIC_PORT="443" \ ``` 外层代理: ```text portal.example.com -> 127.0.0.1:3081 *.apps.example.com -> 127.0.0.1:8088 ``` DNS: ```text portal.example.com -> 服务器 IP apps.example.com -> 服务器 IP *.apps.example.com -> 服务器 IP ``` ## 8. Nginx 外层代理示例 示例只展示关键转发逻辑,证书路径和自动签发方式按你的环境调整。 ```nginx server { listen 80; server_name portal.example.com *.apps.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name portal.example.com; ssl_certificate /etc/letsencrypt/live/portal.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/portal.example.com/privkey.pem; location / { proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://127.0.0.1:3081; } } server { listen 443 ssl http2; server_name *.apps.example.com; ssl_certificate /etc/letsencrypt/live/apps.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/apps.example.com/privkey.pem; location / { proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_pass http://127.0.0.1:8088; } } ``` 证书注意: - `portal.example.com` 可以用普通单域名证书。 - `*.apps.example.com` 需要通配符证书,通常要用 DNS-01 验证。 - 也可以用支持自动证书的 Caddy / Traefik 简化这层。 ## 9. 常见误区 ### DNS 不能配置端口 DNS 只能做: ```text 域名 -> IP ``` 端口来自: - URL 里显式端口 - 协议默认端口 - 外层代理监听和转发规则 ### 不要把 portal 转到 8088 `8088` 是实例入口,不是认证门户入口。 推荐: ```text portal.example.com -> 3081 *.apps.example.com -> 8088 ``` ### 不要公开 8090 和 19090 `8090` 是部署控制面,`19090` 是内部 AuthZ 服务。它们应该只允许容器网络或可信内网访问。 ### 修改 DEPLOY_PUBLIC_* 后旧实例不会自动改 URL 这些变量影响新创建实例的 `public_url` 和 `instance_host`。旧实例已经写入注册表,需要重新创建或手动更新注册表和代理配置。 ## 10. 本机测试不需要正式域名 如果只是本机验证完整链路,继续使用: ```bash export BEAVER_BASE_DOMAIN=127.0.0.1.nip.io ``` 它已经足够测试: - 注册 - 登录 - 自动创建实例 - 跳转个人实例 等准备对外访问时,再切换正式 DNS、HTTPS 和外层代理。