baa-conductor

git clone 

baa-conductor / coordination / tasks / done
im_wower  ·  2026-03-22

T-028-real-rollout.md

  1---
  2task_id: T-028
  3title: 真实 Cloudflare / VPS 上线执行
  4status: done
  5branch: feat/T-028-real-rollout-v2
  6repo: /Users/george/code/baa-conductor
  7base_ref: main@be74d58
  8depends_on:
  9  - T-018
 10  - T-019
 11  - T-020
 12  - T-021
 13  - T-022
 14  - T-023
 15  - T-024
 16  - T-025
 17  - T-027
 18write_scope:
 19  - docs/ops/**
 20  - docs/runtime/**
 21  - ops/nginx/**
 22  - apps/control-api-worker/**
 23  - scripts/ops/**
 24  - scripts/runtime/**
 25updated_at: 2026-03-22T03:32:57+0800
 26---
 27
 28# T-028 真实 Cloudflare / VPS 上线执行
 29
 30## 目标
 31
 32把当前已经完成的本地联调骨架真正部署到 Cloudflare、VPS、mini、mac,并形成一套可复查的上线记录。
 33
 34## 本任务包含
 35
 36- 使用当前 Cloudflare token / wrangler / D1 配置完成 control-api 真实部署
 37- 使用当前 DNS 脚本或命令把二级域名切到预期入口
 38- 在 VPS 上落地 Nginx 配置并完成校验 / reload
 39- 在 mini / mac 上落地 runtime 目录、launchd 安装与基础探活
 40- 把真实环境 URL、端口、角色、检查结果写回文档与任务卡
 41
 42## 本任务不包含
 43
 44- 重写应用架构
 45- 修改 `baa-firefox` 仓库
 46- 长时间稳定性结论
 47
 48## 建议起始文件
 49
 50- `docs/ops/README.md`
 51- `docs/runtime/README.md`
 52- `ops/nginx/baa-conductor.conf`
 53- `apps/control-api-worker/wrangler.jsonc`
 54- `scripts/ops/cloudflare-dns-plan.sh`
 55- `scripts/runtime/install-launchd.sh`
 56
 57## 交付物
 58
 59- 真实可访问的 control-api / status-api / conductor 入口
 60- VPS、mini、mac 的上线执行记录
 61- 更新后的运维文档与上线注意事项
 62
 63## 验收
 64
 65- 能说明 control-api 的真实外网入口和至少一个内网入口
 66- 能说明 VPS 上 Nginx 已完成校验与 reload
 67- 能说明 mini / mac 节点至少完成一次 on-node 探活
 68- `git diff --check`
 69
 70## 更新要求
 71
 72完成时更新 frontmatter 的:
 73
 74- `status`
 75- `base_ref`
 76- `updated_at`
 77
 78并补充下面这些内容:
 79
 80## files_changed
 81
 82- `coordination/tasks/T-028-real-rollout.md`
 83- `scripts/runtime/check-node.sh`
 84- `docs/runtime/launchd.md`
 85- `docs/runtime/node-verification.md`
 86- `docs/runtime/real-rollout-2026-03-22.md`
 87- `docs/ops/README.md`
 88- `docs/ops/real-rollout-2026-03-22.md`
 89
 90## commands_run
 91
 92- 本地干净 worktree:`git -C /Users/george/code/baa-conductor-main-merge worktree add -b feat/T-028-real-rollout-v2 /Users/george/code/baa-conductor-T028-v2 be74d585251f20ff5bd74ae17f6f6b011ff0bd34`
 93- 本地新 worktree 首命令:`cd /Users/george/code/baa-conductor-T028-v2 && npx --yes pnpm install`
 94- 本地构建:`cd /Users/george/code/baa-conductor-T028-v2 && npx --yes pnpm -r build`
 95- `mini` 本机:`./scripts/runtime/bootstrap.sh --repo-dir /Users/george/code/baa-conductor-T028-v2`
 96- `mini` 本机:`set -a; source /Users/george/.config/baa-conductor/control-api-worker.secrets.env; set +a; ./scripts/runtime/install-launchd.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mini --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.71.210.78:4317 --local-api-allowed-hosts 100.71.210.78 --status-api-host 100.71.210.78`
 97- `mini` 本机:`./scripts/runtime/check-launchd.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mini --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.71.210.78:4317 --local-api-allowed-hosts 100.71.210.78 --status-api-host 100.71.210.78`
 98- `mini` 本机:`./scripts/runtime/reload-launchd.sh --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents`
 99- `mini` 本机:`./scripts/runtime/check-node.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mini --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.71.210.78:4317 --local-api-allowed-hosts 100.71.210.78 --status-api-base http://100.71.210.78:4318 --status-api-host 100.71.210.78 --expected-rolez leader --check-loaded`
100- 本地到双节点探活:`curl http://100.71.210.78:4317/healthz`、`curl http://100.71.210.78:4318/healthz`、`curl http://100.112.239.13:4317/healthz`、`curl http://100.112.239.13:4318/healthz`
101- 同步到 `mac`:`rsync -az --delete --exclude '.git' --exclude 'node_modules' /Users/george/code/baa-conductor-T028-v2/ george@100.112.239.13:/Users/george/code/baa-conductor-T028-v2/`
102- `mac` 远端:`cd /Users/george/code/baa-conductor-T028-v2 && npx --yes pnpm install`
103- `mac` 远端:`cd /Users/george/code/baa-conductor-T028-v2 && npx --yes pnpm -r build`
104- `mac` 远端:`./scripts/runtime/bootstrap.sh --repo-dir /Users/george/code/baa-conductor-T028-v2`
105- `mac` 远端:`set -a; source /Users/george/.config/baa-conductor/control-api-worker.secrets.env; set +a; ./scripts/runtime/install-launchd.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mac --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.112.239.13:4317 --local-api-allowed-hosts 100.112.239.13 --status-api-host 100.112.239.13`
106- `mac` 远端:`./scripts/runtime/check-launchd.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mac --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.112.239.13:4317 --local-api-allowed-hosts 100.112.239.13 --status-api-host 100.112.239.13`
107- `mac` 远端:`./scripts/runtime/reload-launchd.sh --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents`
108- `mac` 远端:`./scripts/runtime/check-node.sh --repo-dir /Users/george/code/baa-conductor-T028-v2 --node mac --service conductor --service status-api --install-dir /Users/george/Library/LaunchAgents --local-api-base http://100.112.239.13:4317 --local-api-allowed-hosts 100.112.239.13 --status-api-base http://100.112.239.13:4318 --status-api-host 100.112.239.13 --expected-rolez standby --check-loaded`
109- 生成 DNS / Nginx 计划:`scripts/ops/cloudflare-dns-plan.sh --env /Users/george/.config/baa-conductor/ops.env --fetch-current --emit-shell .tmp/ops/cloudflare-dns-preview.sh --output .tmp/ops/cloudflare-dns-plan.json`、`scripts/ops/nginx-sync-plan.sh --env /Users/george/.config/baa-conductor/ops.env --bundle-dir .tmp/ops/baa-conductor-nginx`
110- VPS 基线:`ssh -p 2222 root@192.210.137.113 'hostname; tailscale ip -4; nginx -v; ss -ltnp | grep -E ":(80|443|2222)\\b"'`
111- VPS upstream 探活:`ssh -p 2222 root@192.210.137.113 'curl http://100.71.210.78:4317/healthz && curl http://100.112.239.13:4317/healthz'`
112- VPS status-api 探活:`ssh -p 2222 root@192.210.137.113 'curl http://100.71.210.78:4318/healthz && curl http://100.112.239.13:4318/healthz'`
113- VPS 依赖:`ssh -p 2222 root@192.210.137.113 'apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y apache2-utils python3-certbot-dns-cloudflare'`
114- VPS Cloudflare DNS challenge 凭据:`printf 'dns_cloudflare_api_token = %s\n' "$CLOUDFLARE_API_TOKEN" | ssh -p 2222 root@192.210.137.113 'install -d -m 700 /root/.secrets/certbot && cat > /root/.secrets/certbot/cloudflare.ini && chmod 600 /root/.secrets/certbot/cloudflare.ini'`
115- VPS 三张证书:三次 `ssh -p 2222 root@192.210.137.113 'certbot certonly --non-interactive --agree-tos --register-unsafely-without-email --preferred-challenges dns-01 --authenticator dns-cloudflare --dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini --dns-cloudflare-propagation-seconds 30 --cert-name <host> -d <host>'`
116- 本地直连域名密码文件:`/Users/george/.config/baa-conductor/direct-node-basic-auth.env`
117- VPS htpasswd:`printf '%s\n' "$BAA_DIRECT_NODE_BASIC_AUTH_PASSWORD" | ssh -p 2222 root@192.210.137.113 "htpasswd -i -c /etc/nginx/.htpasswd-baa-conductor conductor-ops && chmod 640 /etc/nginx/.htpasswd-baa-conductor && chown root:www-data /etc/nginx/.htpasswd-baa-conductor"`
118- Nginx bundle 同步:`rsync -az -e 'ssh -p 2222' /Users/george/code/baa-conductor-T028-v2/.tmp/ops/baa-conductor-nginx/ root@192.210.137.113:/tmp/baa-conductor-nginx/`
119- VPS 安装 / 校验 / reload:`ssh -p 2222 root@192.210.137.113 'cd /tmp/baa-conductor-nginx && ./deploy-on-vps.sh'`、`ssh -p 2222 root@192.210.137.113 'cd /tmp/baa-conductor-nginx && ./deploy-on-vps.sh --reload'`
120- Cloudflare DNS 初次切换:`bash /Users/george/code/baa-conductor-T028-v2/.tmp/ops/cloudflare-dns-preview.sh`
121- Cloudflare DNS 改为 DNS-only:`scripts/ops/cloudflare-dns-plan.sh --env /Users/george/.config/baa-conductor/ops.env --fetch-current --emit-shell .tmp/ops/cloudflare-dns-proxy-off.sh --output .tmp/ops/cloudflare-dns-plan-proxy-off.json`、`bash /Users/george/code/baa-conductor-T028-v2/.tmp/ops/cloudflare-dns-proxy-off.sh`
122- 验收:`curl -H "Authorization: Bearer $CONTROL_API_OPS_ADMIN_TOKEN" https://control-api.makefile.so/v1/system/state`、`curl --resolve conductor.makefile.so:443:192.210.137.113 https://conductor.makefile.so/healthz`、`curl --resolve conductor.makefile.so:443:192.210.137.113 https://conductor.makefile.so/rolez`、`curl -u conductor-ops:... --resolve mini-conductor.makefile.so:443:192.210.137.113 https://mini-conductor.makefile.so/rolez`、`curl -u conductor-ops:... --resolve mac-conductor.makefile.so:443:192.210.137.113 https://mac-conductor.makefile.so/rolez`
123- 收尾校验:`bash -n scripts/ops/*.sh scripts/runtime/*.sh`、`git diff --check`
124- 提交与推送:`git commit -m "Complete T-028 real rollout"`、`git push -u origin feat/T-028-real-rollout-v2`
125
126## result
127
128- `mini``mac` 已从旧的 loopback-only 配置切到各自的 Tailscale `100.x` 监听:`mini 100.71.210.78:4317/4318`、`mac 100.112.239.13:4317/4318`,两台节点都通过了真实 `check-node.sh --check-loaded`129- VPS `racknerd-ff37952` 已真实打通到两台节点的 `4317``4318`;`curl http://100.71.210.78:4317/healthz`、`curl http://100.112.239.13:4317/healthz` 以及对应 `4318` 探针都返回 `ok`130- VPS 已安装 `apache2-utils``python3-certbot-dns-cloudflare`,并通过 Cloudflare DNS challenge 签发三张证书:`conductor.makefile.so`、`mini-conductor.makefile.so`、`mac-conductor.makefile.so`,到期日均为 `2026-06-19`131- `/etc/nginx/.htpasswd-baa-conductor` 已创建,仓库生成的 Nginx bundle 已同步到 VPS,`./deploy-on-vps.sh` 与 `./deploy-on-vps.sh --reload` 都真实通过,`nginx -t` 成功。
132- Cloudflare DNS 已真实切换。三条 conductor 记录最终状态为 `A -> 192.210.137.113 proxied=false`;Cloudflare API 回读计划为 `noop`,权威 NS `giancarlo.ns.cloudflare.com` 对三个 host 都返回 `192.210.137.113`133- 公网验收闭环完成:`https://control-api.makefile.so/v1/system/state` 返回 `ok=true``holder_id=mini-main`;`conductor.makefile.so` 入口返回 `healthz=ok`、`rolez=leader`;`mini-conductor.makefile.so` / `mac-conductor.makefile.so` 未认证为 `401`,带 Basic Auth 后分别返回 `leader` / `standby`134- 为了让 Tailscale rollout 的静态校验真实可用,本分支顺手修复了 `scripts/runtime/check-node.sh`,让它把 `--local-api-allowed-hosts``--status-api-host` 正确传给 `check-launchd.sh`135- 分支已推送:`origin/feat/T-028-real-rollout-v2`
136
137## risks
138
139- 这三条 conductor DNS 记录当前是 `proxied=false`。原因不是源站问题,而是当前 Cloudflare token 只有 DNS 权限,无法把 zone SSL mode 从疑似 `Flexible` 改到 `Full` / `Full (strict)`;若重新开代理,公网会回到 `301 Location: https://$host$request_uri` 循环。
140- `mini``mac` 运行时现在都指向 `/Users/george/code/baa-conductor-T028-v2`,不是文档默认的 `/Users/george/code/baa-conductor`;如果后续切回 canonical 路径,需要重新渲染并 reload launchd 副本。
141- `mini/mac` 直连域名的 Basic Auth 密码只保存在仓库外的 `/Users/george/.config/baa-conductor/direct-node-basic-auth.env` 和 VPS htpasswd 文件里,没有进入 repo;交接时需要确保整合者知道这份私有文件的位置。
142
143## next_handoff
144
145- 如需把 `conductor.makefile.so`、`mini-conductor.makefile.so`、`mac-conductor.makefile.so` 重新放回 Cloudflare 代理,先准备带 zone settings 权限的 token,把 `makefile.so` 的 SSL mode 调到 `Full``Full (strict)`,再把私有 inventory `/Users/george/.config/baa-conductor/ops.env` 里的 `BAA_CF_PROXY_*` 改回 `true` 并重新执行 DNS 计划脚本。
146- 观察三张证书的首次自动续期是否正常;若要显式演练,可在 VPS 上执行 `certbot renew --dry-run`147- 后续若进入 `T-029`,就直接基于当前 `mini leader / mac standby / VPS ingress` 现网做 smoke、切换与长时间稳定性回归,不需要再重新铺节点监听或公网入口。
148
149开始时建议直接把 `status` 改为 `in_progress`150
151做完并推送后:
152
153- 如果等待整合,改为 `review`
154- 如果确认结束,改为 `done`