From 5a46998689832b748507b69e22b30cd69940e5fe Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 1 Apr 2026 15:40:48 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20Secrets=20=E7=AE=A1=E7=90=86=E6=89=8B?= =?UTF-8?q?=E5=86=8A=20(ADR-035+=20=E7=B5=B1=E4=B8=80=20Secrets=20?= =?UTF-8?q?=E7=9C=9F=E7=9B=B8=E4=BE=86=E6=BA=90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 建立 docs/runbooks/SECRETS-MANAGEMENT.md: - 7 個 Gitea Secrets + 12 個 K8s Secrets 完整清單 - 更新 SOP (API + Web UI) - 一鍵狀態檢查命令 - 各 key 取得/更新指南 - 緊急狀況處理 Co-Authored-By: Claude Sonnet 4.6 --- docs/runbooks/SECRETS-MANAGEMENT.md | 147 ++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 docs/runbooks/SECRETS-MANAGEMENT.md diff --git a/docs/runbooks/SECRETS-MANAGEMENT.md b/docs/runbooks/SECRETS-MANAGEMENT.md new file mode 100644 index 000000000..b4af2dc5b --- /dev/null +++ b/docs/runbooks/SECRETS-MANAGEMENT.md @@ -0,0 +1,147 @@ +# AWOOOI Secrets 管理手冊 + +> 版本: v1.0 | 建立: 2026-04-01 Claude Code + 統帥 +> **目的**: 永不再因 Secrets 遺失導致系統故障 + +--- + +## 🔴 第一原則 + +**每個 Secret 只有一個真相來源:Gitea Secrets** +CD Pipeline 每次部署自動注入到 K8s,禁止手動 patch。 + +--- + +## 📋 完整 Secrets 清單 + +### Gitea Secrets (CD 注入 K8s) + +| Secret 名稱 | 用途 | 取得方式 | 格式 | 有效期 | +|-------------|------|----------|------|--------| +| `DEPLOY_SSH_KEY` | SSH 到 K8s 節點部署 | `cat ~/.ssh/deploy_key` (wooo@MacMini) | PEM 私鑰 | 長期 | +| `HARBOR_USERNAME` | Harbor Registry 推送 | Harbor UI → 帳號設定 | 字串 | 長期 | +| `HARBOR_PASSWORD` | Harbor Registry 推送 | Harbor UI → 帳號設定 | 字串 | 長期 | +| `TELEGRAM_BOT_TOKEN` | CD 部署通知 | @BotFather → /mybots | `{id}:AAH...` | 長期 | +| `TELEGRAM_CHAT_ID` | CD 通知接收人 | Telegram 個人 ID | 數字 | 長期 | +| `NVIDIA_API_KEY` | Nemotron LLM 仲裁 | https://build.nvidia.com → API Keys | `nvapi-...` | **可能過期** | +| `GEMINI_API_KEY` | Gemini 備援 LLM | https://aistudio.google.com/apikey | `AIzaSy...` | **可能過期** | + +### K8s Secret (awoooi-secrets) — CD 自動同步 + +| Secret Key | 用途 | 狀態 | 來源 | +|-----------|------|------|------| +| `OPENCLAW_TG_BOT_TOKEN` | API 告警發送 | ✅ | Gitea: `TELEGRAM_BOT_TOKEN` | +| `OPENCLAW_TG_CHAT_ID` | API 告警接收 | ✅ | Gitea: `TELEGRAM_CHAT_ID` | +| `NVIDIA_API_KEY` | Nemotron LLM | ✅ | Gitea: `NVIDIA_API_KEY` | +| `GEMINI_API_KEY` | Gemini 備援 | ✅ | Gitea: `GEMINI_API_KEY` | +| `DATABASE_URL` | PostgreSQL 連線 | ✅ | 手動設定 (永久) | +| `REDIS_URL` | Redis 連線 | ✅ | 手動設定 (永久) | +| `JWT_SECRET` | API 認證 | ✅ | 手動設定 (永久) | +| `WEBHOOK_HMAC_SECRET` | Alertmanager HMAC | ✅ | 手動設定 (永久) | +| `SENTRY_DSN` | 錯誤追蹤 | ✅ | 手動設定 (永久) | +| `SENTRY_AUTH_TOKEN` | Sentry API | ✅ | 手動設定 (永久) | +| `CLAUDE_API_KEY` | Claude 備援 LLM | ❌ 未設定 | 需更新 | +| `OPENCLAW_TG_USER_WHITELIST` | Telegram 白名單 | ❌ CHANGE_ME | 需更新 | + +--- + +## 🔧 Gitea Secret 更新 SOP + +```bash +# 方法一: Gitea Web UI +# http://192.168.0.110:3001/wooo/awoooi/settings/secrets + +# 方法二: Gitea API +GITEA_TOKEN="e6c9fecb1f0148939493ae0fa30407d28c91279d" +curl -X PUT "http://192.168.0.110:3001/api/v1/repos/wooo/awoooi/actions/secrets/NVIDIA_API_KEY" \ + -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"data": "nvapi-新的key值"}' +``` + +更新後,**推一個空 commit 觸發 CD 重新注入**: +```bash +git commit --allow-empty -m "chore: refresh secrets injection" && git push gitea main +``` + +--- + +## 🩺 狀態檢查命令 + +```bash +# 一鍵檢查所有 K8s Secrets 狀態 +ssh wooo@192.168.0.121 "sudo kubectl get secret awoooi-secrets -n awoooi-prod -o json" | \ + python3 -c " +import sys,json,base64 +d=json.load(sys.stdin)['data'] +for k in sorted(d.keys()): + v = base64.b64decode(d[k]).decode() + status = '❌ CHANGE_ME' if v == 'CHANGE_ME' else '❌ EMPTY' if not v else '✅' + print(f'{status} {k}') +" + +# 測試 NVIDIA API Key +ssh wooo@192.168.0.121 "NVIDIA_KEY=\$(sudo kubectl get secret awoooi-secrets -n awoooi-prod \ + -o jsonpath='{.data.NVIDIA_API_KEY}' | base64 -d) && \ + curl -s -o /dev/null -w '%{http_code}' \ + -X POST https://integrate.api.nvidia.com/v1/chat/completions \ + -H 'Authorization: Bearer '\$NVIDIA_KEY \ + -H 'Content-Type: application/json' \ + -d '{\"model\":\"nvidia/nemotron-mini-4b-instruct\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"max_tokens\":5}'" + +# 測試 Gemini API Key +ssh wooo@192.168.0.121 "GEMINI_KEY=\$(sudo kubectl get secret awoooi-secrets -n awoooi-prod \ + -o jsonpath='{.data.GEMINI_API_KEY}' | base64 -d) && \ + curl -s -o /dev/null -w '%{http_code}' \ + 'https://generativelanguage.googleapis.com/v1beta/models?key='\$GEMINI_KEY" +``` + +--- + +## 🔑 各 Secret 取得/更新指南 + +### NVIDIA_API_KEY +- **網址**: https://build.nvidia.com/explore/discover → 右上角 "Get API Key" +- **格式**: `nvapi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` +- **注意**: 免費 tier 每月有 quota,不會自動過期但可能被 revoke + +### GEMINI_API_KEY +- **網址**: https://aistudio.google.com/apikey → "Create API key" +- **格式**: `AIzaSy...` (39 字元) +- **注意**: 免費 tier 有 RPM/RPD 限制 + +### CLAUDE_API_KEY (目前未設定) +- **網址**: https://console.anthropic.com/settings/keys → "Create Key" +- **格式**: `sk-ant-api03-...` +- **注意**: 需要付費帳戶 + +### DEPLOY_SSH_KEY +- **取得**: `cat ~/.ssh/deploy_key` (在 ogt 的 MacMini 上) +- **備份位置**: 務必備份到安全位置 + +--- + +## 🚨 緊急狀況處理 + +### 情況:LLM 仲裁全部失敗 (mock_fallback) +1. 檢查 pod logs: `ssh wooo@192.168.0.121 "sudo kubectl logs deployment/awoooi-api -n awoooi-prod --since=5m | grep ai_provider_failed"` +2. 如果是 timeout → NVIDIA free tier 過載,等待即可 +3. 如果是 auth error → 更新對應 Gitea Secret,觸發 CD 重注入 + +### 情況:CD Pipeline 無法部署 +1. 確認所有 Gitea Secrets 都已設定: `http://192.168.0.110:3001/wooo/awoooi/settings/secrets` +2. 手動 trigger: Gitea UI → Actions → "CD Pipeline" → "Run workflow" + +### 情況:Telegram 通知不來 +- 確認 `TELEGRAM_BOT_TOKEN` 在 Gitea secrets 正確 +- 測試: `curl -s "https://api.telegram.org/bot{TOKEN}/getMe"` +- 詳見: `feedback_telegram_token_disaster.md` + +--- + +## 📅 定期維護 (月度) + +- [ ] 檢查 NVIDIA API Key 用量: https://build.nvidia.com +- [ ] 檢查 Gemini API 配額: https://aistudio.google.com +- [ ] 執行 `狀態檢查命令` 確認全部 ✅ +- [ ] 確認 CI/CD 最近 30 天無 secrets 相關錯誤