跳转至

核心架构 SSOT

SSOT Key: core 核心定义: 定义基础设施的整体分层架构、环境隔离模型及模块间依赖关系。


1. 真理来源 (The Source)

原则:目录结构即架构 (Directory Structure as Architecture)。

本话题的配置和状态由以下物理位置唯一确定:

维度 物理位置 (SSOT) 说明
目录结构 目录结构规范 物理文件布局
层级定义 Repo Root Bootstrap, Platform, Libs, Tools
变量契约 远端 SSOT + .env.example 运行时配置入口
自动化入口 tasks.py Invoke 任务加载与执行
跨仓库代码契约 infra2-sdk 应用与 infra 固定版本消费的无副作用协议包

Code as SSOT 索引


2. 架构模型

2.1 4-Layer Architecture Overview

flowchart TB
    subgraph Secrets["Secrets Layer"]
        OP["1Password<br/>(Bootstrap Credentials)"]
        Vault["Vault<br/>(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

flowchart TB
    Bootstrap["L1 Bootstrap<br/>(Trust Anchor)"]
    Platform["L2 Platform<br/>(Control Plane)"]
    Data["L3 Data<br/>(Stateful Services)"]
    Apps["L4 Apps<br/>(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 层及以上进行物理隔离。
  • 模式 C: 跨仓库代码共享必须通过固定版本的 infra2-sdk;App 只向 infra2 发部署请求,不执行 infra2 源码。

⛔ 禁止模式 (Blacklist)

  • 反模式 A: 禁止 循环依赖 (如 Bootstrap 依赖 Platform 的 Vault)。
  • 反模式 B: 禁止 跨环境直接访问数据库 (如 Prod App 连 Staging DB)。
  • 反模式 C: 禁止把 workspace submodule 当作 Python/运行时依赖,或形成 infra2 -> app -> infra2 递归引用。

3.1 Repository dependency boundary

三种依赖必须分开:

关系 载体 版本语义
跨仓库代码契约 infra2-sdk wheel/tag 每个消费者独立固定并逐步升级
部署控制 DeployRequest event → infra2 receiver infra2 验证后选择 released IaC tag 并执行 deploy_v2
统一开发入口 repos/{infra2-sdk,finance_report,truealpha} submodules 最近通过集成验证的 workspace 组合,不代表 live 版本

正式生产身份仍是 infra2 release tag、SDK SemVer 和 App image ref/digest;repos/ 指针不得进入 deploy config hash、package discovery 或常规服务 fan-out。开发者通过 git submodule update --init --recursive 取得该组合;更新指针只表示 workspace 集成基线升级,不会触发发布或部署。


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_PATHENV_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
SDK 契约采用 libs/tests/test_sdk_contract_adoption.py ✅ Critical
App 请求边界 libs/tests/test_app_deploy_request.py ✅ Critical

Used by