Files
vps/compose
windyboy 906fb4a759 VPS-78: CSG day 费用口径统一 + 断档自愈 (v5) + v3/v5 迁移脚本入库
- compose/pgdb/csg-snapshot-v3.sql: 补提交(此前只存在于工作区,未入 git)
- compose/pgdb/csg-snapshot-v5.sql: 新增
  · csg_ladder_cost_raw() 无舍入阶梯费用助手
  · csg_daily_snapshot() v5: day 费用改累积边际差分 + round(...,2);
    p_month 上移 + 跨月守卫;日期与用量同源 latest_day_kwh
  · 一次性归一历史 day cost(UPDATE 3 行,总差 -0.01)
  · csg_backfill_missing_days() + job 1011(insert-only 断档自愈)
- runbooks/pgdb-health.md: 新增 check 9 CSG 归档新鲜度
- hosts/pgdb.md: v5 事实 + Known issues 2026-09-22
2026-09-22 08:45:45 +08:00
..

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 -qup -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/<project>/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

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.

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/<project>/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.