核心架构 SSOT¶
SSOT Key:
core核心定义: 定义基础设施的整体分层架构、环境隔离模型及模块间依赖关系。
1. 真理来源 (The Source)¶
原则:目录结构即架构 (Directory Structure as Architecture)。
本话题的配置和状态由以下物理位置唯一确定:
| 维度 | 物理位置 (SSOT) | 说明 |
|---|---|---|
| 目录结构 | 目录结构规范 | 物理文件布局 |
| 层级定义 | Repo Root | Bootstrap, Platform, Libs, Tools |
| 变量契约 | 远端 SSOT + .env.example |
运行时配置入口 |
| 自动化入口 | tasks.py |
Invoke 任务加载与执行 |
Code as SSOT 索引¶
- 任务加载器:参见
tasks.py - 部署基类:参见
libs/deployer.py - 环境变量/密钥:参见
libs/env.py
2. 架构模型¶
2.1 4-Layer Architecture Overview¶
```mermaid
flowchart TB
subgraph Secrets["Secrets Layer"]
OP["1Password
(Bootstrap Credentials)"]
Vault["Vault
(Machine Secrets)"]
end
subgraph CI["CI/CD Layer"]
GitHub["GitHub<br/>(Code Repository)"]
Actions["GitHub Actions<br/>(Workflows)"]
IaCRunner["IaC Runner<br/>(GitOps Webhook)"]
end
subgraph Bootstrap["L1 Bootstrap (Trust Anchor)"]
Dokploy["Dokploy<br/>(Container Platform)"]
OP1["1Password Connect"]
Vault1["Vault<br/>(Secret Store)"]
IaC["IaC Runner<br/>(Automation)"]
end
subgraph Platform["L2 Platform (Shared Services)"]
PG["PostgreSQL"]
Redis["Redis"]
Authentik["Authentik SSO"]
MinIO["MinIO"]
end
subgraph Apps["L4 Apps (Business Logic)"]
FinanceReport["Finance Report"]
Wealthfolio["Wealthfolio"]
end
%% Secrets flow
OP -->|bootstrap secrets| Vault
Vault -->|app tokens| Platform
Vault -->|app tokens| Apps
%% CI/CD flow
GitHub -->|push to main| Actions
Actions -->|webhook /deploy| IaCRunner
GitHub -->|webhook /webhook| IaCRunner
IaCRunner -->|invoke sync| Platform
%% Bootstrap provides
Dokploy -->|container orchestration| Platform
Dokploy -->|container orchestration| Apps
Vault1 -->|secrets| Platform
Vault1 -->|secrets| Apps
%% Platform provides
PG -->|database| Apps
Redis -->|cache| Apps
Authentik -->|SSO| Apps
MinIO -->|storage| Apps
```
2.2 Simplified Layer Dependency¶
```mermaid
flowchart TB
Bootstrap["L1 Bootstrap
(Trust Anchor)"]
Platform["L2 Platform
(Control Plane)"]
Data["L3 Data
(Stateful Services)"]
Apps["L4 Apps
(Business Logic)"]
Bootstrap -->|Provides Dokploy| Platform
Platform -->|Provides Vault/DB/SSO| Apps
Data -->|Planned| Apps
```
2.3 层级定义¶
| 层级 | 目录 | 职责 | 部署份数 |
|---|---|---|---|
| L1 Bootstrap | bootstrap/ |
启动集群,建立 Trust Anchor | 1 (Global) |
| L2 Platform | platform/ |
提供公共服务 (Vault, SSO, DB) | 1 or N (Per-env) |
3. 设计约束 (Dos & Don'ts)¶
✅ 推荐模式 (Whitelist)¶
- 模式 A: 上层模块只能依赖下层模块的显式交付物(Vault KV 或 Dokploy 环境变量),禁止隐式依赖。
- 模式 B: 环境之间 (Staging vs Prod) 必须在 Data 层及以上进行物理隔离。
⛔ 禁止模式 (Blacklist)¶
- 反模式 A: 禁止 循环依赖 (如 Bootstrap 依赖 Platform 的 Vault)。
- 反模式 B: 禁止 跨环境直接访问数据库 (如 Prod App 连 Staging DB)。
4. 目录结构规范¶
Bootstrap 层目录结构¶
bootstrap/
├── 01.dokploy_install/ # 使用编号前缀(按部署顺序)
│ └── README.md
├── 02.dns_and_cert/
│ └── README.md
├── 03.dokploy_setup/
│ └── README.md
├── 04.1password/
│ ├── README.md
│ └── compose.yaml # 统一使用 compose.yaml
├── 05.vault/
│ ├── README.md
│ ├── compose.yaml
│ └── vault.hcl
└── README.md # 组件索引
规则:
- ✅ 使用 NN.component_name/ 格式(两位数字 + 点号 + 组件名)
- ✅ 编号反映部署顺序和依赖关系
- ✅ 每个组件目录包含 README.md(操作手册)
- ✅ Docker Compose 配置统一命名为 compose.yaml
- ✅ 配置文件与 README 放在同一目录
Platform 层目录结构¶
platform/
├── 01.postgres/
│ ├── README.md
│ ├── compose.yaml
│ ├── deploy.py
│ └── shared_tasks.py
├── 02.redis/
│ ├── README.md
│ ├── compose.yaml
│ ├── deploy.py
│ └── shared_tasks.py
├── 10.authentik/
│ ├── README.md
│ ├── compose.yaml
│ ├── deploy.py
│ └── shared_tasks.py
├── 21.portal/
│ ├── README.md
│ ├── compose.yaml
│ ├── deploy.py
│ └── shared_tasks.py
└── README.md
Volume 路径规范¶
层次结构:
/data/
└── bootstrap/ # 按层级组织
├── 1password/ # 组件数据目录
│ ├── 1password-credentials.json
│ └── ... (database files)
└── vault/
├── file/ # 存储
├── logs/ # 日志
└── config/ # 配置文件
规则:
- ✅ Volume 根路径:/data/<layer>/<component>/
- ✅ Bootstrap 层:/data/bootstrap/<component>/
- ✅ Platform 层:/data/platform/<component>${ENV_SUFFIX}/
- ✅ Data 层:/data/<env>/data/<component>/(若未来引入)
文件命名规范¶
| 文件类型 | 命名规则 | 示例 |
|---|---|---|
| Docker Compose | compose.yaml |
✅ 统一标准名 |
| HCL 配置 | <service>.hcl |
vault.hcl, traefik.hcl |
| 环境变量 | .env.example, .env |
组件目录(.env.example)与项目根(.env 仅作 bootstrap 种子,可选) |
| 自动化脚本 | tasks.py / deploy.py |
Invoke 任务文件 |
| README | README.md |
每个组件目录必需 |
5. 环境变量规范¶
三层结构 (远端 SSOT)¶
| 层级 | 路径格式 | 说明 |
|---|---|---|
| Project | {project} |
Dokploy/Vault 项目级变量 |
| Environment | {project}/{env} |
环境级变量 |
| Service | {project}/{env}/{service} |
服务级变量 |
命名约束:
- project / env / service 不允许包含 - 或 /,避免路径歧义。
- 需要分隔时使用 _(域名会自动转换为 -)。
部署环境选择¶
- DEPLOY_ENV: 目标环境(默认
production) - ENV_DOMAIN_SUFFIX: 生产为空,非生产为
-<env>(如-staging;内部_会转为-) - ENV_SUFFIX: 可选,仅在需要容器/数据路径隔离时显式设置
- 数据路径: 非生产必须配置
DATA_PATH或ENV_SUFFIX(除非ALLOW_SHARED_DATA_PATH=1)
本地文件(仅模板/种子)¶
.env.example:仅 KEY 清单(进 Git,按组件存放).env:bootstrap 种子变量(可选/手动,CI 可用;不进 Git)
服务命名规范¶
原则:目录名、Dokploy 应用名、容器名保持一致性。
- 目录名:
{nn}.{service}(如01.postgres) - Dokploy 应用名:
service(如postgres,redis,authentik) - 容器名:
platform-<service>${ENV_SUFFIX}或<service>-<role>${ENV_SUFFIX}(如platform-postgres-staging,authentik-server-staging)
完整域名格式: <service>${ENV_DOMAIN_SUFFIX}.<internal_domain>
示例:
- sso${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}
- vault${ENV_DOMAIN_SUFFIX}.${INTERNAL_DOMAIN}
域名规则¶
澄清:
INTERNAL_DOMAIN实际是平台的公网基础域名(如zitian.party),由 Cloudflare 管理 DNS 和证书。真正的内网域名是 Docker 容器名(如platform-authentik-server${ENV_SUFFIX})。
| 域名类型 | 用途 | 示例 | 管理方式 |
|---|---|---|---|
| 公网域名 | 用户访问入口 | sso${ENV_DOMAIN_SUFFIX}.zitian.party |
Cloudflare DNS + compose.yaml Traefik labels |
| 容器域名 | 容器间通信 | platform-authentik-server${ENV_SUFFIX} |
Docker 内部 DNS |
| Dokploy 域名 | (可选) 非 SSO 服务 | - | Dokploy UI 配置(与 labels 冲突) |
环境域名规则:
| 环境 | 域名模式 | 示例 |
|---|---|---|
| Production | <service>.<internal_domain> |
sso.${INTERNAL_DOMAIN} |
| Non-Prod | <service>-<env>.<internal_domain> |
sso-staging.${INTERNAL_DOMAIN} |
SSO 保护服务的域名配置:
- deploy.py: subdomain=None (禁用 Dokploy 域名配置)
- compose.yaml: 添加 Traefik labels 定义路由和 ForwardAuth 中间件
- Authentik: external_host 使用公网域名,internal_host 使用容器名
6. 验证与测试 (The Proof)¶
| 行为描述 | 测试文件 (Test Anchor) | 覆盖率 |
|---|---|---|
| 目录结构完整性 | test_structure.py (Backlog) |
⏳ Backlog |
| DNS 规则一致性 | test_network.py |
✅ Critical |