域名与路由架构 SSOT¶
SSOT Key:
platform.domain核心定义: 定义公网域名、容器域名、Traefik 路由的分层架构,以及 Dokploy 域名配置规范。
1. 真理来源 (The Source)¶
| 维度 | 物理位置 (SSOT) | 说明 |
|---|---|---|
| 公网 DNS | Cloudflare Zone: ${INTERNAL_DOMAIN} |
泛域名解析到 VPS_HOST |
| DNS 自动化 | bootstrap/02.dns_and_cert/tasks.py |
管理 Cloudflare 记录 |
| Traefik 配置 | 各服务 compose.yaml labels |
路由规则与中间件 |
| Dokploy 配置 | 各服务 deploy.py |
subdomain 参数控制 |
| 容器 DNS | Docker 内部 DNS | 自动解析容器名 |
2. 域名分层架构¶
┌─────────────────────────────────────────────────────────────┐
│ 用户浏览器 │
│ https://home.zitian.party │
└──────────────────────┬──────────────────────────────────────┘
│ DNS 查询
▼
┌─────────────────────────────────────────────────────────────┐
│ Cloudflare Edge │
│ - DNS: *.zitian.party → VPS_HOST │
│ - SSL: 边缘证书 │
└──────────────────────┬──────────────────────────────────────┘
│ HTTPS (443)
▼
┌─────────────────────────────────────────────────────────────┐
│ Traefik (VPS) │
│ - 路由规则: compose.yaml labels │
│ - SSL: Let's Encrypt 源站证书 │
│ - 中间件: ForwardAuth, CORS, etc. │
└──────────────────────┬──────────────────────────────────────┘
│
┌─────────────┼─────────────┐
│ │ │
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Authentik │ │ Portal │ │ Vault │
│ (SSO检查) │ │ (服务) │ │ (服务) │
└────────────┘ └────────────┘ └────────────┘
│ │ │
└───────────────┴───────────────┘
Docker 内部网络
(容器名: platform-authentik-server${ENV_SUFFIX})
3. 域名类型与用途¶
3.1 公网域名 (Public Domain)¶
- 定义: 由
INTERNAL_DOMAIN环境变量定义的基础域名(如zitian.party) - DNS: Cloudflare 管理,通过 API 自动化
- 用途: 用户访问入口、SSO 回调 URL
- 证书: Cloudflare 边缘证书 + Traefik Let's Encrypt 源站证书
规则: ```bash
Platform 服务(所有环境)¶
${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}
ENV_DOMAIN_SUFFIX: production -> "",非生产 -> "-${ENV}"¶
示例: sso.zitian.party, home-staging.zitian.party¶
说明: ENV 内部用 '_',域名中使用 '-'(如 staging_cn -> staging-cn),且不允许 '-' 或 '/'¶
```
3.2 容器域名 (Container Domain)¶
- 定义: Docker 内部 DNS 自动解析的容器名
- 格式:
${LAYER}-${SERVICE}${ENV_SUFFIX}(如platform-authentik-server-staging) - 用途: 容器间通信、Traefik ForwardAuth 地址
- DNS: Docker 内部 DNS (不可公网访问)
规则: ```yaml
compose.yaml 中定义¶
services: authentik-server: container_name: platform-authentik-server${ENV_SUFFIX} # 其他容器可通过 platform-authentik-server${ENV_SUFFIX}:9000 访问 ```
3.3 Dokploy 域名配置 (可选)¶
- 用途: Dokploy UI 自动生成 Traefik labels
- 限制: 与 compose.yaml labels 冲突
- 推荐: SSO 保护的服务禁用 (
subdomain=None)
4. 路由配置方式对比¶
| 方式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| compose.yaml labels | 完全控制、支持复杂中间件、代码化 | 需手动编写 labels | SSO 保护、需要 ForwardAuth |
| Dokploy UI 配置 | UI 友好、快速配置 | 与 labels 冲突、不支持复杂中间件 | 简单服务、无 SSO |
| 混合模式 | - | 配置分散、难以维护 | ⛔ 禁止 |
5. 标准操作程序 (Playbooks)¶
SOP-001: 新增 SSO 保护服务¶
```bash
1. deploy.py 禁用 Dokploy 域名¶
subdomain = None
2. compose.yaml 添加 Traefik labels¶
labels:
- "traefik.enable=true"
- "traefik.http.routers.${SERVICE}${ENV_DOMAIN_SUFFIX}.rule=Host(${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN})"
- "traefik.http.routers.${SERVICE}${ENV_DOMAIN_SUFFIX}.entrypoints=websecure"
- "traefik.http.routers.${SERVICE}${ENV_DOMAIN_SUFFIX}.tls.certresolver=letsencrypt"
- "traefik.http.middlewares.${SERVICE}-auth.forwardauth.address=http://platform-authentik-server${ENV_SUFFIX}:9000/outpost.goauthentik.io/auth/traefik"
- "traefik.http.routers.${SERVICE}${ENV_DOMAIN_SUFFIX}.middlewares=${SERVICE}-auth@docker"
3. Cloudflare 添加 DNS 记录(如果不在泛域名内)¶
invoke dns_and_cert.add --records=${SERVICE}${ENV_DOMAIN_SUFFIX}
4. Authentik 创建代理应用¶
invoke authentik.shared.create-proxy-app \ --name="${SERVICE}" \ --slug="${SERVICE}" \ --external-host="https://${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}" \ --internal-host="platform-${SERVICE}" ```
SOP-002: 新增非 SSO 服务¶
```bash
1. deploy.py 配置域名(可选)¶
subdomain = "${SERVICE}" # 最终域名: ${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}
2. compose.yaml 不需要 Traefik labels¶
Dokploy 会自动生成基础路由¶
3. Cloudflare 添加 DNS 记录¶
invoke dns_and_cert.add --records=${SERVICE}${ENV_DOMAIN_SUFFIX} ```
SOP-003: 排查域名冲突¶
```bash
1. 检查 Dokploy 配置¶
如果 Domain 字段有值,且 compose.yaml 有 labels,会冲突¶
2. 检查 Traefik 路由¶
docker logs bootstrap-traefik 2>&1 | grep "Router"
3. 检查 DNS 解析¶
dig ${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}
4. 检查证书¶
curl -vI https://${SERVICE}${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN} ```
6. 设计约束 (Dos & Don'ts)¶
✅ 推荐模式 (Whitelist)¶
- SSO 服务用 labels:
subdomain=None+ compose.yaml labels - 简单服务用 Dokploy: UI 配置域名,无需 labels
- 容器间通信用容器名:
platform-authentik-server${ENV_SUFFIX}:9000 - 公网访问用公网域名:
https://sso.zitian.party
⛔ 禁止模式 (Blacklist)¶
- 反模式 A: 同时使用 Dokploy 域名配置和 compose.yaml labels(会冲突)
- 反模式 B: 在 SSO 回调 URL 使用容器名(浏览器无法访问)
- 反模式 C: 硬编码域名在代码中(应使用环境变量
INTERNAL_DOMAIN) - 反模式 D: 手动在 Cloudflare UI 添加记录后不同步到 tasks.py
7. 验证与测试 (The Proof)¶
```bash
1. 检查 DNS 解析¶
dig home.zitian.party
Expected: A record → VPS_HOST¶
2. 检查 HTTPS 可达¶
curl -I https://home.zitian.party
Expected: 200 OK 或 302 (SSO 重定向)¶
3. 检查 Traefik 路由¶
docker logs bootstrap-traefik 2>&1 | grep "home.zitian.party"
Expected: Router created¶
4. 检查容器 DNS¶
docker exec platform-portal${ENV_SUFFIX} ping -c 1 platform-authentik-server${ENV_SUFFIX}
Expected: 解析成功¶
5. 端到端测试¶
pytest e2e_regressions/tests/platform/test_portal.py ```
8. 故障排查¶
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| "502 Bad Gateway" | 容器未启动或端口错误 | 检查 docker ps 和 compose.yaml 端口配置 |
| "404 Not Found" | Traefik 路由未生效 | 检查 labels 语法和 Traefik logs |
| "SSL 证书无效" | Let's Encrypt 申请失败 | 检查 DNS 解析和 80 端口可达性 |
| "DNS 无法解析" | Cloudflare 记录缺失 | 运行 invoke dns_and_cert.apply |
| "重定向循环" | ForwardAuth 地址错误 | 检查 middleware 地址是否为容器名 |