# compose/ — repo-owned Compose declarations Non-secret Compose sources for the Docker hosts. Secrets are **never** in these files: every secret is a `${VAR}` reference resolved from the **server-local `.env`** (docker compose reads `.env` from the project directory automatically). ## Source-of-truth matrix | Project | Host | Compose source | Mechanism | |---------|------|----------------|-----------| | `vaultwarden` | us2 (`/opt/vaultwarden`) | `compose/vaultwarden/compose.yml` | static file + `compose-deploy.yml` | | `pdns` | hk2 (`/opt/pdns`) | `compose/pdns/compose.yml` | static file + `compose-deploy.yml` | | `pgdb` | pgdb (`/opt/database`, 无 ansible) | `compose/pgdb/compose.yml` | static file(手动部署:scp → `docker compose config -q` → `up -d`;服务器文件名 `docker-compose.yml`) | | `soft-serve` | us2 (`/opt/soft-serve`, 已退役停用) | `compose/soft-serve/compose.yml` (+ `Dockerfile.backup`, `scripts/`) | static file(参考镜像; 2026-09-18 被 gitea 替换 VPS-94, 数据保留作回滚) | | `gitea` | us2 (`/opt/gitea`) | `compose/gitea/compose.yml` (+ `Dockerfile.backup`, `scripts/`) | static file(参考镜像, 未接入 compose-deploy; 服务器文件为准; 2026-09-18 替换 soft-serve, VPS-94) | | `adguardhome` | dns.windy.lan (`/opt/adguardhome`) | — (待从 LAN 提取) | static file (pending) | | `unifi` | ubnt (`/home/windy/unifi-9`) | — (待从 LAN 提取) | static file (pending) | | `wireguard` | us4 (`/opt/wireguard`) | `ansible/templates/wireguard-compose.yml.j2` | role-rendered (inventory vars) | | `rustdesk` | hk2 (`/opt/rustdesk`) | `ansible/roles/rustdesk/templates/compose.yml.j2` | role-rendered (inventory vars) | | `mailcow` | mx2 (`/opt/mail`) | — (mailcow update generator owns it) | excluded by design | Mechanism rule: **static** `compose//compose.yml` for declarations that do not vary per host; **role-rendered j2** for declarations driven by inventory vars (image pins, relay host). One mechanism per project; do not duplicate a project in both. ## Deploying a static project ```bash cd ansible # Read-only diff + validation against the server .env (no writes) ansible-playbook playbooks/compose-deploy.yml --limit vaultwarden --check --diff # Apply: stage repo file → validate `docker compose config -q` → backup current # file → promote → `docker compose up -d` (gated) ansible-playbook playbooks/compose-deploy.yml --limit vaultwarden \ -e '{"compose_deploy_confirm": true}' ``` See [`../runbooks/ansible-operations.md`](../runbooks/ansible-operations.md). ## Adding a project 1. Sanitize the live compose so every secret is `${VAR}` from `.env` (prefer `${VAR:?missing VAR}` for required keys). 2. Commit `compose//compose.yml` + `.env.example` (key names only). 3. Add `compose_repo_project` (+ `compose_remote_file` if not `compose.yml`) to the host in `ansible/inventory/hosts.yml`, and allowlist the project in `ansible/roles/compose_deploy/defaults/main.yml`. 4. Verify with `--check --diff` (zero diff) then a gated apply.