這份是 living 檔:每棒就地 Edit,只描述「此刻」。歷史脈絡看同資料夾的
FR-184-LOG.md。
| 項目 | 值 |
|---|---|
| 最後更新 | 2026-11-08 17:40(首腦第 2 棒交出:T3 完成、1.30.1 線上更新成功、VM 升 4 核 16 GB、Terraform 導讀寫好) |
| branch | BE feature/FR-172;infra feature/FR-172(clone 時帶入,不切);兩邊都已 push 到 origin(11-08) |
| 母案卡 | CM-3643 https://app.notion.com/p/FR-184-GCP-VM-Terraform-6-4-411346da4cd0810fa529df7b81d720d1 |
| 下一張要做的卡 | 下一棒=Terraform Q&A:決策者要能回答 PM 的問題,首腦陪讀 infra repo、答問題、需要時補導讀。之後才是 P1 → O1 → V1 |
| 卡片狀態 | T1 CM-3644 驗收通過待確認;T2 CM-3645 工作坊上仍是 In progress(實際已由首腦做完並回寫,見 §2-8);F1 CM-3650、T4 CM-3651 取消(卡上已寫理由,等決策者在狀態頁按「這張不用做」);其餘 Not started |
| 接手前必讀 | §0 讀序 |
install.sh 裝系統(程式零改動),自己營運多租戶的雲端版給客戶試用。換雲只換 Terraform 的 module,安裝腳本不動。docs/terraform-walkthrough.md,含 PM 可能問的九題),下一棒以它為底陪決策者讀、答問題、答不出或文件沒寫到的就查程式碼補進導讀。~/Projects/Billows/Audit-Manager/guidant-ai-infra/docs/terraform-walkthrough.md(導讀)全讀,再讀 modules/platform-gcp/main.tf、budget.tf、scripts/startup.sh、envs/gcp-prod/*.tf 實際程式——答問題以程式碼為準,導讀與程式不一致時改導讀docs/features/FR-184-2611-gcp-vm-deployment/design.md 全讀(§3 決策、§5.2 裝機五步、§7 拆分表、§8 驗收、§10 風險)python3 /Users/chouraymond/Projects/Jedicogy/agent-workshop/scripts/notion_case.py get CM-3646(T3 卡,卡尾有三段首腦補充:1.30.0、AI 金鑰走 install.conf、序號裝完才貼)~/Projects/Billows/Audit-Manager/guidant-ai-infra/docs/runbook.md(機器座標、防火牆驗法)FR-184-LOG.md 最後一個 blockDEPLOYMENT_MODE=host 而不是 saas?prevent_destroy/deletion_protection,為什麼是它們?GCP(專案 guidant-ai-cloud-514012,帳號 company.jedicotech@gmail.com,gcloud config 名 guidantai)
| 項目 | 狀態 |
|---|---|
VM guidant-ai-vm |
跑著,asia-east1-b,e2-standard-4(4 核 16 GB)+8 GB swap,Ubuntu 24.04,vTPM(11-08 17:05 由 2 核 8 GB 升級,infra 5fe59da) |
| 固定 IP | 35.194.213.124 |
| 開機腳本 | exit 0:swap、資料碟 /dev/sdb bind 到 /srv/guidant-ai//var/lib/docker//var/lib/containerd、docker 29.9.3+compose v5.7.0、Ops Agent active、/dev/tpm0 |
| 防火牆 | 直打 IP 的 80/443 逾時;5432、20202 被擋;22 只放 125.228.154.97(公司線,188 與決策者 Mac 同一個) |
| ssh | ssh jedi@35.194.213.124(首腦 Mac 與 188 的公鑰都在) |
| 系統 | 1.30.1(11-08 13:53 裝 1.30.0、16:45~16:57 更新中心線上升到 1.30.1),9 容器 healthy;Cloudflare Origin 憑證、UPDATE_SITE_URL、Turnstile 兩把 key 升級後都保留;安裝紀錄 /srv/guidant-ai/log/install-20261108-134535.log |
| Terraform | state 在 gs://guidant-ai-cloud-514012-tfstate/gcp-prod/,24 個資源;本機 envs/gcp-prod/terraform.tfvars(不入版控)已填真值 |
| 預算告警 | 每月 6,500 TWD(約 200 美元;帳單帳戶是 TWD 計價,預算幣別必須相同),50/90/100%與預測超標寄信,只通知不停機;infra 724e9c0、modules/platform-gcp/budget.tf |
Secret Manager(18 個,名稱都是 guidant-*)
| secret | 誰放的 | 用途 |
|---|---|---|
| db-admin、db-app、redis、redis-api、redis-socketio、redis-worker | 決策者 | 裝機自帶密碼(12 字元英數) |
| root-admin | 決策者 | GUIDANT_ROOT_ADMIN_PASSWORD,非互動安裝必填 |
| anthropic | 決策者 | GUIDANT_AI_KEY_ANTHROPIC,install.conf 填,裝機時加密進 DB |
| smtp | 決策者 | Brevo SMTP key,備查;實際由決策者裝完在後台填 |
| turnstile-secret | 決策者 | install.conf 的 GUIDANT_TURNSTILE_SECRET_KEY |
| origin-cert、origin-key | 決策者 | Cloudflare Origin 憑證與私鑰,已驗配對、SAN 只有 guidant-ai.jedicotech.com、到 2041 |
VM service account 只有前六個的讀取權(Terraform 綁的)。其餘首腦從 Mac 讀出再送上 VM。 11-08 裝機後:redis-api/redis-socketio/redis-worker 已用 installer 產的值加新版本(舊版本是決策者給的、裝機沒用到);另新建 6 個備查(label source=installer,VM 不可讀、不在 Terraform 管理):guidant-s3-access-key、guidant-s3-secret-key、guidant-classifier-token、guidant-bugsink-db、guidant-jwt-secret、guidant-app-encryption-key。guidant-db-app 決策者 11-08 換過一版(不可與 db-admin 相同)。
Cloudflare(jedicotech.com,權杖與 Zone ID 在 infra .env,權杖只有 DNS 編輯權)
guidant-ai.jedicotech.com → 35.194.213.124,橘雲代理,已解析到 Cloudflare,連網址回 521(正常,系統未裝)guidant-ai.jedicotech.com 另有 Configuration Rule 設「嚴格」(決策者 11-08 設,運算式 (http.host eq "guidant-ai.jedicotech.com"))0x4AAAAAAF3nyyICSRHDlH3k(公開值)noreply@jedicotech.com 驗證通過、四筆 DNS 已加安裝包:188 /opt/guidant-ai-be/.build/bundle/guidant-ai-1.30.0.tar.gz,11-08 13:09 決策者重出(sha256 6b0f806f…),含 Turnstile 改動(開包核過 install.sh/compose/fe 的 nginx 與 entrypoint/Login.js)。這包有兩個問題:vulndb 檔是 600(457f2964a 已修出包腳本,包本身未重出)、沒帶 DEFAULT_UPDATE_SITE_URL(手跑出包沒設這個環境變數;CI 會帶)。VM 上已手動處理,家目錄的包已刪。
commits
| repo | commits |
|---|---|
| BE | (已 push)db989fcc3 討論稿、5ac49c456 設計 v1.0、0209f3ea0 網址、ea6095af0 開卡、f7a336878 secret 改讀既有、5acafb2ce Turnstile 兩卡、bf880a7cf site key、f16174dcf 架構圖、1af8bb821 架構圖補 Agent、5a0f17ab0 交接、811a9ba44 memory、a108ab505 Turnstile 有填 key 就開(主產品)、本棒文件 commit |
| FE | (已 push)f95a85b8 登入頁問後端決定 Turnstile、前門 CSP 依 site key 放行 |
| infra | (已 push)8194fb0 開機腳本補時區與 tpm2-tools、724e9c0 預算告警;(新建遠端分支)7ec4f3a 骨架、78e8255 專案 ID、6775501 工作坊登記、2227c0d 網址、224b744 對齊 8 GB/host、93e0287+31dc505 T1(小弟,已合回)、08c67b6 T2 runbook |
machine_type 重 apply 升級)(11-07)DEPLOYMENT_MODE=host:saas 兩個既有缺口(common/authz/tenant_hq.py 總部判定讓郵件/LDAP/安全政策三頁消失、product_update_flow.py:193 只認 host 照)另開 FR(11-07)install.conf 填 GUIDANT_TURNSTILE_SITE_KEY/GUIDANT_TURNSTILE_SECRET_KEY(寫進 compose .env,升級保留)。F1、T4 取消(11-08)。admin 後台設定之後另做(11-08).env(11-07)guidant-ai.jedicotech.com;SSL 只對這個主機名稱設嚴格,不動全網域(11-08)01fb1289e),決策者裁撤回(b0cc9b321,理由:設定檔開關沒人記得設、1.30.0 已出版不含開關),改由 Agent 端自己判斷(CM-3654):主系統憑證能被系統信任庫驗過(含 Cloudflare 公開憑證)就不比對指紋。所以雲端版 guidant.env 不用加任何指紋開關。CM-3654 的修正(evidence-agent 16ca2b5、bf262cf)已含在 Agent 1.7.0 正式版(11-08 已發),雲端版現在就能接 Agent;判準是「系統信任庫驗得過」不是寫死 Cloudflare,換其他 CDN/公開 CA 都不用改。CM-3654 卡在修正待驗證,待真機接一台 Agent 驗收guidant.env 不加 PRODUCT_UPDATE_ALLOW_SAME_VERSION🔴 下一個動作:Terraform Q&A(決策者發令再開始)。首腦陪決策者讀 infra repo,答 PM 會問的問題。
做法建議:
writing-technical-docs skill「系統說明」骨架,或 Artifact 一頁)Q&A 之後才是:P1(救火用直接部署,批 3,可派小弟)→ O1(備份與災難復原,批 4,開工前先跟決策者定災難復原做法)→ V1(驗收,批 5)。
1.30.1 線上更新實績(11-08 16:45~16:57):八步全過(自我替換 → 預檢 → 收單 → 複製資料庫 123 MB/11 秒 → 複本套新版 → 健康檢查 → 換接 → 清理)。健康檢查在 Turnstile 開著時通過(a108ab505 的放寬生效)。升完 Turnstile、UPDATE_SITE_URL、Origin 憑證都在。
VM 升規格實績(11-08 17:00~17:06):guidantai stop → apply(約 2 分 45 秒)→ 開機腳本 exit 0、vTPM 解封成功 → guidantai start 9 容器 healthy。指紋不變、License 不用重開。前後對照:VM 內 API 80~130 ms → 17~24 ms;CPU pressure 28% → 4%;可用記憶體 1.7 GB → 9.4 GB。注意:停過服務再改規格,重開機後要手動 guidantai start(容器停下的狀態會保留)。
裝機時實際走過的步驟與坑(下次重建 VM 照這個):
install.conf 在 Mac 從 Secret Manager 組(600,單引號包值),scp 上 VM;裝完 shred -u--check-only;主機時區由開機腳本設 Asia/Taipei(infra 8194fb0)8194fb0);主產品 --check-only 也會照實報錯(b3b21a950)chmod 644 後 sudo GUIDANT_REUSE_EXISTING_INSTALL=1 ./install.sh --config install.conf 重跑(沿用已產的密碼)install -m 600 -o 101 -g 101 放 key、sudo guidantai restart guidant-feUPDATE_SITE_URL:用 sudo EDITOR=<追加一行的腳本> guidantai config edit guidant.env 補 UPDATE_SITE_URL=https://guidantai-update.jedicotech.com,再 sudo guidantai start之後順序:P1 管線 gcp-prod(救火用,可派小弟,批 3)→ O1 備份告警(批 4,開工前先跟決策者定災難復原做法)→ V1 驗收(批 5)。
⚠️ 這節是建議清單,不是執行授權。接手方盤點完即停,等決策者發令。
/etc/machine-id 在系統碟;install.sh 提示寫「換機器需走 --restore」但沒有這個選項(T1 小弟實查 install.sh:770~774)。O1 開工前要跟決策者定457f2964a+9086e8ad8(改接既有 dist_perms.sh 整包正規化+斷言,已 push),1.30.1 帶上。暫時解法:chmod 644 後 GUIDANT_REUSE_EXISTING_INSTALL=1 重跑b3b21a950 讓 --check-only 與正式安裝共用 OS 判斷,24.04 上檢查就會照實報錯;infra 8194fb0 開機腳本預裝 tpm2-tools 並設時區(已 apply、VM 上重跑驗過)。重建 VM 只剩 Origin 憑證與 188 known_hosts 要手動(runbook「重建 VM 後要手動補的」)*),所有租戶共用。host 模式下安裝精靈建的 Billows 被 common/authz/tenant_hq.py 判為總部,其管理員能改全站寄信/LDAP/登入政策。Billows 留給自家用,外部試用客戶另開租戶;根治在 saas FRhas_secret: false 被存回 DB:secret 欄有值(加密、長度 204)、寄信正常,has_secret 是讀取時算的旗標卻被畫面原樣存回。不影響使用,另開小卡STORAGE_CONFIG,新租戶複製 root(SeaweedFS、同一個 bucket guidant-ai,檔名時間+uuid 不撞名,歸屬靠 DB 紀錄+RLS);租戶可改指向自己的 Agent(檔留在客戶內網,雲端只留參照)。compliance.remote_agents 有 RLS 但沒 FORCE、INSERT policy 無條件(註冊 token 綁租戶,實務上擋得住),交 Agent 資安那條線確認83556a06(CM-3655,另一 session)已讓前門只信 Cloudflare IP 範圍送來的真實 IP,1.30.0 起帶上,未在雲端實測稽核紀錄/assets/*(檔名帶雜湊)Cloudflare 已快取(預設 4 小時);theme-init.js、layout/ 主題檔名固定也被快取 4 小時,前端改主題時升級後最多 4 小時不生效。可改前門 nginx 分檔種設 Cache-Control(雜湊檔 1 年 immutable、固定檔名 no-cache),屬產品改動。決策者 11-08 裁:先不動,看客戶反應gcloud config configurations list # guidantai 要 active
gcloud billing projects describe guidant-ai-cloud-514012 --format="value(billingEnabled)" # True
gcloud secrets list --project=guidant-ai-cloud-514012 --format="value(name)" | wc -l # 18
ssh -o ConnectTimeout=8 jedi@35.194.213.124 'free -g | sed -n 2,3p; df -h /srv/guidant-ai | tail -1; ls /srv/guidant-ai'
curl -s -o /dev/null -w "%{http_code}\n" -m 15 https://guidant-ai.jedicotech.com/ # 200
curl -s -m 15 https://guidant-ai.jedicotech.com/api/1.0/setup/status # turnstile.enabled true
ssh jedi@35.194.213.124 'sudo guidantai status | grep -c healthy' # 9
cd ~/Projects/Billows/Audit-Manager/guidant-ai-infra/envs/gcp-prod && terraform plan -detailed-exitcode >/dev/null; echo $? # 0=無漂移| 東西 | 在哪 |
|---|---|
| infra repo | ~/Projects/Billows/Audit-Manager/guidant-ai-infra(GitLab auditmanager/guidant-ai-infra);導讀 docs/terraform-walkthrough.md |
| Terraform 初始化 | terraform init -backend-config="bucket=guidant-ai-cloud-514012-tfstate" |
| Cloudflare 權杖 | infra .env CLOUDFLARE_API_TOKEN、CLOUDFLARE_ZONE_ID(600、不入版控) |
| 安裝包 | 188 /opt/guidant-ai-be/.build/bundle/ |
| installer 原始碼 | BE scripts/installer/install.sh、install.conf.example |
| 設計站 | BE docs/features/FR-184-2611-gcp-vm-deployment/(index.html 雙擊可開) |
| 架構圖 | 同上 diagrams/cloud-architecture.png,圖源 cloud_architecture.py(venv 要裝 diagrams 0.25.1) |
| 工作坊 | http://127.0.0.1:7777;工作坊 46 暫停中 |
docker compose up -d 必帶 service 名feedback_brain_handson_cards_open_as_paused_not_empty_model)K8s;saas 模式;AWS module;多租戶自助註冊;高可用;Agent 資安(另一個 session);Cloudflare DNS 收進 Terraform。
請接手 FR-184(主系統上 GCP),這一棒要陪我做 Terraform Q&A(PM 會問)。先讀 docs/features/FR-184-2611-gcp-vm-deployment/handoff/FR-184-STATE.md,照 §0 讀序讀完(含 infra repo 的 docs/terraform-walkthrough.md 與實際 .tf 檔)、答 §0.4 冷接自檢,再跑 §5 pre-flight。
讀取與盤點完成後不做任何事——不派工、不跑測試、不改檔、不 ssh 上 VM 動手、不 terraform apply,回報自檢答案與現況後等我下指令才開始作業。