- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml) - 部署模式: rsync Python 檔案至 188 → docker restart (volume mount) - Dockerfile/requirements 變動時自動重建 Docker image - 部署通知: Telegram (開始/成功/失敗) - 健康檢查: https://mo.wooo.work/health (最多 5 次重試) - 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
188 KiB
EwoooC — Claude 專案記憶(原 MOMO Pro System)
此檔案供 Claude Code 自動讀取,記錄專案的關鍵資訊與待辦事項。 專案正式名稱:EwoooC(ADR-006,2026-04-18 決策) 範圍:本目錄唯一範圍為
momo-pro-system,不含 AWOOOI / WOOO AIOps SaaS。
🏛️ 第零章:遊戲規則憲法(Claude Code 官方規範 — 2026-04-18 訂立)
這是本系統的元憲法。所有 AI 助手(Claude / Antigravity)在任何 Session 開始前必須先讀此章。
📐 記憶架構分層(四層缺一不可)
| 層次 | 位置 | 用途 | 生命週期 |
|---|---|---|---|
| Memory(持久記憶) | ~/.claude/projects/.../memory/*.md |
統帥偏好、技術決策、協作 context | 永久,跨 Session |
| ADR(架構決策記錄) | docs/adr/ADR-XXX-*.md |
重大架構決策,含背景/替代方案/後果 | 永久,只增不刪 |
| SOT(單一事實來源) | docs/AI_INTELLIGENCE_MODULE_SOT.md |
當前 AI 模組架構狀態(可更新) | 隨架構演進 |
| Skills(執行流程) | .claude/skills/*.py |
Claude 執行複雜任務的 SOP checklist | 隨流程成熟迭代 |
📋 失憶防範三大鐵律(絕對禁止違反)
鐵律一:每次決策必沉澱
- ✅ 任何架構決策 → 立刻建
ADR-XXX.md+ 更新docs/adr/README.md - ✅ 任何統帥偏好/風格 → 立刻寫入
memory/user_profile.md或新 memory 文件 - ✅ 任何技術債/待辦 → 立刻寫入
memory/project_tech_debt_backlog.md - ❌ 禁止:口頭決定不留文字記錄(下個 Session 必失憶)
鐵律二:CLAUDE.md 是憲法主幹
- ✅ 每次 Session 開始,先讀 CLAUDE.md → memory/ → 相關 ADR
- ✅ 重大架構章節必須同步更新到 CLAUDE.md(SOT 章節)
- ✅ 新憲法條款必須更新 CONSTITUTION.md
- ❌ 禁止:依賴 Claude 對話 Session 記憶(context window 有截斷)
鐵律三:範圍邊界
- ✅ 本 CLAUDE.md 範圍 = Momo Pro System(EwoooC)唯一
- ❌ 禁止:將 AWOOOI / WOOO AIOps SaaS 的決策混入本文件
- ❌ 禁止:跨專案邊界做架構決策
🔄 Session 開始 SOP(每次 Claude 啟動必做)
1. 讀 CLAUDE.md 頭部(此章 + 環境章)
2. 讀 memory/MEMORY.md 索引 → 依需求讀具體 memory
3. 讀 docs/adr/README.md 索引 → 依任務讀相關 ADR
4. 確認當前任務屬於哪個 Agent 層(Hermes/NemoTron/OpenClaw)
5. 確認任務結束後需更新哪些記憶層
📝 記憶更新 SOP(每次 Session 結束前必做)
□ 有架構決策?→ 新建或更新 docs/adr/ADR-XXX.md + README.md 索引
□ 有統帥偏好/回饋?→ 更新 memory/user_profile.md 或 feedback_*.md
□ 有技術債?→ 更新 memory/project_tech_debt_backlog.md
□ 有 SOT 變更?→ 更新 docs/AI_INTELLIGENCE_MODULE_SOT.md
□ 有憲法新條款?→ 更新 CONSTITUTION.md + 本 CLAUDE.md
□ 有技能流程變更?→ 更新 .claude/skills/ 對應 skill 文件
□ 更新 memory/MEMORY.md 索引(加入新 memory 文件連結)
專案概覽
| 項目 | 說明 |
|---|---|
| 專案名稱 | EwoooC(原 MOMO Pro System,WOOO TECH) |
| 技術棧 | Flask (gunicorn) + PostgreSQL (pgvector) + Docker Compose V12.0 |
| 主要功能 | 商品看板、每日業績報表、廠商缺貨通知、EDM 爬蟲、AI 知識庫(KM) |
| 正式運行主機 | ollama@192.168.0.188(Docker Compose,非 K8s) |
| 對外域名 | mo.wooo.work / momo.wooo.work(皆透過 110 VM Nginx 反向代理) |
🌐 環境架構總覽(2026-04-19 依 SSH 實地審計重寫,見 ADR-008)
重要: 先前文件誤記為「K3s / kubectl / 192.168.0.110 運行應用」。實地審計 (2026-04-18) 確認 EwoooC 從未遷移到 K8s,188 始終是 Docker Compose 架構。本章以實際現況為準。
| 主機 | 角色 | 承載內容 |
|---|---|---|
192.168.0.188 (ollama@) |
EwoooC 正式運行主機 | momo-pro-system / momo-db / momo-scheduler / openclaw / n8n(Docker) / Ollama |
192.168.0.110 (wooo@) |
周邊服務主機 | VM Nginx 反向代理、Harbor(仍在運行)、Sentry self-hosted、SigNoz、Gitea (+ runner)、Langfuse、監控 exporter |
192.168.0.112 (kali@) |
安全掃描工作站 | Nmap / Bandit / Trivy / WireGuard |
⚠️ 110 的
/home/wooo/momo_pro_system/實際已空置(僅剩docker/+venv/),不是 EwoooC 的運行目錄。 ⚠️ 110 載載 load avg ≈ 14.5,負責 monitor.wooo.work / registry.wooo.work / Harbor / Sentry / SigNoz 等周邊堆疊。
EwoooC 運行主機細節(ollama@192.168.0.188)
| 項目 | 值 |
|---|---|
| 專案路徑 | /home/ollama/momo-pro/ |
| 部署方式 | Docker Compose V12.0(無 Git 版控,純檔案系統) |
| 主容器 | momo-pro-system (Flask + gunicorn) / momo-db (pgvector/pgvector:pg14) / momo-scheduler / openclaw (clawbot-v5) |
| 容器啟動指令 | gunicorn --bind 0.0.0.0:80 --workers 4 --timeout 300 app:app |
| 主容器端口 | 127.0.0.1:5003:80(gunicorn 內部聽 80,host 僅本地 5003) |
| Volume 掛載 | app.py / scheduler.py / config.py / auth.py / config/ / database/ / templates/ / services/ / routes/ / data/ / logs/ / backups/(皆為 host 目錄掛到容器 /app,修改即時生效) |
| 未掛載 | docs/(CLAUDE.md / ADR 純屬本地參考文件) |
| 資料庫 | momo-db 使用 pgvector/pgvector:pg14,為 AI KM 模組(ADR-002/003/007)提供 vector(1024) 欄位 |
SSH 連線 SOP(必須經 110 跳板)
# 先跳 110
ssh wooo@192.168.0.110
# 再進 188(SSH Key 已預先建立)
ssh ollama@192.168.0.188
Claude 工具層可直接執行:ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "<cmd>"。
Docker Compose 管理指令(在 188 上)
cd /home/ollama/momo-pro
# 查看所有容器
docker ps
# 即時日誌(Flask 主應用)
docker logs -f momo-pro-system --tail 100
# 重啟主應用(Python 檔案 volume 掛載已更新時使用)
docker restart momo-pro-system
# 完全重建(新增 Python 套件/更改 Dockerfile 時)
docker compose build momo-app && docker compose up -d momo-app
# 進入資料庫
docker exec -it momo-db psql -U momo -d momo_analytics
網路架構圖(2026-04-19 實地重繪)
┌────────────────────────────────────────────────┐
Internet │ 110 (wooo@192.168.0.110) │
│ │ 周邊服務主機 + VM Nginx 反向代理 │
▼ │ │
┌──────────┐ │ VM Nginx (systemd, port 80/443, SSL) │
│ DNS │ │ ├─ mo.wooo.work ──┐ │
│ Records │ │ ├─ momo.wooo.work ──┤ ⚠️ TODO:需統帥確認 │
└────┬─────┘ │ ├─ registry.wooo.work ─┤ 這兩個域名目前 │
│ │ ├─ monitor.wooo.work │ 實際 upstream 為何?│
▼ │ └─ ollama.wooo.work ─┘ 檔案 /etc/nginx/ │
┌──────────┐ │ sites-enabled/momo│
│DNS → 110 │ │ (110 本地的周邊容器:) │
└────┬─────┘ │ Harbor (11 個 harbor-* 容器,仍在運行) │
│ │ Sentry self-hosted (30+ 容器) │
│ │ SigNoz / Gitea + runner / Langfuse │
│ │ Docker Registry / Superset │
│ │ Prometheus exporters / Fail2Ban exporter │
│ (VM Nginx 反向代理) └────────────────────────────┬───────────────────┘
│ │ (proxy_pass)
▼ ▼
┌────────────────────────────────────────────────────────────────────┐
│ 188 (ollama@192.168.0.188) EwoooC 正式運行主機 │
│ /home/ollama/momo-pro/ (Docker Compose V12.0) │
├────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────┐ ┌───────────────────┐ │
│ │ momo-pro-system │──▶│ momo-db │ │
│ │ Flask + gunicorn │ │ pgvector/pg14 │ │
│ │ 127.0.0.1:5003:80 │ │ (DB + KM vector) │ │
│ └────────────────────┘ └───────────────────┘ │
│ ┌────────────────────┐ ┌───────────────────┐ │
│ │ momo-scheduler │ │ openclaw │ │
│ │ (爬蟲排程) │ │ (clawbot-v5) │ │
│ └────────────────────┘ └───────────────────┘ │
│ ┌────────────────────┐ ┌───────────────────┐ │
│ │ n8n (Docker) │ │ Ollama + WebUI │ │
│ └────────────────────┘ └───────────────────┘ │
└────────────────────────────────────────────────────────────────────┘
服務端口對照表
| 服務 | 主機 | 類型 | 本地綁定 | 外部訪問 | 說明 |
|---|---|---|---|---|---|
| momo-pro-system | 188 | Docker | 127.0.0.1:5003:80 |
mo.wooo.work / momo.wooo.work (經 110 VM Nginx) |
Flask + gunicorn (4 workers) |
| momo-db | 188 | Docker | 內部 network | 僅容器網路 | pgvector/pg14 |
| momo-scheduler | 188 | Docker | — | — | 爬蟲排程 |
| openclaw | 188 | Docker | — | — | clawbot-v5 |
| n8n | 188 | Docker | 127.0.0.1:5678:5678 |
monitor.wooo.work/n8n/ (經 110 代理) |
Webhook 自動化 |
| Ollama | 188 | Docker | 內部 network | ollama.wooo.work (經 110) |
AI 模型服務 |
| Registry | 110 | Docker | 127.0.0.1:5000 |
registry.wooo.work (經 VM Nginx) |
Container Registry |
| Prometheus | 110 | Docker | 內部 | monitor.wooo.work/prometheus/ |
監控指標收集 |
| Grafana | 110 | Docker | 內部 | monitor.wooo.work/grafana/ |
監控儀表板 |
| Alertmanager | 110 | Docker | 內部 | monitor.wooo.work/alertmanager/ |
告警路由 |
| Harbor | 110 | Docker | 內部 | 待定 | 尚未撤除(文件先前誤報已移除) |
VM Nginx 反向代理(110 上)
Nginx 配置位置:/etc/nginx/sites-enabled/momo
mo.wooo.work / momo.wooo.work 的流量路徑(現況推測,待驗證):
用戶 → {mo|momo}.wooo.work:443 → 110 VM Nginx (SSL 終結) → ??? → 188:5003 momo-pro-system
⚠️ TODO: 需統帥確認 — 110 上
proxy_pass的具體 upstream。若為http://192.168.0.188:5003,要求 188 的 5003 對 110 開放(非純 127.0.0.1 綁定);若 110 本機另跑一個 reverse proxy daemon 聽127.0.0.1:5001再轉 188,需補查。此段待 SSH 到 110 檢視sites-enabled/momo實際內容後更新。
監控堆疊(Docker,分佈於 110 + 188)
| 組件 | 主機 | 說明 |
|---|---|---|
| Prometheus | 110 Docker | 抓取 110 + 188 兩邊的 exporter |
| Grafana | 110 Docker | monitor.wooo.work/grafana/ |
| Alertmanager | 110 Docker | 告警 → Telegram |
| Node Exporter | 110 + 188 | 各自主機指標 |
| cAdvisor | 110 + 188 | 容器資源指標 |
| n8n | 188 Docker | 自動化 Webhook(容器名 n8n) |
Grafana 登入:
- URL:
http://192.168.0.110:30030(若已改內部綁定,需透過 monitor.wooo.work) - 帳號 / 密碼:
admin/Wooo_Grafana_2026
Telegram 告警配置:
- Bot:
@wooowooowooobot - Chat ID:
5619078117
故障排除:服務 502 / 容器停止
K3s / kubectl / PVC / StatefulSet 相關故障排除流程已作廢(188 無 K8s)。改用 Docker Compose 操作:
# 在 188 上
docker ps -a | grep momo # 查看容器狀態
docker logs -f momo-pro-system --tail 100 # 看日誌
docker restart momo-pro-system # 單純重啟
cd /home/ollama/momo-pro && docker compose up -d # 全部重新拉起
# 在 110 上(VM Nginx 若異常)
sudo systemctl reload nginx
sudo nginx -t
回滾(Docker Compose 原生機制)
188 無 K8s,無所謂「回滾到 Docker Compose」。版本回退方式是:
- 重建 Docker image 至舊版本並
docker compose up -d - 若 Python 檔案損壞,可從
/home/ollama/momo-pro/backups/取回
過往
/home/wooo/backups/pre-k8s-migration/quick_rollback.sh已失去意義(188 從未 K8s 化),保留檔案但不再作為回滾途徑。
🔐 服務帳號密碼總覽 (2026-04-18 更新)
單一監控中心: 所有服務集中於 UAT 主機
應用服務
| 環境 | 服務 | URL | 帳號 | 密碼 | 版本 |
|---|---|---|---|---|---|
| 🟢 正式 | EwoooC(MOMO Pro) | https://mo.wooo.work、https://momo.wooo.work | - | 0936223270 |
V9.4(Docker Compose 於 188) |
| 🟢 正式 | CI/CD Dashboard | https://mo.wooo.work/cicd | - | - | - |
| 🟢 正式 | PostgreSQL (momo-db, pgvector) | 容器內部 network on 188 | momo |
wooo_pg_2026 |
pgvector/pg14,含 KM vector(1024) |
監控服務 (集中於 UAT)
| 服務 | URL | 帳號 | 密碼 | 說明 |
|---|---|---|---|---|
| 監控入口頁面 | https://monitor.wooo.work/ | - | - | 所有監控服務入口 (110) |
| Grafana | http://192.168.0.110:30030 或 monitor.wooo.work/grafana/ | admin |
Wooo_Grafana_2026 |
監控儀表板 (110 Docker) |
| Prometheus | monitor.wooo.work/prometheus/ | - | - | 指標收集 (110 Docker) |
| Alertmanager | monitor.wooo.work/alertmanager/ | - | - | 告警路由 → Telegram (110 Docker) |
| n8n | http://192.168.0.188:5678 (內部) | admin@wooo.work |
Wooo_N8n_2026 |
自動化工作流程 (188 Docker, 容器名 n8n) |
開發工具
| 服務 | URL | 帳號 | 密碼 | 說明 |
|---|---|---|---|---|
| Registry | https://registry.wooo.work | admin |
Wooo_Registry_2026 |
Container Registry |
BI 分析平台
| 服務 | URL | 帳號 | 密碼 | 說明 |
|---|---|---|---|---|
| Apache Superset | https://monitor.wooo.work/superset/ | admin |
Wooo_Superset_2026 |
BI 分析儀表板 |
| Superset DB (readonly) | 10.42.0.199:5432 | superset_readonly |
Wooo_Superset_RO_2026 |
唯讀資料庫用戶 |
管理工具
| 服務 | URL | 帳號 | 密碼 | 說明 |
|---|---|---|---|---|
| Portainer | https://monitor.wooo.work/portainer/ | admin |
Wooo_Portainer_2026 |
Docker 容器管理 |
AI 服務
| 服務 | URL | API Key | 說明 |
|---|---|---|---|
| Ollama AI | https://ollama.wooo.work | 0df8b4f247a4497998248f013ce92a17 |
AI 模型服務 |
| Gemini AI | API | AIzaSyCqv7TY2iTGi2wa91d2irwH08VYXjT9YUk |
文案生成 |
指標收集器 (Exporters)
| 服務 | URL | 說明 |
|---|---|---|
| Node Exporter | 110 + 188 (127.0.0.1:9100) | 各主機 CPU/記憶體/磁碟 |
| cAdvisor | 110 + 188 (127.0.0.1:8080) | 容器資源使用 |
| Postgres Exporter | 188 Docker (針對 momo-db pgvector) | PostgreSQL 監控 |
| Blackbox Exporter | 110 (127.0.0.1:9115) | 外部服務探測 |
SSH 連線
| 伺服器 | 指令 | 密碼 | 說明 |
|---|---|---|---|
| EwoooC 正式主機 | ssh -J wooo@192.168.0.110 ollama@192.168.0.188 |
0936223270 |
運行 Flask 主應用 / momo-db / scheduler / openclaw / n8n / Ollama |
| 周邊服務主機 | ssh wooo@192.168.0.110 |
0936223270 |
VM Nginx 反代 / Harbor / Sentry / SigNoz / Gitea / 監控堆疊 |
| Kali DevSecOps | ssh kali@192.168.0.112 |
- | 安全掃描工作站 |
Telegram 告警
| 項目 | 值 |
|---|---|
| Bot Token | 8075645931:AAH-EGKMo8ZC4QJs-Nc1_0s92xHrGdQvdpg |
| Chat ID | 5619078117 |
| 告警來源 | Alertmanager + n8n 工作流程 |
| 告警類型 | Pod OOMKilled、重啟過多、記憶體不足等 |
API Keys 總覽
| 服務 | Key | 用途 |
|---|---|---|
| Gemini AI | AIzaSyCqv7TY2iTGi2wa91d2irwH08VYXjT9YUk |
Google Gemini AI 文案生成 |
| YouTube API | AIzaSyBA9n7-rYIQVMq8rSF7kz486avBAfFzJ0s |
YouTube 趨勢爬蟲 |
| n8n API | wooo_n8n_api_2026 |
n8n 工作流 API 存取 |
| Ollama API | 0df8b4f247a4497998248f013ce92a17.vqSWDEK0RppTZIwcdT-ei-Sz |
Ollama AI 模型服務 |
| LINE Channel | nD6MSXjB2FyB111zpT6Yik5B275mi6olHjjf94VnqN1ljUcqzcA7KtSSslxsOCEG6pERzmidNJFdzol6h+9V+t1x3j4Q8ljAacqC+i0627RuwbkiLxoHTJ/9HbIdehhoSJoeuNJHLraE721iDDfIuQdB04t89/1O/w1cDnyilFU= |
LINE 訊息推送 |
| Telegram Bot | 8075645931:AAH-EGKMo8ZC4QJs-Nc1_0s92xHrGdQvdpg |
Telegram 告警通知 |
🔄 運維架構(2026-04-19 依 SSH 實地審計重寫)
架構: EwoooC 正式服務跑在 188 Docker Compose,監控告警堆疊跑在 110 Docker,n8n Webhook 引擎跑在 188 Docker (容器名
n8n)。
架構圖
┌──────────────────────────────────────────────┐ ┌─────────────────────────────────────────────┐
│ 110 (wooo@192.168.0.110) 周邊服務主機 │ │ 188 (ollama@192.168.0.188) EwoooC 正式主機 │
│ │ │ │
│ ┌────────────────────────────────────────┐ │ │ ┌───────────────────────────────────────┐ │
│ │ Prometheus + Grafana + Alertmanager │ │ │ │ /home/ollama/momo-pro/ (Compose V12) │ │
│ │ (Docker) │──┼────┼─▶│ momo-pro-system / momo-db (pgvector) │ │
│ │ 每 15s 抓取 110 + 188 exporter 指標 │ │ │ │ momo-scheduler / openclaw / n8n │ │
│ └────────────────────────────────────────┘ │ │ └───────────────────────────────────────┘ │
│ ┌────────────────────────────────────────┐ │ │ ┌───────────────────────────────────────┐ │
│ │ VM Nginx (systemd) SSL 終結 + 反代 │──┼────┼─▶│ 127.0.0.1:5003 momo-pro-system │ │
│ │ mo.wooo.work / momo.wooo.work → 188 │ │ │ │ (⚠️ TODO 待確認 5003 對 110 開放路徑) │ │
│ └────────────────────────────────────────┘ │ │ └───────────────────────────────────────┘ │
│ │ │ ┌───────────────────────────────────────┐ │
│ Harbor / Sentry / SigNoz / Gitea / Langfuse │ │ │ n8n Docker (容器名 `n8n`) │ │
│ Docker Registry / Superset │ │ │ 自動化工作流程引擎 │ │
│ (monitor.wooo.work 反代入口) │ │ └───────────────────────────────────────┘ │
└──────────────────────────────────────────────┘ └─────────────────────────────────────────────┘
監控 → 告警 → 自動修復 流程
Prometheus(110) 每 15s 抓取
│
├─ 110 cAdvisor/Node exporter
├─ 188 cAdvisor/Node exporter
├─ momo-db pg_exporter (188)
└─ Blackbox: mo.wooo.work / momo.wooo.work / monitor.wooo.work
│
▼
Alertmanager(110) 告警路由
│
├─ Telegram 通知(@wooowooowooobot)
└─ n8n webhook 觸發自動修復
│
▼
ssh 188 → docker restart <container>
域名健康監控腳本(2026-02-09 / 2026-04-19 修正)
腳本位置: /home/wooo/scripts/domain-health-monitor.sh(110 上執行,因為 110 是 VM Nginx 所在,也能 SSH 到 188)
Cron 排程: 每 5 分鐘執行
監控域名清單:
| 域名 | 預期狀態碼 | 服務名稱 | 自動修復命令 |
|---|---|---|---|
https://mo.wooo.work/health |
200 | EwoooC App (正式) | ssh ollama@188 "docker restart momo-pro-system" |
https://momo.wooo.work/health |
200 | EwoooC App (momo 域名別名) | ssh ollama@188 "docker restart momo-pro-system" |
https://monitor.wooo.work/ |
200 | Monitor 首頁 (110) | sudo systemctl reload nginx |
https://registry.wooo.work/v2/ |
401 | Docker Registry (110) | cd /home/wooo/devops/registry && docker compose restart |
http://192.168.0.188:5678/ |
200 | n8n (188) | ssh ollama@188 "docker restart n8n" |
https://monitor.wooo.work/superset/login/ |
200 | Superset (110) | docker compose restart |
Cron 設定:
*/5 * * * * /home/wooo/scripts/domain-health-monitor.sh >> /home/wooo/logs/domain_health_monitor.log 2>&1
日誌檔案: /home/wooo/logs/domain_health_monitor.log
基礎設施清單
| 項目 | 主機 | 狀態 | 備註 |
|---|---|---|---|
| Docker Compose | 188 | ✅ V12.0 | 承載 EwoooC 正式服務 |
| pgvector DB | 188 Docker | ✅ pg14 | AI KM vector(1024) |
| Prometheus | 110 Docker | ✅ | 指標收集 |
| Grafana | 110 Docker | ✅ | 儀表板 |
| Alertmanager | 110 Docker | ✅ | Telegram 告警 |
| n8n | 188 Docker | ✅ | 容器名 n8n,自動化任務 |
| PostgreSQL Exporter | 188 Docker | ✅ | 對 momo-db 做指標 |
| 自動修復 | 110 Cron | ✅ | domain-health-monitor.sh via SSH |
n8n 自動化工作流程 (2026-02-07 更新)
概述
n8n 作為 UAT 監控管理平台,負責:
- UAT 服務監控與自動修復
- 系統告警通知 (Telegram)
| 類型 | Python Scheduler | n8n |
|---|---|---|
| 系統健康監控 | ❌ | ✅ 每 5 分鐘 |
| 資料爬蟲 | ✅ 專業爬蟲邏輯 | ❌ |
| Google Drive 匯入 | ✅ 複雜資料處理 | ✅ 匯入監控 |
| Telegram/LINE 通知 | ✅ 業績通知 | ✅ 系統告警 |
| 自動修復 | ❌ | ✅ 本地 kubectl |
已部署工作流程
2026-04-18 更新: 單一 UAT 環境監控 + 自動修復
系統監控類 (12 個)
| # | 工作流程 | 頻率 | 自動修復 | 說明 |
|---|---|---|---|---|
| 01 | 磁碟空間監控 | 每小時 | ✅ 自動清理 | 警告 80%、緊急 90% |
| 02 | SSL 證書監控 | 每日 09:00 | ❌ | 30 天內到期告警 |
| 03 | CI/CD Pipeline 通知 | Webhook | ❌ | CI/CD 成功/失敗通知(webhook 來源待定,GitLab 已撤除) |
| 04 | 資料庫備份監控 | 每日 10:00 | ❌ | 檢查最新備份狀態 |
| 05 | 爬蟲執行監控 | 每 2 小時 | ✅ 重啟 scheduler | 檢查爬蟲排程執行 |
| 06 | K8s Pod 狀態監控 | 每 10 分鐘 | ✅ 自動重啟 Pod | 應用健康檢查 |
| 07 | Docker Registry 健康檢查 | 每 30 分鐘 | ❌ | Registry 可用性 |
| 11 | Registry 健康監控 | 每 10 分鐘 | ❌ | 詳細 Registry 狀態 |
| 12 | Google Drive 匯入監控 | 每 30 分鐘 | ❌ | 自動匯入狀態追蹤 |
| 15 | Ollama/WebUI 健康監控 | 每 5 分鐘 | ✅ 自動重啟 | AI 服務監控 |
| 16 | K8s MOMO App 健康監控 | 每 5 分鐘 | ✅ 自動重啟 | 主應用深度監控 |
| 18 | Clawdbot 健康監控 | 每 5 分鐘 | ✅ 自動修復 | Bot 服務監控 |
環境監控類
| # | 工作流程 | 頻率 | 自動修復 | 說明 |
|---|---|---|---|---|
| 17 | UAT 健康監控 | 每 5 分鐘 | ❌ | 服務可用性檢查 |
| 18 | PostgreSQL 資料庫監控 | 每 15 分鐘 | ❌ | 資料庫狀態 |
| 20 | UAT 自動修復機制 | 每 5 分鐘 | ✅ 自動重啟 | 服務自我修復 |
定期報告類 (3 個)
| # | 工作流程 | 頻率 | 說明 |
|---|---|---|---|
| 08 | 每日系統狀態報告 | 每日 09:00 | 應用、備份、爬蟲狀態彙報 |
| 09 | 每週業績摘要 | 每週一 09:00 | 週業績、訂單數、成長率 |
| 10 | 月初作業提醒 | 每月 1 日 09:00 | 月結待辦事項提醒 |
其他工作流程
| # | 工作流程 | 說明 |
|---|---|---|
| 13 | PostgreSQL 慢查詢監控 | 慢查詢告警 + 自動 VACUUM |
| 14 | Windows 遠端控制 | Telegram Bot 遠端控制 |
| 19 | UAT 頁面健康監控 | 關鍵頁面可用性檢查 |
| - | EwoooC 系統健康監控 | 整體系統狀態 |
工作流程檔案位置
n8n-workflows/
├── 01-disk-space-monitor.json # 磁碟空間監控
├── 02-ssl-certificate-monitor.json # SSL 證書監控
├── 03-cicd-pipeline-notify.json # CI/CD 通知 (Webhook)
├── 04-backup-monitor.json # 備份監控
├── 05-crawler-monitor.json # 爬蟲監控
├── 06-k8s-pod-monitor.json # K8s Pod 監控
├── 07-registry-health.json # Registry 健康檢查
├── 08-daily-system-report.json # 每日系統報告
├── 09-weekly-sales-summary.json # 每週業績摘要
├── 10-monthly-reminder.json # 月初提醒
├── 11-harbor-health-monitor.json # Harbor 健康監控
├── 12-google-drive-import-monitor.json # Google Drive 匯入監控
├── 13-slow-query-monitor.json # PostgreSQL 慢查詢監控
├── 14-ollama-health-monitor.json # Ollama 健康監控
├── 17-uat-health-monitor.json # UAT 健康監控
├── 18-postgres-health-monitor.json # PostgreSQL 資料庫監控
└── 20-auto-repair-uat.json # UAT 自動修復機制
系統管理 API (供 n8n 呼叫)
| 端點 | 方法 | 說明 |
|---|---|---|
/api/system/cleanup |
POST | 自動清理 (Docker prune, 日誌輪替) |
/api/system/k8s/restart |
POST | 重啟 K8s Deployment |
/api/system/crawler/status |
GET | 爬蟲執行狀態 |
/api/system/backup/status |
GET | 備份狀態檢查 |
/api/system/ssl/check |
GET | SSL 證書檢查 |
/api/system/registry/health |
GET | Registry 健康檢查 |
通知模板管理系統
功能說明
提供 Web UI 管理 Telegram/LINE 通知訊息內容,可自訂 emoji、標題、內容格式。
管理頁面
- URL:
/notification_templates - 功能: 編輯模板、預覽訊息、初始化預設模板
API 端點
| 端點 | 方法 | 說明 |
|---|---|---|
/api/notification/templates |
GET | 取得所有模板 |
/api/notification/templates/<code> |
GET | 取得單一模板 |
/api/notification/templates/<code> |
PUT | 更新模板 |
/api/notification/render |
POST | 渲染模板 (n8n 呼叫) |
預設模板列表 (14 個)
| 分類 | 模板代碼 | 說明 |
|---|---|---|
| system | disk_warning |
磁碟空間警告 (80%) |
| system | disk_critical |
磁碟空間嚴重不足 (90%) |
| system | cleanup_complete |
自動清理完成 |
| system | ssl_warning |
SSL 證書即將到期 |
| system | pod_unhealthy |
K8s Pod 異常 |
| system | pod_restart_result |
Pod 重啟結果 |
| system | crawler_warning |
爬蟲執行警告 |
| system | registry_unhealthy |
Registry 異常 |
| system | backup_warning |
備份監控警告 |
| system | cicd_success |
CI/CD 成功 |
| system | cicd_failed |
CI/CD 失敗 |
| report | daily_report |
每日系統狀態報告 |
| business | weekly_sales |
每週業績摘要 |
| business | monthly_reminder |
月初作業提醒 |
n8n 整合方式
在 n8n 中呼叫 /api/notification/render 取得格式化訊息後發送:
POST /api/notification/render
{
"code": "disk_warning",
"variables": {
"usage_percent": 85,
"free_gb": 15,
"total_gb": 100
}
}
n8n 管理指令
# SSH 到 UAT
ssh wooo@192.168.0.110
# 查看 n8n 容器狀態
docker ps | grep n8n
# 查看 n8n 日誌
docker logs momo-n8n --tail 50
# 列出所有工作流程
docker exec momo-n8n n8n list:workflow
# 手動觸發工作流程
docker exec momo-n8n n8n execute --id=H7O3cl6sUPSLM7UD
n8n API 存取
# 列出工作流程
curl -H "X-N8N-API-KEY: wooo_n8n_api_2026" \
http://192.168.0.110:5678/api/v1/workflows
# 執行工作流程
curl -X POST -H "X-N8N-API-KEY: wooo_n8n_api_2026" \
http://192.168.0.110:5678/api/v1/workflows/H7O3cl6sUPSLM7UD/activate
Docker Registry 詳細資訊
| 項目 | 值 |
|---|---|
| 外部 URL | https://registry.wooo.work (HTTPS, 推薦) |
| 內部 URL | http://127.0.0.1:5000 (僅本機可存取) |
| 帳號 | admin |
| 密碼 | Wooo_Registry_2026 |
| 映像位置 | registry.wooo.work/wooo/momo-pro-system:latest |
⚠️ 安全提醒: Port 5000 已改為僅綁定 127.0.0.1,外部訪問必須透過 HTTPS 域名。
Rancher (K8s 管理平台)
| 項目 | 值 |
|---|---|
| URL | https://192.168.0.110:8443 |
| 帳號 | admin |
| 密碼 | 0B5-z2m0yxle6HtTq5WA |
| 功能 | K3s 集群管理、監控、日誌 |
| K3s 集群 | momo-k3s (已匯入) |
| Cluster ID | c-52mz8 |
| K8s 版本 | v1.34.3+k3s1 |
Registry 映像管理
# 登入 Registry (使用 HTTPS 域名)
echo 'Wooo_Registry_2026' | docker login registry.wooo.work -u admin --password-stdin
# 映像位置 (使用域名)
registry.wooo.work/wooo/momo-pro-system:latest
CI/CD 流程(GitLab 已撤除,待定新方案)
2026-04-18 更新: GitLab CE + GitLab CI/CD 已從基礎設施移除,新的 CI/CD 方案尚未定案。 目前部署以「本地 build + SCP + kubectl rollout restart」為暫時流程,相關腳本待 CI/CD 選型後重寫。
手動觸發 K8s 更新
# SSH 到 UAT
ssh wooo@192.168.0.110
# 重啟 K8s Deployment(會自動拉取最新 Image)
kubectl rollout restart deployment/momo-app deployment/momo-scheduler -n momo
# 查看更新狀態
kubectl rollout status deployment/momo-app -n momo
Docker 容器(DevOps 服務)
| 容器名稱 | 說明 | Port |
|---|---|---|
| registry | Docker Registry 容器 | 5000 |
| watchtower | Docker 映像自動更新 | - |
| n8n | Webhook 自動化 | 5678 |
K8s Pod(應用服務)
| Pod | 說明 | 資源限制 |
|---|---|---|
| momo-app | Flask 主應用 | 512Mi-4Gi / 200m-2000m |
| momo-postgres | PostgreSQL 資料庫 | 256Mi-1Gi / 100m-500m |
| momo-scheduler | 爬蟲排程服務 | 256Mi-2Gi / 100m-1000m |
K8s 配置檔案
| 檔案 | 說明 |
|---|---|
k8s/02-configmap.yaml |
環境變數配置(Ollama AI、密碼策略等) |
k8s/04-momo-app.yaml |
Flask 主應用 Deployment + Google Drive 認證 |
k8s/05-scheduler.yaml |
爬蟲排程 Deployment + Google Drive 認證 |
k8s/08-google-drive-secret.yaml |
Google OAuth 認證 Secret |
k8s/nginx/monitor.conf |
VM Nginx 配置(含 Rancher 代理) |
Nginx 代理路徑(monitor.wooo.work)
| 路徑 | 後端服務 | Port |
|---|---|---|
/grafana/ |
Docker Grafana | 3000 |
/prometheus/ |
Prometheus | 9090 |
/alertmanager/ |
Alertmanager | 9093 |
/portainer/ |
Portainer | 9000 |
/n8n/ |
n8n | 5678 |
/pgadmin/ |
pgAdmin | 8088 |
/loki/ |
Loki | 3100 |
/rancher/ |
Rancher | 8443 (HTTPS) |
/k8s-grafana/ |
K8s Grafana | 30030 |
關鍵路徑
| 用途 | 路徑 |
|---|---|
| 主資料庫 | data/momo_database.db |
| UAT 資料庫 | data/momo_database_uat.db |
| Google Drive 認證 | config/google_credentials.json |
| 排程器程式 | run_scheduler.py |
| 排程統計 | data/scheduler_stats.json |
| 系統日誌 | logs/system.log |
Ollama AI 服務
| 項目 | 值 |
|---|---|
| Host | http://192.168.0.188:11434 |
| 預設模型 | llama3:70b-instruct-q2_K |
| API Key | 0df8b4f247a4497998248f013ce92a17.vqSWDEK0RppTZIwcdT-ei-Sz |
| 超時設定 | 基本 180 秒 / 文案生成 240 秒 |
K8s ConfigMap 設定
# k8s/02-configmap.yaml
OLLAMA_HOST: "http://192.168.0.188:11434"
OLLAMA_MODEL: "llama3:70b-instruct-q2_K"
環境變數
OLLAMA_HOST=http://192.168.0.188:11434
OLLAMA_MODEL=llama3:70b-instruct-q2_K
OLLAMA_API_KEY=0df8b4f247a4497998248f013ce92a17.vqSWDEK0RppTZIwcdT-ei-Sz
Ollama 伺服器健康監控 (2026-01-28 新增)
監控腳本: /home/ollama/scripts/ollama_health_monitor.sh
排程: 每 5 分鐘執行 (cron)
n8n 工作流程: 14-ollama-health-monitor.json
監控項目:
| 項目 | 端點 | 說明 |
|---|---|---|
| Nginx | 進程檢查 | 確保代理服務正常 |
| Ollama API | http://127.0.0.1:11434/api/tags | AI 模型服務 |
| Open WebUI | http://192.168.0.188/ | Web 介面 |
自動修復機制:
| 問題 | 修復動作 |
|---|---|
| Nginx 停止 | sudo systemctl restart nginx |
| Ollama 停止 | systemctl restart ollama |
| Open WebUI 502 (Docker 網路失效) | sudo systemctl restart docker |
| Open WebUI 容器卡住 | docker restart open-webui |
SSH 連線:
ssh ollama@192.168.0.188
# 密碼: 0936223270
手動檢查:
# 執行健康檢查
/home/ollama/scripts/ollama_health_monitor.sh
# 查看日誌
tail -f /var/log/ollama_health_monitor.log
Ollama 伺服器安全加固 (2026-02-02 新增)
安全腳本: scripts/security/harden_ollama_server.sh
已安裝防護:
| 服務 | 配置 | 說明 |
|---|---|---|
| Fail2Ban | SSH 3 次失敗封鎖 1 小時 | 防暴力破解 |
| UFW 防火牆 | 預設拒絕入站 | 網路存取控制 |
UFW 規則:
# 公開服務
22/tcp # SSH
80/tcp # HTTP
443/tcp # HTTPS
# 僅限內網 (192.168.0.0/24)
11434 # Ollama API
3000 # Open WebUI
5678 # n8n
8080 # SearXNG
管理指令:
# 查看 Fail2Ban 封鎖狀態
sudo fail2ban-client status sshd
# 查看防火牆規則
sudo ufw status verbose
Kali Linux DevSecOps 工作站
| 項目 | 值 |
|---|---|
| IP | 192.168.0.112 |
| 用戶 | kali |
| 用途 | 集中式安全掃描、滲透測試、弱點管理 |
SSH 連線
ssh kali@192.168.0.112
目錄結構
/home/kali/
├── projects/ # 專案程式碼 (Git clone)
│ └── momo-pro-system/ # 主專案
└── scripts/ # 自動化掃描腳本
├── port_monitor.py # 端口監控
├── port_baseline.json # 端口基線
├── code_security_scan.py # 程式碼安全掃描 (Bandit)
├── registry_image_scan.py # 容器映像掃描 (Trivy)
└── logs/ # 掃描日誌
自動化掃描工具
1. 端口監控 (port_monitor.py)
- 執行頻率: 每小時
- 監控目標:
192.168.0.110,192.168.0.188 - 功能: Nmap 掃描,與基線比對,發現新端口時發送 Telegram 告警
- Cron:
0 * * * * /usr/bin/python3 /home/kali/scripts/port_monitor.py
2. 程式碼安全掃描 (code_security_scan.py)
- 執行頻率: 每日 08:00
- 工具: Bandit (Python 安全分析器)
- 功能: 掃描 ~/projects 下所有專案,發送 Telegram 報告
- Cron:
0 8 * * * /usr/bin/python3 /home/kali/scripts/code_security_scan.py
3. Registry 映像掃描 (registry_image_scan.py)
- 執行頻率: 每週日 09:00
- 工具: Trivy (容器弱點掃描器)
- 功能: 掃描 Docker Registry 中的映像,發送 Telegram 報告
- Cron:
0 9 * * 0 /usr/bin/python3 /home/kali/scripts/registry_image_scan.py - 掃描目標:
registry.wooo.work/wooo/momo-pro-system:latest
基線端口清單 (2026-01-25 更新)
192.168.0.110 (外部可見):
| Port | Service |
|---|---|
| 22 | SSH |
| 80 | HTTP |
| 443 | HTTPS (SSL, Registry/mo.wooo.work) |
⚠️ Port 5050, 5678, 9100 已隱藏,僅本地可存取
192.168.0.188 (外部可見):
| Port | Service |
|---|---|
| 22 | SSH |
| 80 | HTTP |
| 443 | HTTPS |
手動執行掃描
# 端口掃描
python3 ~/scripts/port_monitor.py
# 程式碼安全掃描 (Bandit)
python3 ~/scripts/code_security_scan.py
# Registry 映像掃描 (Trivy)
python3 ~/scripts/registry_image_scan.py
WireGuard VPN (WG-Easy)
| 項目 | 值 |
|---|---|
| 管理介面 | http://192.168.0.112:51821 |
| 外部端點 | 114.32.151.246:51820/udp |
| 密碼 | Wooo_VPN_2026 |
| 允許網段 | 192.168.0.0/24, 10.0.0.0/8 |
| DNS | 8.8.8.8, 8.8.4.4 |
使用方式:
- 開啟管理介面
http://192.168.0.112:51821 - 輸入密碼登入
- 點擊「+ New」建立新用戶
- 手機下載 WireGuard App,掃描 QR Code 即可連線
Docker 容器管理:
# 查看狀態
docker ps --filter name=wg-easy
# 重啟服務
docker restart wg-easy
# 查看日誌
docker logs wg-easy
⚠️ 安全提醒: 需要在路由器設定 Port Forwarding: 51820/UDP → 192.168.0.112:51820
🛡️ 服務變更安全協議 (2026-02-08 新增)
核心原則: 避免「改一個壞一個」,每次變更前必須確認所有相關服務狀態
服務依賴關係圖
┌─────────────────────────────────────────────────────────────────────────────┐
│ UAT 服務依賴架構圖 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ VM Nginx │ ← 所有外部流量入口 │
│ │ (Port 80/443) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────┴────────────────────────────────────────────────────────┐ │
│ │ │ │
│ ▼ ▼ ▼ │ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │mo.wooo │ │monitor. │ │registry. │ │ │
│ │.work │ │wooo.work │ │wooo.work │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ │ │ │ │ │
│ ▼ ▼ ▼ │ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │K8s │ │Superset │ │Registry │ │ │
│ │momo-app │ │Grafana │ │Docker │ │ │
│ │ │ │Prometheus│ │ │ │ │
│ └────┬─────┘ │n8n │ └──────────┘ │ │
│ │ │Portainer │ │ │
│ │ └──────────┘ │ │
│ ▼ │ │
│ ┌──────────┐ │ │
│ │momo- │ │ │
│ │postgres │ │ │
│ └──────────┘ │ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
⚠️ 重要依賴關係:
1. Nginx 故障 → 所有外部服務不可訪問
2. Docker 故障 → Superset、n8n、Registry 全停
3. K8s 故障 → momo-app、momo-scheduler、momo-postgres 全停
4. Registry 故障 → K8s 無法拉取新映像
變更前必做檢查清單 ✅
在進行任何配置變更之前,必須執行以下檢查:
# 1. 記錄當前所有服務狀態(變更前快照)
ssh wooo@192.168.0.110 "
echo '=== 變更前服務狀態快照 ==='
echo '時間:' \$(date '+%Y-%m-%d %H:%M:%S')
echo ''
echo '--- Docker 容器 ---'
docker ps --format 'table {{.Names}}\t{{.Status}}' | head -20
echo ''
echo '--- K8s Pods ---'
kubectl get pods -n momo --no-headers 2>/dev/null
echo ''
echo '--- 健康檢查 ---'
curl -s -o /dev/null -w 'mo.wooo.work: %{http_code}\n' https://mo.wooo.work/health
curl -s -o /dev/null -w 'Superset: %{http_code}\n' https://monitor.wooo.work/superset/login/
curl -s -o /dev/null -w 'n8n: %{http_code}\n' http://127.0.0.1:5678/ 2>/dev/null || echo 'n8n: 連線失敗'
" | tee /tmp/pre_change_status.txt
服務恢復 SOP
1. Docker 容器停止 (Exit 128/137)
常見原因: 系統重啟、Docker 重啟、OOM
# 檢查停止的容器
ssh wooo@192.168.0.110 "docker ps -a --filter status=exited"
# 恢復 n8n (如有衝突需先刪除)
ssh wooo@192.168.0.110 "docker rm -f momo-n8n; cd /home/wooo && docker compose up -d n8n"
# 恢復 Superset
ssh wooo@192.168.0.110 "cd /home/wooo/momo_pro_system/docker/superset && docker compose down && docker compose up -d"
# 恢復 Registry
ssh wooo@192.168.0.110 "cd /home/wooo/devops/registry && docker compose up -d"
2. Nginx 502 Bad Gateway
診斷流程:
# Step 1: 確認後端容器狀態
docker ps | grep <service_name>
# Step 2: 測試容器內部
docker exec <container> curl -s http://127.0.0.1:<port>/health
# Step 3: 如果內部正常但外部 502 = Docker 網路問題
sudo systemctl restart docker
3. Superset 路徑問題 (/superset/superset/)
根本原因: Superset 內部路由已是 /superset/...,Nginx proxy_redirect / /superset/ 會重複添加
正確的 Nginx 配置:
location /superset/ {
proxy_pass http://127.0.0.1:8088/;
# 關鍵:Superset 內部已是 /superset/,不需要再添加
proxy_redirect /superset/ /superset/;
proxy_redirect ~^/(?!superset)(.*)$ /superset/$1;
# 只重寫 static 和 api 路徑
sub_filter '"/static/' '"/superset/static/';
sub_filter "'/static/" "'/superset/static/";
sub_filter_once off;
}
Superset 配置 (superset_config.py):
ENABLE_PROXY_FIX = True
PROXY_FIX_CONFIG = {
"x_for": 1,
"x_proto": 1,
"x_host": 1,
"x_prefix": 0, # 必須為 0!Nginx 已處理前綴
}
4. K8s Pod 問題
# 查看 Pod 狀態
kubectl get pods -n momo
# 查看 Pod 詳情
kubectl describe pod <pod-name> -n momo
# 重啟 Deployment
kubectl rollout restart deployment/momo-app deployment/momo-scheduler -n momo
# 查看日誌
kubectl logs -f deployment/momo-app -n momo --tail=100
變更後驗證清單 ✅
每次變更完成後,必須執行以下驗證:
# 完整服務健康檢查
ssh wooo@192.168.0.110 "
echo '=== 變更後服務驗證 ==='
echo '時間:' \$(date '+%Y-%m-%d %H:%M:%S')
echo ''
# Docker 容器
echo '--- Docker 容器狀態 ---'
docker ps --format 'table {{.Names}}\t{{.Status}}' | head -15
# K8s
echo ''
echo '--- K8s Pods ---'
kubectl get pods -n momo --no-headers 2>/dev/null
# 健康檢查
echo ''
echo '--- 健康檢查 ---'
curl -s -o /dev/null -w 'mo.wooo.work: %{http_code}\n' https://mo.wooo.work/health
curl -s -o /dev/null -w 'Superset 登入: %{http_code}\n' https://monitor.wooo.work/superset/login/
curl -s -o /dev/null -w 'n8n: %{http_code}\n' http://127.0.0.1:5678/ 2>/dev/null || echo 'n8n: 連線失敗'
curl -s -o /dev/null -w 'Registry: %{http_code}\n' https://registry.wooo.work/v2/ 2>/dev/null || echo 'Registry: 連線失敗'
curl -s -o /dev/null -w 'CI/CD Dashboard: %{http_code}\n' https://mo.wooo.work/cicd 2>/dev/null
echo ''
echo '=== 驗證完成 ==='
"
Claude 協作改進方案
2026-02-08 新增 - 回應用戶「改一個壞一個」的反饋
1. 變更前自動快照
- 在進行任何配置變更前,Claude 應主動執行「變更前必做檢查清單」
- 將結果保存以便變更後對比
2. 相關服務連帶檢查
- 修改 Nginx → 同時檢查所有代理的服務
- 修改 Docker Compose → 同時檢查相關容器
- 修改 K8s YAML → 同時檢查 Pod 狀態
3. 變更後完整驗證
- 不只驗證目標服務,還要驗證所有可能受影響的服務
- 使用「變更後驗證清單」確保沒有遺漏
4. 文檔記錄
- 每次修復重要問題後,立即更新 CLAUDE.md
- 記錄問題症狀、根本原因、解決方案
常見問題與解法
1. Scheduler 無法匯入 Google Drive 檔案
症狀: 日誌顯示 找不到認證檔案: config/google_credentials.json
K8s 解法: 使用 initContainer 從 Secret 複製認證到可寫入目錄
# k8s/04-momo-app.yaml & k8s/05-scheduler.yaml
initContainers:
- name: copy-google-credentials
image: busybox:1.36
command: ['sh', '-c', 'cp /secrets/* /config/ && chmod 644 /config/*']
volumeMounts:
- name: google-drive-secrets
mountPath: /secrets
readOnly: true
- name: momo-config-volume
mountPath: /config
volumes:
- name: google-drive-secrets
secret:
secretName: google-drive-credentials
- name: momo-config-volume
emptyDir: {}
Docker 解法: 確認 docker-compose.yml 中 scheduler 有掛載 config 目錄
scheduler:
volumes:
- ./config:/app/config:ro # 必須有這行
2. 資料沒有同步到 realtime_sales_monthly
症狀: daily_sales_snapshot 有資料但 realtime_sales_monthly 沒有
解法: 檢查 services/import_service.py 中的同步邏輯 (約 line 404-459)
3. LINE 通知發送失敗
症狀: You have reached your monthly limit
原因: LINE Notify 免費方案每月 1000 則限制,需等待下月重置
4. 502 Bad Gateway (Docker 網路問題)
2026-01-28 新增 - 詳細排查過程與自動修復方案
症狀:
- 訪問
https://mo.wooo.work/返回502 Bad Gateway - Nginx 無法連接到後端服務
診斷步驟:
-
檢查 Docker 容器狀態
ssh wooo@192.168.0.110 "sudo docker ps | grep momo"結果:容器顯示
Up About a minute (healthy),看起來正常 -
檢查外部端口連通性
curl -v http://127.0.0.1:5001/health結果:
Connection reset by peer或超時(約 30 秒) -
檢查容器內部健康
docker exec momo-pro-system curl -s http://127.0.0.1:80/health結果:
{"status": "healthy"}- 容器內部正常! -
診斷結論
- ✅ 容器內部服務正常運行
- ❌ Docker 端口映射/網路轉發失效
- Docker-proxy 進程存在但不轉發流量
根本原因: Docker 網路棧故障,通常發生在:
- 系統重啟後 Docker 網路未正確初始化
- iptables 規則被其他服務清除
- Docker daemon 內部狀態不一致
解決方案:
# 重啟 Docker 服務(會重建網路棧)
sudo systemctl restart docker
# 等待容器自動啟動(約 30 秒)
sleep 30
# 驗證服務恢復
curl -s https://mo.wooo.work/health
自動修復腳本: 見 scripts/docker_health_monitor.sh
🔧 自動化監控與修復
Docker 網路健康監控 (Cron)
腳本位置: /home/wooo/scripts/docker_health_monitor.sh
功能:
- 每 5 分鐘檢查 mo.wooo.work 健康狀態
- 檢測到 502/超時時自動執行診斷
- 確認是 Docker 網路問題後自動重啟 Docker
- 發送 Telegram 通知
Cron 設定:
# 每 5 分鐘執行健康檢查
*/5 * * * * /home/wooo/scripts/docker_health_monitor.sh >> /var/log/docker_health_monitor.log 2>&1
監控邏輯:
外部健康檢查 (curl mo.wooo.work)
│
├── 成功 (HTTP 200) → 結束
│
└── 失敗 (502/超時)
│
├── 檢查容器內部 (docker exec curl)
│ │
│ ├── 內部正常 → Docker 網路問題 → 重啟 Docker
│ │
│ └── 內部失敗 → 應用問題 → 重啟容器
│
└── 發送 Telegram 告警
Telegram 告警範例:
🔴 MOMO Pro 服務異常
症狀: 502 Bad Gateway
診斷: Docker 網路轉發失效
動作: 已自動重啟 Docker 服務
時間: 2026-01-28 15:30:00
5. K8s ImagePullBackOff (Registry 服務中斷)
2026-01-28 新增 - Docker Registry 服務中斷導致 K8s 無法拉取映像檔
症狀:
- K8s Pods 顯示
ImagePullBackOff或ErrImagePull - Google Drive 自動匯入停止運作
- Scheduler 和 App 服務中斷
診斷步驟:
-
檢查 K8s Pod 狀態
sudo kubectl get pods -n momo結果:
momo-app和momo-scheduler顯示ImagePullBackOff -
查看詳細錯誤
sudo kubectl describe pod <pod-name> -n momo結果:
Failed to pull image: dial tcp 192.168.0.110:5000: connect: connection refused -
檢查 Registry 服務
docker ps | grep registry結果:Registry 容器未運行
根本原因:
- Docker Registry 服務停止(可能因系統重啟)
- Registry 端口配置改為 127.0.0.1:5000(安全配置)導致 K8s 無法連線
解決方案:
# 1. 啟動 Registry
cd /home/wooo/devops/registry
docker compose up -d
# 2. 更新 K8s 使用 HTTPS 域名
# 修改 k8s/04-momo-app.yaml 和 k8s/05-scheduler.yaml
# 將 image: 192.168.0.110:5000/wooo/momo-pro-system:latest
# 改為 image: registry.wooo.work/wooo/momo-pro-system:latest
# 3. 更新 registry secret
kubectl delete secret registry-secret -n momo
kubectl create secret docker-registry registry-secret \
--docker-server=registry.wooo.work \
--docker-username=admin \
--docker-password=Wooo_Registry_2026 \
-n momo
# 4. 套用配置並重啟
kubectl apply -f k8s/04-momo-app.yaml -f k8s/05-scheduler.yaml
kubectl rollout restart deployment/momo-app deployment/momo-scheduler -n momo
自動修復腳本: 見 scripts/registry_health_monitor.sh
6. Scheduler CrashLoopBackOff (run_scheduler.py 遺失)
2026-02-02 新增 - Scheduler Pod 重啟 387 次
症狀:
- momo-scheduler Pod 顯示 CrashLoopBackOff
- 日誌:
python: can't open file '/app/run_scheduler.py': [Errno 2] No such file or directory
原因: run_scheduler.py 檔案在某次部署中遺失
解決方案:
# 1. 確認檔案存在
ls /Users/ogt/momo-pro-system/run_scheduler.py
# 2. 重建 Docker 映像
cd /home/wooo/momo_pro_system
docker build -t registry.wooo.work/wooo/momo-pro-system:latest .
docker push registry.wooo.work/wooo/momo-pro-system:latest
# 3. 重啟 scheduler
kubectl rollout restart deployment/momo-scheduler -n momo
7. vendor-stockout 500 錯誤 (模板路徑錯誤)
2026-02-02 新增 - 模板檔案位置不正確
症狀:
- 訪問
/vendor-stockout/返回 Internal Server Error - 日誌:
jinja2.exceptions.TemplateNotFound: vendor_stockout/index.html
原因: 模板檔案放在根目錄 (vendor_stockout_index.html),而非正確路徑 (templates/vendor_stockout/index.html)
解決方案:
# 建立正確目錄並移動模板
mkdir -p templates/vendor_stockout
mv vendor_stockout_*.html templates/vendor_stockout/
# 重新命名為正確名稱
mv templates/vendor_stockout/vendor_stockout_index.html templates/vendor_stockout/index.html
# ... 其他檔案同理
8. Alertmanager 無法發送 Telegram 告警
2026-02-02 新增 - 訊息模板語法錯誤
症狀:
- Alertmanager 日誌持續報錯
- 錯誤:
template: :12:27: can't evaluate field StartsAt in type *template.Data
原因: Telegram 訊息模板中 .StartsAt 放在 {{ range .Alerts }} 區塊外,而 StartsAt 是每個 Alert 的屬性
解決方案:
# k8s/monitoring/values-prometheus.yaml
# ❌ 錯誤寫法
{{ range .Alerts }}
📝 摘要: {{ .Annotations.summary }}
{{ end }}
⏰ 時間: {{ .StartsAt.Local.Format "..." }} # 在 range 外,.StartsAt 不存在
# ✅ 正確寫法
{{ range .Alerts }}
📝 摘要: {{ .Annotations.summary }}
⏰ 時間: {{ .StartsAt.Local.Format "..." }} # 在 range 內
{{ end }}
套用修復:
# 更新 Helm values
scp k8s/monitoring/values-prometheus.yaml wooo@192.168.0.110:/home/wooo/momo_pro_system/k8s/monitoring/
# 升級 Prometheus stack
helm upgrade prometheus prometheus-community/kube-prometheus-stack \
-n monitoring \
-f /home/wooo/momo_pro_system/k8s/monitoring/values-prometheus.yaml
# 重啟 Alertmanager
kubectl rollout restart statefulset/alertmanager-prometheus-kube-prometheus-alertmanager -n monitoring
🔧 Registry 自動監控
Registry 健康監控 (Cron)
腳本位置: /home/wooo/scripts/registry_health_monitor.sh
功能:
- 每 5 分鐘檢查 Registry 服務狀態
- 檢測到 Registry 停止時自動啟動
- 發送 Telegram 告警通知
Cron 設定:
# 每 5 分鐘執行 Registry 健康檢查
*/5 * * * * /home/wooo/scripts/registry_health_monitor.sh >> /var/log/registry_health_monitor.log 2>&1
排程任務設定
| 任務 | 頻率 | 說明 |
|---|---|---|
| Google Drive 自動匯入 | 每 30 分鐘 | 匯入 即時業績_當日.xlsx |
| 商品看板爬蟲 | 每 1 小時 | 爬取 momo 商品資料 |
| EDM 限時搶購爬蟲 | 每 1 小時 | 爬取 EDM 活動 |
| 購物節活動爬蟲 | 每 6 小時 | 爬取節慶活動 |
🔄 系統重開機自動啟動機制 (2026-01-31 新增)
概述
系統重開機後,透過 systemd 服務自動啟動所有必要服務,確保服務可用性。
服務啟動順序
重開機完成
↓ (30 秒延遲,等待系統穩定)
1. 確認 Docker 服務啟動
↓
2. 停止 Supabase 非必要服務 (減少資源競爭)
↓
3. 清理並啟動 Docker Registry (等待 healthy)
↓
4. 重啟 K8s momo-app/scheduler (等待就緒)
↓
5. 啟動監控服務
↓
6. 健康檢查 + Telegram 通知
⚠️ 2026-04-18 備註(ADR-008): 以下 systemd 服務設定與路徑為 110 主機早期架構,188 的 Docker Compose 自帶
restart: unless-stopped即可自動恢復,目前 188 不需要此 systemd 腳本。保留本章以供 110 周邊服務(Harbor/Sentry 等)啟動順序參考。
相關檔案(110 周邊服務用,若仍存在)
| 檔案 | 位置 | 說明 |
|---|---|---|
| 啟動腳本 | /home/wooo/momo_pro_system/scripts/tools/system_startup.sh ⚠️(110 上路徑已空置,腳本存在與否需確認) |
舊啟動腳本 |
| systemd 服務 | /etc/systemd/system/momo-startup.service |
開機自動執行 |
| 日誌檔案 | /var/log/momo_startup.log |
啟動日誌 |
188 主機啟動策略(實況)
188 不需要客製 systemd 服務 — Docker Compose 的 restart: unless-stopped 已足夠:
# docker-compose.yml(V12.0 已設定)
services:
momo-app:
restart: unless-stopped
momo-scheduler:
restart: unless-stopped
momo-db:
restart: unless-stopped
開機後 Docker daemon 啟動 → 容器自動恢復 → 無需額外腳本介入。
故障排除
| 問題 | 解決方法 |
|---|---|
| Registry 啟動失敗 | 手動執行 cd /home/wooo/devops/registry && docker compose down && docker compose up -d |
| K8s Pod 卡在 Init | 檢查 Registry 是否健康,重啟 Pod |
| 服務未自動啟動 | 確認 systemctl is-enabled momo-startup.service 返回 enabled |
| 查看詳細日誌 | cat /var/log/momo_startup.log 或 journalctl -u momo-startup.service -n 100 |
模組化輔助腳本庫
deploy/lib/
├── registry.sh # Registry 管理函數
├── k8s.sh # K8s 管理函數
├── monitoring.sh # 監控與 Telegram 通知
└── systemd.sh # Systemd 服務管理
已完成功能 (2026-02)
- SSL 憑證配置 (Let's Encrypt)
- UAT 服務自動啟動腳本優化
- 服務依賴關係文檔建立
- Harbor 移除,改用 Docker Registry (registry.wooo.work)
- CI/CD Dashboard 完整版 (
/cicd頁面) - 監控告警環境標籤
已完成功能 (2026-01)
- 廠商缺貨郵件系統(含自訂模板編輯)
- 缺貨清單分頁 UI(待發送/已發送分開)
- 郵件發送歷史頁面(含內容預覽)
- 每日業績 Telegram/LINE 通知(含趨勢 emoji)
- 修復 scheduler config 目錄掛載問題
- PostgreSQL 資料庫支援(雙資料庫架構)
- 商品看板效能優化(索引 + FileLock 快取鎖)
- K8s Google Drive 認證(initContainer 架構)
- Ollama AI 服務配置(192.168.0.188)
- Rancher K8s 管理平台部署
- K3s 集群匯入 Rancher(momo-k3s)
- CI/CD 安全掃描 (Bandit + Trivy) — 原 GitLab CI 已撤除,待新方案重建
- Kali Linux DevSecOps 工作站(192.168.0.112)
- 自動化端口監控與程式碼掃描 (Cron)
- Registry HTTPS 安全配置(隱藏 5000 端口)
- WireGuard VPN (WG-Easy) 遠端存取
- 系統重開機自動啟動機制 (systemd + 健康檢查)
更新記錄 (2026-01-22 ~ 02-13)
⚠️ 2026-04-18 補正說明(ADR-008): 以下歷史紀錄多處提到「K8s 遷移」「kubectl rollout restart」「
/home/wooo/momo_pro_system/路徑」等,經實地 SSH 審計確認 EwoooC 從未切換到 K3s/K8s,實際始終是 188 上的 Docker Compose。相關歷史段落保留為「文件考古」,不可據此執行任何部署動作。最新部署 SOP 見本文件開頭「🌐 環境架構總覽」與「部署指令」章節。
2026-02-13:重開機服務修復與 Clawdbot 整合
1. 系統啟動腳本更新 (v2.0)
問題: 每次重開機後服務異常,Harbor 已移除但腳本仍嘗試啟動
修復內容:
- 更新
scripts/tools/system_startup.sh為 v2.0 版本 - 移除 Harbor 相關啟動邏輯
- 改用 docker-registry 作為容器倉庫
- 簡化啟動流程:Docker → Registry → n8n → Superset → K8s
啟動腳本新流程:
1. 檢查 Docker 服務
2. 啟動 Docker Registry (docker-registry)
3. 啟動 n8n (momo-n8n)
4. 啟動 Superset (docker compose)
5. 重啟 K8s 應用 (momo-app, momo-scheduler)
6. 健康檢查 + Telegram 通知
2. Monitor 首頁更新
問題: monitor.wooo.work 顯示許多不存在的服務 (Grafana Docker, Portainer, Loki, Metabase 等)
修復:
- 重新設計 Monitor 首頁,只顯示實際部署的服務
- 移除不存在的服務連結:Docker Grafana、Portainer、Loki、Metabase、Nextcloud、Grist、pgAdmin、cAdvisor
目前顯示的服務:
| 分類 | 服務 |
|---|---|
| 應用服務 | EwoooC (mo.wooo.work / momo.wooo.work) |
| 開發工具 | Docker Registry、n8n |
| 監控服務 | Grafana (K8s)、Prometheus、Alertmanager |
| BI 分析 | Apache Superset |
3. Harbor 完全移除
- 清理所有 Harbor 相關容器
- 更新域名健康監控腳本移除 Harbor 檢查
- 改用 docker-registry 容器
4. Clawdbot 整合腳本 (Ollama Server)
新增腳本 (位於 192.168.0.188:~/scripts/):
| 腳本 | 功能 | 使用方式 |
|---|---|---|
health_check.sh |
服務健康檢查 | /ssh ~/scripts/health_check.sh |
k8s_manage.sh |
K8s 管理 | /ssh ~/scripts/k8s_manage.sh [pods|logs|restart] |
backup_manage.sh |
備份管理 | /ssh ~/scripts/backup_manage.sh [status|run] |
sales_query.sh |
業績查詢 | /ssh ~/scripts/sales_query.sh [today|status] |
gemini_cost_report.sh |
Gemini 費用 | 每日 9:00 Cron 自動發送 |
SSH Key 設定:
- Ollama → UAT SSH Key 已添加到 authorized_keys
- 允許 Clawdbot 透過 SSH 執行 K8s 管理命令
5. 域名監控更新
檔案: scripts/domain-health-monitor.sh
- 移除 Metabase 監控(未部署)
- 目前監控服務:EwoooC App、Monitor、Registry、n8n、Superset
6. 監控告警異常修復 (2026-02-13 06:30)
發現的問題:
- n8n 容器不存在 - 容器未設置自動重啟或被意外刪除
- Superset 容器未啟動 - 容器意外停止且未自動重啟
- 監控腳本配置錯誤 - n8n 和 Superset 監控路徑錯誤(寫成 K8s 但實際是 Docker)
服務修復記錄:
| 服務 | 問題 | 修復方式 | 修復時間 |
|---|---|---|---|
| n8n | 容器不存在 | docker run -d --name momo-n8n ... |
06:32 |
| Superset | 容器停止 | cd docker/superset && docker compose up -d |
06:33 |
| Clawdbot Gateway | 服務停止 | systemctl --user start clawdbot-gateway |
06:33 |
監控腳本重大更新 (scripts/domain-health-monitor.sh):
# 舊配置(錯誤)
- ["https://monitor.wooo.work/n8n/healthz"]="200|n8n (K8s)|kubectl rollout restart ..."
- ["https://monitor.wooo.work/superset/health"]="200|Superset (K8s)|kubectl rollout restart ..."
- 固定等待時間 30 秒
# 新配置(正確)
+ ["http://127.0.0.1:5678/"]="200|n8n|docker start momo-n8n ..."|30"
+ ["http://127.0.0.1:8088/health"]="200|Superset|cd docker/superset && docker compose up -d|60"
+ 加入重試機制(最多 3 次,每次間隔 10 秒)
服務優先級定義:
| 優先級 | 服務 | 說明 |
|---|---|---|
| 1 (最高) | EwoooC App | 核心業務 |
| 2 | Registry | 映像倉庫 |
| 3 | n8n | 自動化工作流程 |
| 4 | Superset | BI 分析平台 |
| 5 | Monitor 頁面 | 監控入口 |
最終服務狀態 (06:38 驗證):
| 服務 | 狀態碼 | 狀態 |
|---|---|---|
| EwoooC App (mo) | 200 | ✅ 正常 |
| EwoooC App (momo) | 200 | ✅ 正常 |
| Registry | 401 | ✅ 正常 (需認證) |
| n8n | 200 | ✅ 正常 |
| Superset | 200 | ✅ 正常 |
| Monitor | 200 | ✅ 正常 |
變更檔案:
scripts/domain-health-monitor.sh- 修正監控路徑、增加等待時間、加入重試機制
7. 下午修復 (2026-02-13 17:00)
Clawdbot Gateway 穩定性優化:
- 問題:Clawdbot Gateway 經常異常,出現鎖定檔案衝突
- 原因:舊進程未正確終止,留下
~/.clawdbot/gateway.lock - 修復:在 systemd service 添加
ExecStartPre清理鎖定檔案 - 位置:
~/.config/systemd/user/clawdbot-gateway.service(192.168.0.188)
[Service]
ExecStartPre=/bin/bash -c 'pkill -9 clawdbot 2>/dev/null || true; rm -f ~/.clawdbot/gateway.lock 2>/dev/null || true; sleep 2'
ExecStart=/usr/bin/clawdbot gateway
Restart=always
RestartSec=15
已修復問題:
| 問題 | 狀態 | 修復方式 |
|---|---|---|
| Monitor Logo 破圖 | ✅ 已修復 | 創建 /var/www/monitor/monitor-static/images/ 並複製 logo |
| Superset 404 | ✅ 已修復 | Nginx 添加 /superset/ 重定向和 /superset/login/ 代理規則 |
| Clawdbot Linger | ✅ 已修復 | loginctl enable-linger ollama 已啟用 |
Superset Nginx 配置修復:
# 根路徑重定向
location /superset/ {
if ($request_uri = /superset/) {
return 302 /superset/welcome/;
}
# ... 其他配置
}
# 登入頁面代理到正確路徑
location = /superset/login/ {
proxy_pass http://superset_backend/login/;
# ... 其他 headers
}
待修復問題:
| 問題 | 狀態 | 說明 |
|---|---|---|
| Clawdbot Telegram 衝突 | ⏳ 待修復 | Bot Token 與監控告警系統共用,需創建新的 Telegram Bot 給 Clawdbot |
最終服務狀態 (17:09 驗證):
| 服務 | 狀態碼 | 狀態 |
|---|---|---|
| Monitor Logo | 200 | ✅ 正常 |
| Superset 根路徑 | 302 | ✅ 重定向正常 |
| Superset Login | 200 | ✅ 正常 |
| MOMO App | 200 | ✅ 正常 |
8. 晚間修復 (2026-02-13 19:30-20:00)
Superset 登入轉圈問題修復:
- 問題:Superset 登入頁面一直轉圈,無法登入
- 原因:
/static/靜態資源路徑返回 302 重定向而非正確的代理 - 修復:修改 Nginx
/static/location 為直接代理到 Superset backend
# 修正後
location ^~ /static/ {
proxy_pass http://superset_backend/static/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
n8n 工作流程重新匯入:
- 問題:n8n 只有 1 個工作流程(應有 29 個)
- 原因:n8n 容器重建後資料遺失
- 修復:從
n8n-workflows/目錄重新匯入所有 27+ 個工作流程
Alertmanager 路由規則更新:
- 問題:Telegram 告警未正確發送到 momo namespace 的告警
- 修復:Helm upgrade prometheus-stack 套用正確的路由規則
n8n executeCommand 節點問題:
- 問題:n8n 2.6.4 版本不支援
executeCommand節點類型 - 影響工作流程:UAT 自動修復、Clawdbot 健康監控、UAT 頁面健康監控
- 修復:停用有問題的工作流程,改用 Cron 腳本自動修復(已正常運作)
自動修復機制確認:
| 機制 | 狀態 | 說明 |
|---|---|---|
| Cron domain-health-monitor.sh | ✅ 運作中 | 每 5 分鐘檢查 7 個服務,自動修復 |
| n8n 磁碟空間監控 | ✅ 運作中 | 自動清理磁碟 |
| n8n 健康監控 | ✅ 運作中 | HTTP 檢查 UAT 服務 |
| Prometheus Alertmanager | ✅ 運作中 | K8s momo namespace 告警 → Telegram |
| n8n 自動修復工作流程 | ❌ 已停用 | executeCommand 不支援,改用 Cron |
最終驗證 (20:00):
- ✅ Superset 登入成功
- ✅ 所有 7 個監控服務正常
- ✅ Telegram 告警測試成功
- ✅ Cron 自動修復機制運作正常
- ✅ 29 個 n8n 工作流程已載入
9. 進階自動修復系統部署 (2026-02-13 20:15)
新增自動修復腳本 (scripts/auto-repair/):
| 腳本 | 功能 | 執行頻率 |
|---|---|---|
oom-handler.sh |
OOM 檢測,自動增加記憶體 +50% 並重啟 | 每 15 分鐘 |
postgres-repair.sh |
連線檢測、死鎖處理、VACUUM、週備份 | 每 30 分鐘 |
auto-rollback.sh |
連續 5 次健康檢查失敗,自動回滾版本 | 每 5 分鐘 |
master-auto-repair.sh |
主協調腳本 | 每 5 分鐘 |
Cron 設定:
*/5 * * * * /home/wooo/scripts/auto-repair/master-auto-repair.sh >> /var/log/master_auto_repair.log 2>&1
自動修復能力總覽:
| 問題類型 | 自動修復方式 | 狀態 |
|---|---|---|
| OOM 記憶體不足 | 自動增加限制 +50%,重啟 Pod | ✅ 已實作 |
| PostgreSQL 連線失敗 | 自動重啟 Pod | ✅ 已實作 |
| PostgreSQL 死鎖 | 終止長時間查詢 | ✅ 已實作 |
| 表膨脹/Dead Tuples | 自動 VACUUM ANALYZE | ✅ 已實作 |
| 程式碼 Bug (5次失敗) | 自動回滾到上一版本 | ✅ 已實作 |
| 服務無回應 | Cron 腳本自動重啟 | ✅ 已實作 |
新增 Prometheus 告警規則 (k8s/monitoring/complete-alerting-rules.yaml):
完整的 Prometheus → Alertmanager → Telegram → 自動修復 流程配置:
# 告警規則群組
- name: memory-alerts # OOM 相關告警
- name: postgres-alerts # PostgreSQL 告警
- name: app-health-alerts # 應用健康告警
- name: infrastructure-alerts # 基礎設施告警
| 告警名稱 | 觸發條件 | 告警等級 | 自動修復標籤 |
|---|---|---|---|
PodOOMKilled |
OOMKilled 事件 | critical | oom-handler |
HighMemoryUsage |
記憶體 > 85% | warning | 無 |
MemoryNearLimit |
記憶體 > 95% | critical | oom-handler |
PostgresDown |
pg_up == 0 | critical | postgres-repair |
PostgresHighConnections |
連線 > 80% | warning | postgres-repair |
PostgresDeadlocks |
死鎖發生 | warning | postgres-repair |
PostgresSlowQueries |
查詢 > 5 分鐘 | warning | postgres-repair |
MomoAppDown |
健康檢查失敗 | critical | auto-rollback |
HighHTTP5xxRate |
5xx > 5% | warning | auto-rollback |
PodRestartTooMany |
1小時重啟>5次 | warning | auto-rollback |
DiskSpaceLow |
磁碟 < 15% | warning | disk-cleanup |
DiskSpaceCritical |
磁碟 < 5% | critical | disk-cleanup |
MomoSchedulerDown |
Scheduler 停止 | critical | domain-health-monitor |
監控 → 告警 → 自動修復 完整流程圖:
┌─────────────────────────────────────────────────────────────────────────┐
│ 完整監控與自動修復架構 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 監控層 告警層 修復層 │
│ ─────── ─────── ─────── │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │
│ │Prometheus│ ──────▶│Alertmgr │ ──Telegram──▶│ Cron 自動修復 │ │
│ │ 指標收集 │ │告警路由 │ │ master-auto- │ │
│ └─────────┘ └─────────┘ │ repair.sh │ │
│ │ │ └────────┬────────┘ │
│ ▼ ▼ │ │
│ PrometheusRule webhook (預留) ▼ │
│ (告警規則) └── n8n 整合 ┌────────────┐ │
│ │ oom-handler │ │
│ ┌─────────┐ ┌─────────┐ │ postgres- │ │
│ │域名健康 │ ──────▶│Telegram │ ◀─────────────│ repair │ │
│ │監控腳本 │ │告警通知 │ │ auto- │ │
│ └─────────┘ └─────────┘ │ rollback │ │
│ (每5分鐘Cron) └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
n8n 工作流程更新 (2026-02-13 20:30):
- 重新匯入所有 27+ 個工作流程到 n8n
- 停用使用
executeCommand節點的工作流程 (n8n 2.6.4 不支援) - 停用的工作流程改用 Cron 自動修復機制代替:
- UAT 自動修復 → Cron: domain-health-monitor.sh
- Clawdbot 健康監控 → Cron: 已整合
Git 提交記錄 (2026-02-13 21:00):
feat: 完整監控告警與自動修復系統
新增自動修復腳本 (scripts/auto-repair/):
- oom-handler.sh: OOM 自動增加記憶體
- postgres-repair.sh: PostgreSQL 自動維護
- auto-rollback.sh: 健康檢查失敗自動回滾
- master-auto-repair.sh: 主協調腳本
新增 Prometheus 告警規則:
- k8s/monitoring/complete-alerting-rules.yaml
- 14 個告警規則覆蓋所有核心服務
- 每個告警都有對應的自動修復標籤
已提交至 Git 版控: ✅
2026-02-09:域名健康監控與服務修復
1. 新增域名健康監控腳本
腳本: scripts/domain-health-monitor.sh
Cron: 每 5 分鐘執行
功能:
- 監控 8 個核心域名健康狀態
- 自動發送 Telegram 告警
- 嘗試自動修復(重啟容器/K8s Pod)
- 等待 30 秒驗證修復結果
2. 更新 Nginx 配置
檔案: docker/nginx/monitor-clean.conf
變更:
- 移除 Harbor 相關配置(Harbor 已廢棄)
- 新增 Docker Registry 反向代理(port 5002)
- 更新 Prometheus 使用 K8s ClusterIP (10.43.25.78:9090)
- 更新 Alertmanager 使用 K8s ClusterIP (10.43.79.187:9093)
3. Docker 服務修復
n8n 容器重建:
- 問題:Task Runner 403 錯誤 + 端口綁定問題
- 修復:添加
N8N_RUNNERS_DISABLED=true環境變數 - 重建命令:
docker run -d --name momo-n8n --restart unless-stopped \
-p 5678:5678 \
-e N8N_BASIC_AUTH_USER=admin \
-e N8N_BASIC_AUTH_PASSWORD=Wooo_N8n_2026 \
-e N8N_RUNNERS_DISABLED=true \
-v n8n_data:/home/node/.n8n \
n8nio/n8n:latest
Superset 容器修復:
- 問題:Docker 重啟後容器停止
- 修復:
cd /home/wooo/momo_pro_system/docker/superset && docker compose up -d
4. 當前服務狀態 (2026-02-09 驗證)
正常運作的服務:
| 服務 | URL | 狀態碼 |
|---|---|---|
| EwoooC App (mo) | https://mo.wooo.work/health | 200 ✅ |
| EwoooC App (momo) | https://momo.wooo.work/health | 200 ✅ |
| Monitor 首頁 | https://monitor.wooo.work/ | 200 ✅ |
| Superset | https://monitor.wooo.work/superset/login/ | 200 ✅ |
| Metabase | https://monitor.wooo.work/metabase/ | 200 ✅ |
| n8n | http://192.168.0.110:5678/ | 200 ✅ |
| Registry | https://registry.wooo.work/v2/ | 401 ✅ |
| K8s Grafana | https://monitor.wooo.work/k8s-grafana/ | 302 ✅ |
| Prometheus | https://monitor.wooo.work/prometheus/ | 302 ✅ |
| Alertmanager | https://monitor.wooo.work/alertmanager/ | 200 ✅ |
未部署的服務:
- Nextcloud: 無容器
- Grist: 無容器
- Docker Grafana: 無容器(使用 K8s Grafana)
- Portainer: 無容器
- Loki: 無容器
- cAdvisor: 無容器
- Blackbox Exporter: 無容器
已知問題:
harbor-core容器卡在 restart loop(需 root 權限移除)cattle-cluster-agentCrashLoopBackOff(Rancher 相關,不影響核心服務)
2026-02-08:Superset 子路徑代理修復
1. 修復 Superset 雙重前綴問題
問題:訪問 /superset/ 會跳轉到 /superset/superset/welcome/
根本原因:
- Superset 內部 Flask blueprints 已使用
/superset/...路由 superset_config.py中x_prefix=1會再次添加前綴- Nginx
proxy_redirect / /superset/;也會重複添加
修復方案:
superset_config.py: 設置x_prefix=0禁用從 X-Forwarded-Prefix 讀取前綴nginx-superset.conf: 使用智能正則表達式保留已有/superset/前綴proxy_redirect /superset/ /superset/; proxy_redirect ~^/(?!superset)(.*)$ /superset/$1;
2. 修復 Superset 登入重定向問題
問題:訪問 /superset/login/ 後跳轉到 /login/ → 404
根本原因:
- Superset JavaScript bootstrap 資料中
user_login_url: "/login/"沒有前綴 - 瀏覽器直接訪問
/login/時 Nginx 無法匹配到 Superset
修復方案:在 Nginx 添加多個重定向規則
location = /login/ {
return 302 /superset/login/;
}
location = /logout/ {
return 302 /superset/logout/;
}
location ^~ /lang/ {
return 302 /superset$request_uri;
}
location ^~ /users/ {
return 302 /superset$request_uri;
}
修改檔案:
docker/superset/superset_config.py- 設置x_prefix=0docker/superset/nginx-superset.conf- 更新代理規則和重定向
驗證結果:
| 路徑 | 狀態 |
|---|---|
/superset/ |
✅ 302 → /superset/welcome/ |
/superset/login/ |
✅ 200 (登入頁面) |
/login/ |
✅ 302 → /superset/login/ |
/logout/ |
✅ 302 → /superset/logout/ |
2026-02-07:CI/CD Dashboard + 移除 Harbor
1. Harbor 完全移除,改用 Docker Registry
變更原因:Harbor 資源佔用大、穩定性問題,改用輕量級 Docker Registry
| 項目 | 舊配置 | 新配置 |
|---|---|---|
| Registry URL | harbor.wooo.work |
registry.wooo.work |
| Port | 5050 | 5002 (內部) → Nginx 反向代理 |
| 認證 | Harbor 內建 | Nginx Basic Auth |
| 映像路徑 | harbor.wooo.work/wooo/momo-pro-system:latest |
registry.wooo.work/wooo/momo-pro-system:latest |
新增/修改檔案:
docker/registry/docker-compose.yml- Docker Registry 配置docker/registry/config.yml- Registry 儲存配置config/nginx/sites-available/registry- Nginx 反向代理配置
2. CI/CD Dashboard 完整版
URL: https://mo.wooo.work/cicd
功能:
- 即時 Pipeline 流程視覺化(Test → Build → Deploy)
- UAT/PROD 環境健康狀態卡片
- Pod 狀態監控(透過 SSH 查詢)
- 快速操作按鈕(部署 UAT/PROD、回滾)
- 成功率統計、今日部署次數
- 10 秒自動刷新
新增檔案:
routes/cicd_routes.py- CI/CD API 路由 (1354 行)templates/cicd_dashboard.html- Dashboard 前端頁面
API 端點:
| 端點 | 方法 | 說明 |
|---|---|---|
/api/cicd/status |
GET | 取得完整 CI/CD 狀態 |
/api/cicd/pipelines |
GET | 取得最近 Pipeline 列表 |
/api/cicd/environments |
GET | 取得所有環境狀態 |
/api/cicd/deploy/<env> |
POST | 觸發部署 |
/api/cicd/rollback/<env> |
POST | 回滾部署 |
3. CI/CD UAT 自動部署(歷史紀錄)
2026-04-18 備註: 當時的 CI/CD 建構在 GitLab CI 之上,GitLab 已撤除,以下內容僅作歷史參考。
當時流程:push main → UAT 自動部署
當時 Pipeline 階段:
push main
│
├─ test (pytest)
├─ security-scan (Bandit)
│
├─ build (docker build + push to registry.wooo.work)
│
└─ deploy-uat (SSH → git pull → kubectl restart)
4. 監控告警標籤
Alertmanager (Prometheus) 告警模板:
🏢 <b>環境:</b> <code>UAT</code> (mo.wooo.work)
n8n 頁面健康監控:
- UAT 監控:
n8n-workflows/17-page-health-monitor.json- 告警標題:
🔴 *EwoooC 頁面異常* - 標籤:
(mo.wooo.work / momo.wooo.work)
- 告警標題:
5. wooo 用戶 kubectl 無密碼訪問設定
# 設定 kubeconfig
sudo cp /etc/rancher/k3s/k3s.yaml /home/wooo/.kube/config
sudo chown wooo:wooo /home/wooo/.kube/config
# 加入 bashrc
echo 'export KUBECONFIG=/home/wooo/.kube/config' >> ~/.bashrc
修改檔案清單:
app.py- 註冊 CI/CD Blueprintroutes/cicd_routes.py- 新增templates/cicd_dashboard.html- 新增n8n-workflows/17-page-health-monitor.json- 環境標籤k8s/monitoring/values-prometheus.yaml- Alertmanager 環境標籤
6. PostgreSQL 監控部署 (新增)
部署內容:
k8s/monitoring/postgres-exporter.yaml- PostgreSQL Exporter Deployment + ServiceMonitork8s/monitoring/postgres-alerting-rules.yaml- 資料庫告警規則
監控指標:
| 指標 | 閾值 | 告警等級 |
|---|---|---|
| 連線數 | > 80 | Warning |
| 連線數 | > 95 | Critical |
| 資料庫停機 | pg_up == 0 | Critical |
| 資料庫大小 | > 5GB | Warning |
| 資料庫大小 | > 8GB | Critical |
| 死鎖 | > 0 | Warning |
| 表膨脹 (Dead Tuples) | > 100,000 | Warning |
7. n8n 工作流程匯入完成 (22個)
原有工作流程 (20個):
- 系統監控:磁碟空間、SSL 證書、CI/CD 通知、備份、爬蟲、K8s Pod、Harbor
- 定期報告:每日系統報告、每週業績、月初提醒
- AI 監控:Ollama 健康、K8s 健康、慢查詢
新增工作流程 (2個):
17-uat-health-monitor.json- UAT 健康監控18-postgres-health-monitor.json- PostgreSQL 資料庫監控
工作流程匯入方式:
docker exec momo-n8n n8n import:workflow --input=/home/node/n8n-workflows/<file>.json
8. 集中式監控架構
架構決策:所有監控告警統一由 UAT 主機管理
┌─────────────────────────────────────────────────────────────────┐
│ UAT 主機 (192.168.0.110) │
│ 統一監控與排程中心 │
├─────────────────────────────────────────────────────────────────┤
│ Prometheus → Alertmanager → Telegram │
│ n8n 工作流程 │
│ • 監控 EwoooC App (mo.wooo.work / momo.wooo.work) │
│ • PostgreSQL 健康檢查 │
└─────────────────────────────────────────────────────────────────┘
分工原則:
| 類型 | 工具 | 位置 |
|---|---|---|
| 監控告警 | Prometheus + n8n | UAT 集中管理 |
| 業務排程 | momo-scheduler | K8s 內執行 |
2026-02-02:監控系統修復與安全加固
修復項目:
1. K8s Scheduler CrashLoopBackOff 修復
- 問題:momo-scheduler Pod 重啟 387 次,持續 CrashLoopBackOff
- 原因:
run_scheduler.py檔案遺失 - 解決:建立新的
run_scheduler.py獨立排程腳本 - 新增檔案:
run_scheduler.py
# run_scheduler.py 排程任務
- 每小時:主站爬蟲、EDM 爬蟲
- 每 6 小時:購物節爬蟲
- 每 30 分鐘:Google Drive 自動匯入、網頁白頁監控
2. vendor-stockout 500 錯誤修復
- 問題:訪問
/vendor-stockout/返回 Internal Server Error - 原因:模板位置錯誤 (
vendor_stockout_index.html應為templates/vendor_stockout/index.html) - 解決:建立
templates/vendor_stockout/目錄並移動所有模板
templates/vendor_stockout/
├── index.html
├── list.html
├── history.html
├── import.html
├── send_email.html
└── vendor_management.html
3. Alertmanager 無法發送 Telegram 告警修復
- 問題:Alertmanager 日誌持續報錯
can't evaluate field StartsAt in type *template.Data - 原因:Telegram 訊息模板錯誤,
.StartsAt放在{{ range .Alerts }}區塊外 - 解決:修正模板,將
.StartsAt移入 range 區塊內 - 修改檔案:
k8s/monitoring/values-prometheus.yaml
# 修正前(錯誤)
{{ range .Alerts }}...{{ end }}
⏰ <i>時間: {{ .StartsAt.Local.Format "..." }}</i> # 錯誤:在 range 外
# 修正後(正確)
{{ range .Alerts }}
...
⏰ <i>時間: {{ .StartsAt.Local.Format "..." }}</i> # 正確:在 range 內
{{ end }}
4. n8n 配置損壞修復
- 問題:n8n 容器持續重啟,配置檔案損壞
- 解決:重新寫入正確的 JSON 配置
5. 伺服器安全加固
192.168.0.188 (Ollama Server):
- ✅ 安裝 Fail2Ban (SSH 3 次失敗封鎖 1 小時)
- ✅ 安裝 UFW 防火牆
- ✅ AI 服務限制內網存取 (192.168.0.0/24)
192.168.0.110 (UAT Server):
- ✅ Fail2Ban 已運行 (確認配置正確)
- ✅ SSH + Nginx 雙重保護
UFW 規則 (192.168.0.188):
| 端口 | 服務 | 存取範圍 |
|---|---|---|
| 22 | SSH | 公開 |
| 80/443 | HTTP/HTTPS | 公開 |
| 11434 | Ollama API | 僅內網 |
| 3000 | Open WebUI | 僅內網 |
| 5678 | n8n | 僅內網 |
| 8080 | SearXNG | 僅內網 |
監控系統現況:
Prometheus (抓取指標) → PrometheusRule (告警規則) → Alertmanager → Telegram Bot
目前告警規則:
- PodOOMKilled, PodRestartTooMany, PodNotReady, PodPending
- HighMemoryUsage, MemoryNearLimit, HighCPUUsage
- PostgresDown, PVCSpaceLow
- MomoAppDown, HighHTTP5xxRate
- NodeMemoryLow, NodeDiskLow, NodeNotReady
2026-01-31:系統重開機自動啟動機制
問題發現:
- 伺服器重開機後 Registry 容器未正常啟動 (Exit 128)
- K8s Pod 顯示
ImagePullBackOff無法拉取映像 - mo.wooo.work 返回 502 Bad Gateway
- 系統負載過高 (load average 112)
根本原因:
- Registry 容器重開機後未自動啟動
- Supabase 不必要服務佔用大量資源
- 沒有統一的服務啟動順序管理
解決方案:
- 建立
scripts/tools/system_startup.sh統一啟動腳本 - 建立
momo-startup.servicesystemd 服務 - 啟動順序:Docker → 停止 Supabase 多餘服務 → Registry → K8s → 監控
- 每個服務啟動後進行健康檢查
- 啟動完成後發送 Telegram 通知
新增檔案:
scripts/tools/system_startup.sh- 系統啟動腳本scripts/tools/momo-startup.service- systemd 服務定義deploy/lib/registry.sh- Registry 管理函數庫deploy/lib/k8s.sh- K8s 管理函數庫deploy/lib/monitoring.sh- 監控與通知函數庫deploy/lib/systemd.sh- Systemd 服務管理函數庫
部署步驟:
# 1. 上傳腳本
scp scripts/tools/system_startup.sh wooo@192.168.0.110:/home/wooo/momo_pro_system/scripts/tools/
# 2. 安裝 systemd 服務
sudo cp /tmp/momo-startup.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable momo-startup.service
驗證方式:
# 確認服務已啟用
systemctl is-enabled momo-startup.service # 應返回 enabled
# 查看啟動日誌
sudo journalctl -u momo-startup.service
2026-01-28:502 Bad Gateway 排查與自動修復
問題發現:
- mo.wooo.work 返回 502 Bad Gateway
- Nginx 無法連接到後端 Docker 容器
排查過程:
- 檢查 Docker 容器狀態 → 顯示 healthy
- 測試外部端口
curl 127.0.0.1:5001→ Connection reset by peer - 測試容器內部
docker exec curl→ HTTP 200 正常 - 診斷結論:Docker 網路轉發失效
解決方案:
sudo systemctl restart docker
新增功能:
- 新增自動化監控腳本
scripts/docker_health_monitor.sh - 每 5 分鐘自動檢查服務健康狀態
- 檢測到 Docker 網路問題時自動修復
- 發送 Telegram 告警通知
修改檔案:
CLAUDE.md- 新增問題 #4, #5 和自動修復文檔scripts/docker_health_monitor.sh- Docker 網路監控腳本scripts/registry_health_monitor.sh- Registry 服務監控腳本k8s/04-momo-app.yaml- 改用 registry.wooo.work 域名k8s/05-scheduler.yaml- 改用 registry.wooo.work 域名
2026-01-28:Registry 服務中斷與 K8s 映像拉取修復
問題發現:
- Google Drive 自動匯入功能停止
- K8s Pods 顯示
ImagePullBackOff
根本原因:
- Docker Registry 服務停止
- Registry 端口綁定 127.0.0.1:5000(安全配置)
- K8s 嘗試從 192.168.0.110:5000 拉取映像失敗
解決方案:
- 啟動 Registry:
cd /home/wooo/devops/registry && docker compose up -d - K8s 配置改用 HTTPS 域名
registry.wooo.work - 重建 registry secret 使用新域名
- 重啟 K8s Deployments
預防措施:
- 建立 Registry 健康監控腳本
- 加入 cron 排程自動檢查
- UAT crontab - 新增排程任務
2026-01-28:當日業績匯入 OOM 問題修復
問題發現:
- 自動匯入通知發送成功,但
/daily_sales頁面顯示「資料表為空」 - 匯入任務卡在 60% 進度
排查過程:
- 檢查
import_jobs表發現任務狀態為importing,進度 60% - 查看 Docker 日誌發現
Worker was sent SIGKILL! Perhaps out of memory? - 確認 OOM 導致匯入進程被殺死
解決方案:
- 找到暫存檔案
/app/data/temp/即時業績_當日.xlsx(匯入中途失敗但已下載) - 手動觸發匯入:
from services.import_service import import_service import os file_path = '/app/data/temp/即時業績_當日.xlsx' job_id = import_service.create_import_job('daily_sales', None, '即時業績_當日.xlsx', os.path.getsize(file_path)) import_service.process_daily_sales_import(job_id, file_path) - 成功匯入 19,099 筆資料(2026-01-01 ~ 2026-01-27)
資料流向說明(重要):
Excel 檔案 → import_service.process_daily_sales_import()
│
├→ daily_sales_snapshot (主資料表,77欄位,含 snapshot_date)
│
└→ realtime_sales_monthly (副本,28欄位,供業績分析儀表板)
- 正確方向:
daily_sales_snapshot→realtime_sales_monthly(同步寫入) - 禁止反向操作:不可從
realtime_sales_monthly同步回daily_sales_snapshot
修改檔案:
services/import_service.py- 新增日期範圍追蹤scheduler.py- 增強匯入通知格式scripts/google_drive_monitor.sh- Google Drive 認證監控scripts/system_health_monitor.sh- 統一健康監控腳本
2026-01-28:Ollama 502 Bad Gateway 修復與監控機制
問題發現:
http://192.168.0.188/返回 502 Bad Gateway- Ollama API
http://192.168.0.188:11434/api/tags正常回應
診斷過程:
- 檢查 nginx 進程 → 正常運行
- 檢查 nginx error.log →
recv() failed (104: Unknown error)指向127.0.0.1:3000 - 發現 nginx 代理到 Open WebUI 容器 (port 3000),非直接代理 Ollama
- 檢查 Open WebUI 容器 → 容器內部正常,但外部無法連接
- 診斷結論:Docker 端口映射失效
解決方案:
ssh ollama@192.168.0.188
sudo systemctl restart docker
# 等待 60 秒後所有容器恢復
新增監控機制:
- 監控腳本:
scripts/ollama_health_monitor.sh - n8n 工作流程:
n8n-workflows/14-ollama-health-monitor.json - 排程: 每 5 分鐘執行 (cron)
- 自動修復:
- Open WebUI 502 → 重啟 Docker daemon
- Open WebUI 容器卡住 → 重啟容器
- Nginx 停止 → 重啟 nginx
- Ollama 停止 → 重啟 Ollama
部署到 192.168.0.188:
# 1. 上傳監控腳本
scp scripts/ollama_health_monitor.sh ollama@192.168.0.188:/home/ollama/scripts/
# 2. 設定 cron
*/5 * * * * /home/ollama/scripts/ollama_health_monitor.sh >> /var/log/ollama_health_monitor.log 2>&1
# 3. 設定 sudoers(無密碼重啟)
ollama ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart docker, /usr/bin/systemctl restart nginx, /usr/bin/systemctl restart ollama
修改檔案:
scripts/ollama_health_monitor.sh- 新增 Ollama/Open WebUI 監控腳本n8n-workflows/14-ollama-health-monitor.json- 新增 n8n 工作流程CLAUDE.md- 更新 Ollama 監控文檔
2026-01-25:DevSecOps 安全強化 + WireGuard VPN
Registry 安全配置:
- 端口 5000 改為僅綁定 127.0.0.1 (內部)
- 外部訪問改用
registry.wooo.work(HTTPS) - CI/CD 腳本更新使用域名
- 減少攻擊面
WireGuard VPN (WG-Easy):
- 部署於 Kali Linux (192.168.0.112)
- 管理介面:
http://192.168.0.112:51821 - 外部端點:
114.32.151.246:51820/udp - QR Code 掃描連線
CI/CD 安全掃描(已退役,待新方案重建):
- 曾在 GitLab CI 上設置
security-code-scan(每次 Push 執行 Bandit)與container-security-scan(每週 Trivy 容器弱點掃描) - 掃描結果自動發送 Telegram 通知
- 隨 GitLab 撤除而停用,後續需在新 CI/CD 平台重建
SSL/TLS 安全審核 (SSLyze):
- mo.wooo.work 掃描結果:✅ 全部通過
- SSL 2.0/3.0, TLS 1.0/1.1 已禁用
- TLS 1.2/1.3 啟用強加密套件
- HSTS 已啟用,無 Heartbleed/CRIME 弱點
Trivy 容器掃描結果:
- 掃描
192.168.0.110:5050/wooo/momo-pro-system:latest - HIGH: 56 (Debian 基礎映像)
- CRITICAL: 0
- Python 套件: 0 弱點
Kali Linux DevSecOps 工作站 (192.168.0.112):
- 建立集中式安全掃描環境
- 部署
port_monitor.py:Nmap 端口監控,每小時執行 - 部署
code_security_scan.py:Bandit 程式碼掃描,每日執行 - 建立端口基線:9 個端口 (192.168.0.110: 7, 192.168.0.188: 2)
- 程式碼掃描結果:16 HIGH, 65 MEDIUM, 72 LOW
2026-01-24:K8s 配置優化 + Rancher 部署
K8s Google Drive 認證修復:
- 問題:K8s Secret 為唯讀,OAuth Token 無法刷新
- 解法:使用 initContainer 將認證複製到 emptyDir(可寫入)
- 修改檔案:
k8s/04-momo-app.yaml、k8s/05-scheduler.yaml - 新增 Secret:
google-drive-credentials
Ollama AI 配置更新:
- Host 更新為
http://192.168.0.188:11434(原本錯誤指向 192.168.0.110) - 模型更新為
llama3:70b-instruct-q2_K - 修改檔案:
k8s/02-configmap.yaml
n8n 白頁修復:
- 問題:子路徑
/n8n/顯示空白頁面 - 解法:新增環境變數
N8N_PATH_PREFIX=/n8n - 修改檔案:UAT
docker-compose.yml
Rancher 部署 + K3s 匯入:
- 安裝 Rancher v2.13.1 via Docker
- URL:
https://192.168.0.110:8443 - K3s 集群
momo-k3s已成功匯入 - Cluster ID:
c-52mz8 - 修改檔案:
k8s/nginx/monitor.conf(新增/rancher/代理)
2026-01-24:K8s 遷移完成
重大變更:
- ✅ K3s 部署完成 - 版本 v1.34.3+k3s1
- ✅ PostgreSQL 資料遷移完成 - 資料庫:
momo_analytics - ✅ VM Nginx 配置更新 - 指向 K8s ClusterIP
K8s 資源:
| 資源 | 說明 |
|---|---|
| momo-app | Flask 應用 Deployment |
| momo-postgres | PostgreSQL StatefulSet |
| momo-scheduler | 爬蟲排程 Deployment |
| momo-data-pvc | 應用資料 PVC (5Gi) |
| postgres-pvc | 資料庫 PVC (10Gi) |
網路架構:
用戶 → mo.wooo.work:443 → VM Nginx (SSL) → K8s ClusterIP 10.43.238.49:80 → momo-app
備份位置:
/home/wooo/backups/pre-k8s-migration/- 回滾腳本:
quick_rollback.sh
2026-01-22:CI/CD 初版部署(已退役)
2026-04-18 備註: 原本以 GitLab CE + Docker Registry + Watchtower 為核心的 CI/CD 架構已撤除,此段僅作歷史紀錄。Docker Registry 與 Watchtower 仍保留在 UAT 運作。
當時架構重點:
- 自建 Git 伺服器 + CI/CD 平台(已撤除)
- Docker Registry: 私有 Container Registry(保留,位於 registry.wooo.work)
- Watchtower: 自動偵測 Registry 映像更新並部署(保留)
- 部署位置: UAT Server (192.168.0.110)
當時 CI/CD 流程:
git push → CI 測試 → 構建 Docker Image → 推送到 Registry → Watchtower 自動更新容器
2026-01-22:PostgreSQL 相容性修復
問題:sales_analysis 頁面的「星期幾」和「時段」篩選功能在 PostgreSQL 環境下失效
原因:SQLite 使用 strftime('%w', timestamp) 取得星期幾,PostgreSQL 使用 EXTRACT(dow FROM timestamp)
修復內容:
- 更新
app.py中的get_sales_table_data()函數 - 根據
DATABASE_TYPE動態選擇正確的 SQL 語法 - 修復 SQLite 日期字串格式問題(PostgreSQL 返回
datetime物件)
修改檔案:
app.py(約 line 2800-2900)config.py- 新增DATABASE_TYPE變數
驗證:API /api/sales_table?dow=1&hour=14 在 PostgreSQL 環境正常運作
2026-01-23:商品看板效能優化
問題:商品看板首頁載入緩慢(約 3-4 秒)
診斷結果:
- 資料庫有 5,510 商品、609,173 價格記錄
price_records表缺少product_id索引- 多個 gunicorn worker 同時重建快取
優化措施:
1. PostgreSQL 索引優化
CREATE INDEX CONCURRENTLY idx_price_records_product_id ON price_records(product_id);
CREATE INDEX CONCURRENTLY idx_price_records_product_timestamp ON price_records(product_id, timestamp DESC);
CREATE INDEX idx_products_status ON products(status);
2. 跨進程快取鎖定(FileLock)
- 將
threading.Lock()替換為fcntl.flock()檔案鎖 - 解決多 gunicorn worker 同時重建快取的問題
- 鎖定檔案位置:
data/.dashboard_cache.lock
修改檔案:
routes/dashboard_routes.py- 新增FileLock類別,更新get_full_dashboard_data()函數
效能改善:
| 情境 | 優化前 | 優化後 |
|---|---|---|
| 快取命中 | ~1 秒 | ~1 秒 |
| 快取重建(單一 worker) | ~3-4 秒 | ~3-4 秒 |
| 快取重建(多 worker) | 每個各 3-4 秒 | 只有一個重建 |
FileLock 實作細節
import fcntl
class FileLock:
"""簡單的檔案鎖,用於 gunicorn 多進程環境"""
def __init__(self, lock_file):
self.lock_file = lock_file
self.fd = None
def acquire(self, blocking=True):
try:
self.fd = open(self.lock_file, 'w')
if blocking:
fcntl.flock(self.fd, fcntl.LOCK_EX)
else:
fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
return True
except (IOError, OSError):
if self.fd:
self.fd.close()
self.fd = None
return False
def release(self):
if self.fd:
fcntl.flock(self.fd, fcntl.LOCK_UN)
self.fd.close()
self.fd = None
使用方式:
_DASHBOARD_FILE_LOCK = FileLock('/path/to/data/.dashboard_cache.lock')
# 取得鎖(非阻塞)
if not _DASHBOARD_FILE_LOCK.acquire(blocking=False):
# 其他 worker 正在重建,等待
_DASHBOARD_FILE_LOCK.acquire()
_DASHBOARD_FILE_LOCK.release()
return cached_data
try:
# 重建快取...
finally:
_DASHBOARD_FILE_LOCK.release()
資料庫表結構
核心業務表
daily_sales_snapshot- 每日銷售快照 (snapshot_date 欄位)realtime_sales_monthly- 業績分析儀表板資料 (日期 欄位)products- 商品資料price_records- 價格記錄
廠商缺貨系統
vendor_stockout- 缺貨商品清單vendor_list- 廠商資料vendor_emails- 廠商郵件地址email_send_log- 郵件發送記錄
系統表
users- 用戶帳號permissions- 權限定義user_permissions- 用戶權限關聯import_jobs- 匯入任務記錄import_config- 匯入設定
部署指令(Docker-on-188,見 ADR-008)
SSH 進入 188(必經 110 跳板)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188
同步 Python 檔案到 188(volume mount,即時生效)
# 經 110 跳板
scp -o ProxyJump=wooo@192.168.0.110 app.py ollama@192.168.0.188:/home/ollama/momo-pro/
scp -o ProxyJump=wooo@192.168.0.110 -r services/ ollama@192.168.0.188:/home/ollama/momo-pro/
重啟主應用(volume mount 後)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker restart momo-pro-system"
重建映像(新增套件 / Dockerfile 變更)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "cd /home/ollama/momo-pro && docker compose build momo-app && docker compose up -d momo-app"
查看日誌
# momo-pro-system
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker logs -f momo-pro-system --tail 100"
# scheduler
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker logs -f momo-scheduler --tail 100"
# PostgreSQL (pgvector)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker logs -f momo-db --tail 100"
進入容器 Shell
# 進入主應用
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker exec -it momo-pro-system /bin/bash"
# 進入 PostgreSQL(pgvector/pg14)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker exec -it momo-db psql -U momo -d momo_analytics"
待辦:細粒度權限系統實作計畫
需求總結
將現有的三級角色權限系統 (admin/manager/user) 升級為細粒度權限配置系統:
- 保留角色概念:作為「預設權限模板」,新增用戶時快速套用
- 權限粒度:分為「查看」和「操作」兩層
- 不需要權限群組功能
現有系統分析
已有的基礎設施
| 檔案 | 說明 |
|---|---|
database/user_models.py |
User 和 LoginHistory 模型已存在 |
services/user_service.py |
用戶 CRUD 服務已存在 |
services/password_service.py |
密碼服務已存在 |
routes/user_routes.py |
用戶管理路由已存在 |
templates/user_management.html |
用戶管理頁面已存在 |
auth.py |
login_required, role_required 裝飾器已存在 |
需要擴展的部分
- User 模型需新增 permissions 欄位或關聯表
- 新增 Permission 模型和 UserPermission 關聯表
- 新增 permission_required 裝飾器
- 更新用戶管理介面,增加權限勾選區塊
- 更新導航列,根據權限動態顯示選單
資料庫設計
新增表: permissions (權限定義表)
class Permission(db.Model):
"""權限定義表 - 系統預設,不可刪除"""
__tablename__ = 'permissions'
id = Column(Integer, primary_key=True)
code = Column(String(50), unique=True, nullable=False) # 如 'dashboard.view'
name = Column(String(100), nullable=False) # 顯示名稱 '查看首頁看板'
category = Column(String(50), nullable=False) # 分類 '首頁/看板'
description = Column(String(200)) # 詳細說明
sort_order = Column(Integer, default=0) # 排序順序
新增表: user_permissions (用戶權限關聯表)
class UserPermission(db.Model):
"""用戶權限關聯表"""
__tablename__ = 'user_permissions'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
permission_code = Column(String(50), nullable=False)
granted_by = Column(Integer, ForeignKey('users.id'))
granted_at = Column(DateTime, default=datetime.utcnow)
# 複合唯一索引
__table_args__ = (
UniqueConstraint('user_id', 'permission_code', name='uq_user_permission'),
)
權限清單定義
首頁/看板
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
dashboard.view |
查看首頁看板 | 訪問 / 首頁 |
dashboard.export |
匯出看板資料 | 匯出商品資料 Excel |
報表
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
report.daily_sales.view |
查看每日銷售 | 訪問 /daily_sales |
report.daily_sales.export |
匯出每日銷售 | 匯出每日銷售 Excel |
report.monthly_summary.view |
查看月度總結 | 訪問 /monthly_summary_analysis |
report.monthly_summary.import |
匯入月度資料 | 匯入月度總結 Excel |
report.sales_analysis.view |
查看銷售分析 | 訪問 /sales_analysis |
report.growth_analysis.view |
查看成長分析 | 訪問 /growth_analysis |
report.abc_analysis.view |
查看 ABC 分析 | 訪問 /abc_analysis/detail |
活動看板
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
edm.view |
查看 EDM 看板 | 訪問 /edm |
edm.trigger |
觸發 EDM 爬蟲 | 手動觸發爬蟲按鈕 |
festival.view |
查看節慶看板 | 訪問 /festival |
festival.trigger |
觸發節慶爬蟲 | 手動觸發爬蟲按鈕 |
廠商缺貨
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
vendor.index.view |
查看廠商缺貨首頁 | 訪問 /vendor_stockout/ |
vendor.import |
匯入缺貨資料 | 匯入缺貨 Excel |
vendor.list.view |
查看缺貨清單 | 訪問 /vendor_stockout/list |
vendor.list.edit |
編輯缺貨資料 | 編輯/刪除缺貨記錄 |
vendor.management.view |
查看廠商管理 | 訪問 /vendor_stockout/vendor-management |
vendor.management.edit |
管理廠商資料 | 新增/編輯/刪除廠商 |
vendor.email.view |
查看郵件發送 | 訪問 /vendor_stockout/send-email |
vendor.email.send |
發送廠商郵件 | 發送缺貨通知郵件 |
vendor.history.view |
查看歷史記錄 | 訪問 /vendor_stockout/history |
匯入
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
import.auto.view |
查看自動匯入 | 訪問 /auto_import |
import.auto.manage |
管理匯入任務 | 新增/編輯/刪除任務 |
import.manual |
手動匯入資料 | 系統設定頁匯入按鈕 |
系統
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
system.settings.view |
查看系統設定 | 訪問 /settings |
system.settings.edit |
修改系統設定 | 儲存設定變更 |
system.advanced.view |
查看進階設定 | 訪問 /system_settings |
system.advanced.edit |
修改進階設定 | 分類管理等 |
system.logs.view |
查看系統日誌 | 訪問 /logs |
system.crawler.view |
查看爬蟲管理 | 訪問 /crawler_management |
system.crawler.manage |
管理爬蟲設定 | 修改爬蟲設定 |
system.backup |
備份資料庫 | 執行備份操作 |
system.users.view |
查看用戶管理 | 訪問 /user_management |
system.users.manage |
管理用戶帳號 | 新增/編輯/刪除用戶 |
其他
| 權限代碼 | 名稱 | 說明 |
|---|---|---|
brand_assets.view |
查看品牌素材 | 訪問 /brand_assets |
總計: 31 個權限項目
角色預設權限模板
admin (管理員)
- 全部 31 個權限
manager (管理者)
- 所有
.view權限 dashboard.exportreport.daily_sales.exportreport.monthly_summary.importvendor.import,vendor.list.edit,vendor.management.edit,vendor.email.sendimport.auto.manage,import.manualsystem.settings.edit- 排除:
system.users.*,system.backup,system.advanced.edit,system.crawler.manage
user (一般用戶)
dashboard.viewreport.daily_sales.view,report.monthly_summary.view,report.sales_analysis.view,report.growth_analysis.view,report.abc_analysis.viewedm.view,festival.viewvendor.index.view,vendor.list.view,vendor.history.view
修改檔案清單
新增檔案
| 檔案 | 說明 |
|---|---|
database/permission_models.py |
Permission 和 UserPermission 模型 |
services/permission_service.py |
權限 CRUD 服務、角色模板應用 |
templates/user_permissions.html |
用戶權限編輯頁面 (獨立頁面或 Modal) |
修改檔案
| 檔案 | 修改內容 |
|---|---|
auth.py |
新增 permission_required 裝飾器、更新 get_current_user() |
routes/user_routes.py |
新增權限 CRUD API |
templates/user_management.html |
新增「編輯權限」按鈕 |
app.py |
註冊權限 context_processor、初始化權限資料 |
database/manager.py |
新增權限表初始化 |
需更新權限檢查的路由檔案
| 檔案 | 說明 |
|---|---|
routes/dashboard_routes.py |
首頁看板 |
routes/daily_sales_routes.py |
每日銷售 |
routes/monthly_routes.py |
月度總結 |
routes/sales_routes.py |
銷售分析、成長分析 |
routes/edm_routes.py |
EDM、節慶看板 |
routes/system_routes.py |
系統設定、日誌 |
vendor_routes.py |
廠商缺貨相關 |
auto_import_routes.py |
自動匯入 |
crawler_management_routes.py |
爬蟲管理 |
實作步驟
Phase 1: 資料庫模型 (預計 1 步)
-
建立
database/permission_models.py- Permission 模型
- UserPermission 模型
- 權限常數定義 (PERMISSIONS 字典)
- 角色預設權限模板 (ROLE_DEFAULT_PERMISSIONS)
-
更新
database/manager.py- 在
init_db()中初始化權限表資料
- 在
Phase 2: 服務層 (預計 1 步)
- 建立
services/permission_service.pyget_all_permissions()- 取得所有權限定義 (分類顯示)get_user_permissions(user_id)- 取得用戶權限列表set_user_permissions(user_id, permission_codes, granted_by)- 設定用戶權限apply_role_template(user_id, role)- 套用角色預設權限has_permission(user_id, permission_code)- 檢查是否有權限has_any_permission(user_id, *permission_codes)- 檢查是否有任一權限
Phase 3: 認證與裝飾器 (預計 1 步)
- 更新
auth.py- 新增
permission_required(*permissions)裝飾器 - 更新
get_current_user()增加 permissions 欄位 - 登入時載入用戶權限到 session (或每次查詢)
- 新增
Phase 4: API 路由 (預計 1 步)
- 更新
routes/user_routes.pyGET /api/permissions- 取得所有權限定義GET /api/users/<user_id>/permissions- 取得用戶權限PUT /api/users/<user_id>/permissions- 更新用戶權限POST /api/users/<user_id>/apply_role_template- 套用角色模板
Phase 5: 前端介面 (預計 1 步)
- 建立用戶權限編輯介面
- 可在
user_management.html新增 Modal 或獨立頁面 - 按分類顯示權限勾選框
- 「套用角色模板」下拉選單
- 「全選」/「清除」按鈕
- 可在
Phase 6: 套用權限檢查 (預計 2-3 步)
- 更新各路由檔案,將
@role_required改為@permission_required - 更新導航列模板,根據權限動態顯示選單項目
- 更新頁面內的操作按鈕,根據權限顯示/隱藏
Phase 7: 測試驗證 (預計 1 步)
- 建立測試用戶並配置不同權限
- 驗證各頁面和功能的權限控制
- 確認角色模板套用正確
權限裝飾器設計
def permission_required(*permissions):
"""權限檢查裝飾器
使用範例:
@permission_required('dashboard.view')
@permission_required('vendor.list.view', 'vendor.list.edit')
"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not session.get('logged_in'):
return redirect(url_for('login'))
user_id = session.get('user_id')
user_role = session.get('role')
# admin 擁有所有權限
if user_role == 'admin':
return f(*args, **kwargs)
# 檢查用戶是否有任一所需權限
from services.permission_service import PermissionService
if not PermissionService.has_any_permission(user_id, *permissions):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
用戶權限編輯介面設計
┌─────────────────────────────────────────────────┐
│ 編輯權限: peter (Peter Chen) │
├─────────────────────────────────────────────────┤
│ 快速設定: [套用角色模板 ▼] [全選] [清除] │
├─────────────────────────────────────────────────┤
│ │
│ 📊 首頁/看板 │
│ ├─ ☑ 查看首頁看板 │
│ └─ ☐ 匯出看板資料 │
│ │
│ 📈 報表 │
│ ├─ ☑ 查看每日銷售 │
│ ├─ ☐ 匯出每日銷售 │
│ ├─ ☑ 查看月度總結 │
│ ├─ ☐ 匯入月度資料 │
│ ├─ ☑ 查看銷售分析 │
│ ├─ ☑ 查看成長分析 │
│ └─ ☐ 查看 ABC 分析 │
│ │
│ 📣 活動看板 │
│ ├─ ☑ 查看 EDM 看板 │
│ ├─ ☐ 觸發 EDM 爬蟲 │
│ ├─ ☑ 查看節慶看板 │
│ └─ ☐ 觸發節慶爬蟲 │
│ │
│ 🏭 廠商缺貨 │
│ ├─ ☐ 查看廠商缺貨首頁 │
│ ├─ ☐ 匯入缺貨資料 │
│ ├─ ☐ 查看缺貨清單 │
│ ├─ ☐ 編輯缺貨資料 │
│ ├─ ☐ 查看廠商管理 │
│ ├─ ☐ 管理廠商資料 │
│ ├─ ☐ 查看郵件發送 │
│ ├─ ☐ 發送廠商郵件 │
│ └─ ☐ 查看歷史記錄 │
│ │
│ 📥 匯入 │
│ ├─ ☐ 查看自動匯入 │
│ ├─ ☐ 管理匯入任務 │
│ └─ ☐ 手動匯入資料 │
│ │
│ ⚙️ 系統 │
│ ├─ ☐ 查看系統設定 │
│ ├─ ☐ 修改系統設定 │
│ ├─ ☐ 查看進階設定 │
│ ├─ ☐ 修改進階設定 │
│ ├─ ☐ 查看系統日誌 │
│ ├─ ☐ 查看爬蟲管理 │
│ ├─ ☐ 管理爬蟲設定 │
│ ├─ ☐ 備份資料庫 │
│ ├─ ☐ 查看用戶管理 │
│ └─ ☐ 管理用戶帳號 │
│ │
│ 📦 其他 │
│ └─ ☑ 查看品牌素材 │
│ │
├─────────────────────────────────────────────────┤
│ [取消] [儲存權限] │
└─────────────────────────────────────────────────┘
導航列動態顯示
更新 templates/components/_navbar.html,根據權限決定顯示哪些選單項目:
{% if has_permission('dashboard.view') %}
<a class="nav-link" href="/">首頁</a>
{% endif %}
{% if has_permission('report.daily_sales.view') %}
<a class="nav-link" href="/daily_sales">每日銷售</a>
{% endif %}
{# 廠商缺貨子選單 - 有任一權限就顯示 #}
{% if has_any_permission('vendor.index.view', 'vendor.list.view', 'vendor.management.view') %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#">廠商缺貨</a>
<ul class="dropdown-menu">
{% if has_permission('vendor.index.view') %}
<li><a class="dropdown-item" href="/vendor_stockout/">首頁</a></li>
{% endif %}
...
</ul>
</li>
{% endif %}
驗證計畫
-
資料庫測試
- 確認 permissions 和 user_permissions 表正確建立
- 確認初始權限資料正確載入
-
API 測試
- 取得權限列表 API
- 更新用戶權限 API
- 套用角色模板 API
-
權限控制測試
- 建立測試用戶,僅給予
dashboard.view和report.daily_sales.view - 確認可以訪問首頁和每日銷售
- 確認無法訪問廠商缺貨、系統設定等頁面 (403)
- 確認導航列只顯示有權限的選單
- 建立測試用戶,僅給予
-
角色模板測試
- 套用 manager 模板,確認權限正確
- 套用 user 模板,確認權限正確
關鍵檔案路徑
- 新增:
database/permission_models.py - 新增:
services/permission_service.py - 修改:
auth.py(新增裝飾器) - 修改:
routes/user_routes.py(新增 API) - 修改:
templates/user_management.html(新增權限編輯) - 修改:
app.py(context_processor) - 修改: 各路由檔案 (套用權限檢查)
專案憲法 (CONSTITUTION.md)
本文件定義專案開發的核心準則與不可違反的規範 建立日期: 2026-01-12 當前版本: V9.4
第一章:資料庫與模型層規範
第 1 條:商品 ID 命名規範(絕對禁止違反)
- ✅ 正確: 使用
product.i_code作為商品唯一識別碼 - ❌ 禁止: 使用
product.momo_id(此屬性不存在)
第 2 條:時間戳處理規範(絕對禁止違反)
- ✅ 正確: 使用
datetime.now(TAIPEI_TZ).replace(tzinfo=None) - ❌ 禁止: 直接使用
datetime.now()或保留 tzinfo - 理由: SQLite 不支援時區感知的 datetime
第 3 條:價格變動邏輯(絕對禁止違反)
- ✅ 正確: 比對「今日最新價格」與「今日之前的最後一筆價格」
- ❌ 禁止: 僅查詢「昨天 00:00-23:59」的價格記錄
第 4 條:查詢效能優化(強制要求)
- ✅ 正確: 使用批次查詢(如
yesterday_prices_map) - ❌ 禁止: N+1 查詢模式
第二章:爬蟲與資料採集規範
第 5 條:商品圖片 URL 構造(絕對禁止違反)
- ✅ 正確: 使用 CDN 直接構造
image_url = f"https://m.momoshop.com.tw/moscdn/goods/{i_code}_m.webp" - ❌ 禁止: 使用複雜的 DOM 查詢
第 6 條:爬蟲頻率與禮貌性(強制要求)
- ✅ 正確: 每次請求間隔至少 1 秒
- ❌ 禁止: 高頻率無間隔爬取
第三章:API 設計規範
第 8 條:API 邏輯一致性(絕對禁止違反)
- ✅ 正確: API 的資料處理邏輯必須與儀表板完全一致
- ❌ 禁止: API 與前端使用不同的計算邏輯
第 9 條:API 錯誤處理(強制要求)
- ✅ 正確: 所有 API 必須使用 try-except-finally 結構
- ✅ 正確: 錯誤時返回 JSON 格式:
{'products': []}, 500 - ❌ 禁止: 返回 HTML 錯誤頁面或純文字錯誤
第四章:前端 UI/UX 規範
第 11 條:設計系統色彩(絕對禁止違反)
- ✅ 主題色: 紫色漸變
#667eea→#764ba2 - ✅ 漲價: 紅色
#dc3545/#ff6b6b - ✅ 降價: 綠色
#28a745/#51cf66
第 12 條:響應式設計(強制要求)
- ✅ 正確: 所有頁面必須支援手機版(< 768px)
- ✅ 正確: 使用 Bootstrap 5.3.3
第五章:系統架構規範
第 15 條:服務端口(絕對禁止違反)
- ✅ 正確: Flask 使用 Port 80
- ❌ 禁止: 使用 5888 或其他端口(已廢棄)
第 16 條:資料庫路徑(絕對禁止違反)
- ✅ 正確:
data/momo_database.db
第 17 條:時區設定(絕對禁止違反)
- ✅ 正確: 使用
TAIPEI_TZ = pytz.timezone('Asia/Taipei')
第 18 條:日誌系統(強制要求)
- ✅ 正確: 使用
sys_log.info()/sys_log.error()記錄關鍵操作 - ❌ 禁止: 使用
print()輸出日誌
第十章:安全性規範
第 31 條:敏感資訊保護(絕對禁止違反)
- ✅ 正確: 所有 API Token、密碼存放於
config.py - ❌ 禁止: 硬編碼敏感資訊於程式碼中
第 32 條:SQL 注入防護(絕對禁止違反)
- ✅ 正確: 使用 SQLAlchemy ORM 的參數化查詢
- ❌ 禁止: 使用字串拼接建構 SQL 查詢
附錄 A:常見錯誤與解決方案
| 錯誤 | 原因 | 解決 |
|---|---|---|
| 'Product' object has no attribute 'momo_id' | 使用錯誤的屬性名稱 | 改用 product.i_code |
| API 返回空資料 | 價格比對邏輯錯誤(只查昨天) | 使用「今日之前最後一筆」邏輯 |
| 時間戳比對失敗 | 時區感知 datetime 與 naive datetime 混用 | 使用 .replace(tzinfo=None) 統一為 naive |
專案憲法 - 擴充版 (PROJECT_CONSTITUTION.md)
版本: 1.3 最後更新: 2026-01-14
第一章:溝通規範
第 1 條:語言使用
- 所有溝通一律使用繁體中文
- 包含:程式碼註解、文檔說明、Commit 訊息、錯誤訊息、日誌輸出
第二章:安全政策
第 4 條:敏感資訊管理
- 禁止在程式碼中硬編碼任何敏感資訊
- 所有憑證、API 金鑰、密碼必須使用環境變數(
.env)
第 5 條:密碼安全
- 所有密碼必須使用
pbkdf2:sha256雜湊儲存 - 密碼長度至少 8 個字元
- 登入失敗 5 次後鎖定帳號 5 分鐘
第 7 條:CSRF 防護
- 所有 POST/PUT/DELETE/PATCH 請求必須包含 CSRF token
- HTML 表單使用:
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> - AJAX 請求使用:
'X-CSRFToken': getCSRFToken()
第四章:數據爬取規範
第 13 條:爬蟲程式碼穩定性原則
- 爬蟲程式碼屬於核心業務邏輯,修改時必須格外謹慎
- 修改前必須備份現有可運作的版本
- 修改後必須驗證所有爬蟲任務正常執行
第 14 條:爬蟲選擇器維護
- CSS 選擇器和 XPath 是脆弱的依賴
- 修改選擇器前必須記錄修改原因
- 保留舊選擇器作為註解備份
第 15 條:爬蟲錯誤處理
- 所有爬蟲函數必須包含完整的錯誤處理
- 必須處理:網路連線失敗、頁面載入超時、元素找不到、資料格式異常、反爬蟲機制觸發
第六章:部署與維運
第 27 條:環境管理規範(2026-04-18 依 ADR-008 改寫)
環境分層:
| 環境 | 位置 | 用途 |
|---|---|---|
| 開發環境 | /Users/ooo/Library/Mobile Documents/com~apple~CloudDocs/momo-pro-system/ (macOS,iCloud) |
程式碼開發、快速測試 |
| 正式環境 | /home/ollama/momo-pro/ 於 192.168.0.188(Docker Compose) |
生產服務、24/7 運行 |
嚴格禁止:
- ❌ 直接在 188 生產環境隨意改檔案(應走 scp 同步 SOP)
- ❌ 跳過本地測試直接部署到 188
- ❌ 將
.env或資料庫密碼檔上傳到公開 Git
第 28 條:變更前強制備份原則 ⚠️
核心原則:
- 所有涉及嚴重影響的變更、修改操作,變更前必須先進行完整備份
第 29 條:部署強制規範(2026-04-18 依 ADR-008 改寫)⚠️
核心原則:
- 188 正式環境為 Docker Compose + volume mount,目前無 Git 版控(本地 Mac 有),CI/CD 方案待定
- 程式碼變更必先於本地測試,再以 scp(經 110 跳板)同步到
ollama@188:~/momo-pro/ - 重大結構變更同步記入 ADR + CLAUDE.md 更新記錄
官方唯一部署流程:
- 本地 Mac 修改程式碼 + 本地測試通過
- 經 110 跳板 scp 到 188:
scp -o ProxyJump=wooo@192.168.0.110 <檔案> ollama@192.168.0.188:/home/ollama/momo-pro/<目標> - 依檔案類型處理:
- Python 檔案(app.py/services/routes/templates/config.py/database/) → volume mount 即時生效,只需
docker restart momo-pro-system - 新增套件 / Dockerfile 變更 →
docker compose build momo-app && docker compose up -d momo-app - SQL schema 變更 →
docker exec -i momo-db psql -U momo -d momo_analytics < migration.sql
- Python 檔案(app.py/services/routes/templates/config.py/database/) → volume mount 即時生效,只需
禁止行為:
- ❌ 直接在 188 上用
vim改線上檔案(繞過 scp + 本地審視) - ❌ 用
docker cp改容器內檔案(volume mount 下無意義且混亂) - ❌ 把未測試的 commit scp 上去
- ❌ 在 110 做
kubectl *類操作(本系統無 K8s) - ❌ 修改
~/momo_pro_system/於 110(該路徑已空置,不是運行目錄)
唯一例外:
- 熱修復(Hotfix)若時間緊迫可直接在 188 改,但事後必須把 diff 補回本地並記入 CLAUDE.md 更新記錄
違反後果:
- 版本混亂(本地與 188 漂移)、無從追蹤
- 容器重啟後可能丟失(若改了非 mount 的目錄)
- 未來導入 Git/CI 時衝突
適用範圍:
- 資料庫結構變更(ALTER TABLE, DROP, CREATE)
- 大量資料修改或刪除(影響 >100 筆)
- 系統配置檔案修改
- 爬蟲核心邏輯修改
- 認證和安全模組修改
- 生產環境程式碼更新
- K8s ConfigMap 環境變數變更
- K8s Deployment YAML 變更
- Nginx 配置變更
備份命名規範:
資料庫:momo_backup_YYYYMMDD_HHMMSS.db
程式碼:momo_code_backup_YYYYMMDD_HHMMSS.tar.gz
第 30 條:所有變更必須入 Git 版控(絕對禁止違反)⚠️
核心原則:
- 任何對專案的修改,無論大小,都必須提交到 Git 版本控制
- 禁止只在伺服器端修改而不同步到 Git
適用範圍:
- 程式碼變更(Python, JavaScript, HTML, CSS)
- Docker/K8s 配置變更(docker-compose.yml, Deployment YAML)
- n8n 工作流變更(n8n-workflows/*.json)
- Nginx 配置變更
- 安全性修復
- 環境變數變更(ConfigMap)
- 任何系統配置修改
強制流程:
# 1. 本地修改或從伺服器同步變更
# 2. 提交到 Git
git add <changed-files>
git commit -m "描述性訊息"
# 3. 推送到遠端 Git 版控(remote 名稱依新 CI/CD 方案而定)
git push <remote> main
Claude 助手責任:
- 每次完成修改任務後,必須主動詢問或執行 Git 提交
- 若在伺服器端直接修改,必須將變更同步回本地並提交
- 禁止回覆「已完成」但未提交到 Git 的情況
違反後果:
- 本地與伺服器版本不一致
- 下次 CI/CD 部署會覆蓋未提交的變更
- 無法追蹤變更歷史和回滾
第 31 條:端口安全規範(絕對禁止違反)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- 所有內部服務端口必須綁定到 127.0.0.1,禁止暴露到公網 (0.0.0.0)
- 只有必要的公開服務才能綁定到 0.0.0.0
強制本地綁定的服務:
| 服務 | 端口 | 正確配置 | 風險等級 |
|---|---|---|---|
| PostgreSQL | 5432 | 127.0.0.1:5432:5432 |
🔴 極高 |
| Portainer | 9000/9443 | 127.0.0.1:9000:9000 |
🔴 極高 |
| Rancher | 8880/8443 | 127.0.0.1:8880:80 |
🔴 極高 |
| MOMO App | 5001 | 127.0.0.1:5001:80 |
🟠 高 |
| Prometheus | 9090 | 127.0.0.1:9090:9090 |
🟠 高 |
| Alertmanager | 9093 | 127.0.0.1:9093:9093 |
🟠 高 |
| Node Exporter | 9100 | 127.0.0.1:9100:9100 |
🟡 中 |
| Postgres Exporter | 9187 | 127.0.0.1:9187:9187 |
🟡 中 |
| Loki | 3100 | 127.0.0.1:3100:3100 |
🟡 中 |
| cAdvisor | 8080 | 127.0.0.1:8080:8080 |
🟡 中 |
允許公開的服務:
- Port 80/443 (Nginx - HTTPS 反向代理)
- Port 22 (SSH - 需要密鑰認證)
- Port 5000 (Registry - 需要認證)
docker-compose.yml 配置範例:
# ❌ 錯誤 - 暴露到公網
ports:
- "5432:5432"
# ✅ 正確 - 僅本地連線
ports:
- "127.0.0.1:5432:5432"
存取內部服務方式:
# SSH Tunnel 存取 Portainer
ssh -L 9000:127.0.0.1:9000 wooo@192.168.0.110
# 然後瀏覽器開啟 http://localhost:9000
第 32 條:Nginx 安全配置規範(絕對禁止違反)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- 必須隱藏伺服器版本資訊
- 必須設定安全 Headers
- 必須透過 HTTPS 反向代理,禁止直接存取後端服務
強制配置項目:
server {
# 1. 隱藏 Nginx 版本
server_tokens off;
# 2. 安全 Headers(必須全部加入)
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
# 3. HSTS - 強制 HTTPS(防止中間人攻擊)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# 3. 反向代理設定
location / {
proxy_pass http://127.0.0.1:5001; # 後端只綁定本地
# 4. 隱藏後端版本資訊
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
}
Rate Limiting 配置(防止暴力掃描和 DDoS):
# 在 nginx.conf 的 http {} 區塊中
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# 在 server {} 區塊中
limit_req zone=general burst=20 nodelay; # 一般請求
limit_conn conn_limit 50; # 最大同時連線數
# 登入頁面更嚴格
location /login {
limit_req zone=login burst=5 nodelay; # 每秒 3 個請求
}
禁止行為:
- ❌ 暴露 Nginx 版本號 (
nginx/1.x.x) - ❌ 暴露後端框架版本 (
gunicorn,Python) - ❌ 允許直接存取後端端口 (5001)
- ❌ 使用 HTTP 傳輸登入憑證
- ❌ 無限制接受請求(易遭 DDoS)
驗證指令:
# 檢查是否隱藏版本
curl -sI https://mo.wooo.work | grep -i server
# 應該只顯示 "server: nginx" 不帶版本號
第 33 條:資料庫安全規範(絕對禁止違反)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- 資料庫端口絕對禁止暴露到公網
- 必須使用強密碼
- 連線必須透過內部網路或 SSH Tunnel
PostgreSQL 安全配置:
# docker-compose.yml
postgres:
ports:
- "127.0.0.1:5432:5432" # 僅本地連線
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} # 從環境變數讀取
禁止行為:
- ❌ 資料庫密碼寫死在程式碼中
- ❌ 使用弱密碼(如
postgres,123456) - ❌ 允許遠端直接連線資料庫
- ❌ 在錯誤訊息中暴露資料庫結構
第 34 條:容器管理平台安全規範(絕對禁止違反)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- Portainer、Rancher 等容器管理平台屬於最高權限入口
- 必須限制為本地連線,透過 SSH Tunnel 存取
- 必須使用強密碼和雙因素認證(如支援)
風險說明:
- 攻擊者一旦獲得容器管理平台存取權,可以:
- 查看所有容器的環境變數(包含密碼)
- 執行任意容器命令
- 部署惡意容器
- 讀取資料庫內容
- 完全控制整個系統
強制配置:
# Portainer
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9443:9443"
# Rancher(docker run 方式)
docker run -d --name rancher \
-p 127.0.0.1:8880:80 \
-p 127.0.0.1:8443:443 \
rancher/rancher:latest
第 35 條:SSH 安全規範(絕對禁止違反)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- SSH 服務是伺服器的最重要入口,必須嚴格保護
- 必須安裝 Fail2Ban 防止暴力破解攻擊
- 建議使用 SSH Key 認證取代密碼認證
Fail2Ban 強制配置 (/etc/fail2ban/jail.local):
[DEFAULT]
bantime = 3600 # 封鎖 1 小時
findtime = 600 # 10 分鐘內
maxretry = 3 # 最多 3 次失敗
ignoreip = 127.0.0.1/8 192.168.0.0/24 # 白名單
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
常用指令:
# 查看封鎖狀態
sudo fail2ban-client status sshd
# 手動解封 IP
sudo fail2ban-client set sshd unbanip <IP>
# 查看日誌
sudo tail -f /var/log/fail2ban.log
第 36 條:持續性安全監控規範(強制要求)⚠️
2026-01-25 Kali 滲透測試後新增
核心原則:
- 安全不是一次性工作,必須持續監控
- 所有安全事件必須有日誌和告警機制
- 定期執行滲透測試,發現新漏洞立即修復
強制監控項目:
| 監控項目 | 工具 | 告警方式 |
|---|---|---|
| SSH 暴力破解 | Fail2Ban + Prometheus Exporter | Grafana 儀表板 |
| 端口掃描偵測 | CI/CD Nmap 掃描(待新 CI/CD 方案重建) | Telegram 通知 |
| 系統資源 | Prometheus + Node Exporter | Grafana 告警 |
| 容器狀態 | cAdvisor + Prometheus | Grafana 告警 |
| 網站可用性 | Blackbox Exporter | Telegram 通知 |
Fail2Ban Prometheus Exporter:
# 服務位置
/usr/local/bin/fail2ban_exporter.py
systemctl status fail2ban-exporter
# Prometheus 指標
fail2ban_currently_banned{jail="sshd"}
fail2ban_total_banned{jail="sshd"}
每週自動安全掃描(待重建):
# 原本在 GitLab CI 上以排程(每週一 09:00)執行 security-scan job
# 掃描:nmap -Pn --top-ports 100 192.168.0.110
# 通知:Telegram
# GitLab 已撤除,排程掃描需在新 CI/CD 方案或 cron 上重建
發現漏洞處理流程:
- 立即評估風險等級(極高/高/中/低)
- 極高風險:1 小時內修復
- 高風險:24 小時內修復
- 中/低風險:1 週內修復
- 修復後更新憲法和 CLAUDE.md
- 提交到 Git 版控
第 37 條:程式碼安全掃描規範(強制要求)⚠️
2026-01-25 新增
核心原則:
- 每次 Push 必須執行自動化程式碼安全掃描
- 使用 Bandit 工具檢測 Python 常見安全漏洞
- 高危漏洞必須立即修復後才能部署
掃描工具:
| 工具 | 用途 | 說明 |
|---|---|---|
| Bandit | Python 安全掃描 | OWASP Top 10、SQL 注入、XSS、密碼硬編碼等 |
CI/CD Job: security-code-scan(原 GitLab CI Job,待新 CI/CD 方案重建)
漏洞嚴重度與處理:
| 嚴重度 | 圖示 | 處理方式 | 通知 |
|---|---|---|---|
| 高危 (HIGH) | 🔴 | 必須修復後才能合併 | Telegram 警告 |
| 中危 (MEDIUM) | 🟠 | 應在 24 小時內修復 | Telegram 提醒 |
| 低危 (LOW) | 🟡 | 可選擇修復 | 僅記錄 |
常見檢測項目:
B101- assert 在生產環境中使用B105- 硬編碼密碼B303- 使用 MD5 或 SHA1B320- XML 外部實體注入 (XXE)B501- 禁用 SSL 驗證B608- SQL 注入
Bandit 報告位置:(GitLab 已撤除,待新 CI/CD 方案定案後更新路徑)
🔒 資安修復記錄
2026-01-25 Kali Linux 滲透測試修復
| 漏洞 | 風險等級 | 修復方式 | 狀態 |
|---|---|---|---|
| PostgreSQL 5432 暴露公網 | 🔴 極高 | 改為 127.0.0.1:5432 | ✅ 已修復 |
| Portainer 9000/9443 暴露公網 | 🔴 極高 | 改為 127.0.0.1 | ✅ 已修復 |
| Rancher 8880/8443 暴露公網 | 🔴 極高 | 改為 127.0.0.1 | ✅ 已修復 |
| pgAdmin 8088 暴露公網 | 🔴 極高 | 改為 127.0.0.1:8088 | ✅ 已修復 |
| MOMO App 5001 暴露公網 | 🟠 高 | 改為 127.0.0.1,透過 Nginx 代理 | ✅ 已修復 |
| Prometheus 9090 暴露公網 | 🟠 高 | 改為 127.0.0.1:9090 | ✅ 已修復 |
| Grafana 3000 暴露公網 | 🟠 高 | 改為 127.0.0.1,透過 mon.wooo.work | ✅ 已修復 |
| cAdvisor 8080 無認證暴露 | 🟠 高 | 改為 127.0.0.1:8080 | ✅ 已修復 |
| n8n 5678 暴露 API Keys/Sentry | 🔴 極高 | 改為 127.0.0.1:5678 | ✅ 已修復 |
| Registry 5000 HTTP 公開存取 | 🟠 高 | 改為 127.0.0.1:5000,透過 HTTPS | ✅ 已修復 |
| Nginx 暴露版本資訊 | 🟡 中 | server_tokens off | ✅ 已修復 |
| 後端暴露 Gunicorn/Python 版本 | 🟡 中 | proxy_hide_header | ✅ 已修復 |
| 缺少安全 Headers | 🟡 中 | 新增 X-Content-Type-Options 等 | ✅ 已修復 |
| Nextcloud 8081 暴露公網 | 🟠 高 | 改為 127.0.0.1:8081,透過 Nginx 代理 | ✅ 已修復 |
| SSH 22 暴力破解風險 | 🟠 高 | 安裝 Fail2Ban (3次失敗封鎖1小時) | ✅ 已修復 |
| Node Exporter 9100 洩漏硬體資訊 | 🟡 中 | 改為 127.0.0.1:9100 | ✅ 已修復 |
| SSL/TLS 未啟用 HSTS | 🟡 中 | 新增 Strict-Transport-Security 標頭 | ✅ 已修復 |
| 無請求速率限制 (DDoS 風險) | 🟡 中 | 新增 Rate Limiting (10r/s + burst 20) | ✅ 已修復 |
🛡️ 安全監控機制
Fail2Ban 監控 (Prometheus + Grafana)
Exporter 位置: /usr/local/bin/fail2ban_exporter.py
服務: systemctl status fail2ban-exporter
端口: 0.0.0.0:9191 (內部使用)
可用指標:
fail2ban_currently_failed{jail="sshd"} # 目前失敗嘗試數
fail2ban_total_failed{jail="sshd"} # 歷史總失敗數
fail2ban_currently_banned{jail="sshd"} # 目前封鎖 IP 數
fail2ban_total_banned{jail="sshd"} # 歷史總封鎖數
每週自動安全掃描 (Nmap) — 待新 CI/CD 方案重建
原本建構在 GitLab CI 排程之上(每週一 09:00 執行
security-scanjob,掃描 PostgreSQL/MySQL/MongoDB/Redis 等常見危險端口並發送 Telegram 通知)。GitLab 撤除後此排程掃描已停用,需在新 CI/CD 方案或 cron 上重建。
程式碼安全掃描 (Bandit) — 待新 CI/CD 方案重建
原本建構在 GitLab CI 上(
security-code-scanjob,每次 Push 和手動觸發;Bandit 掃描全部 Python 檔案,排除 tests/, venv/, node_modules/;結果依嚴重度發 Telegram 通知)。GitLab 撤除後此掃描需在新 CI/CD 方案上重建。
容器映像檔安全掃描 (Trivy) — 待新 CI/CD 方案重建
原本建構在 GitLab CI 上(
container-security-scanjob,每週一排程 + 手動觸發;Trivy 掃描 Debian 基礎映像與 Python 套件 CVE,僅報告 HIGH/CRITICAL 等級並發送 Telegram 通知)。GitLab 撤除後此掃描需在新 CI/CD 方案上重建。
快速檢查清單
✅ 新功能開發檢查
- 程式碼和註解使用繁體中文
- 無硬編碼敏感資訊
- 所有輸入經過驗證
- POST 請求包含 CSRF token
- 錯誤處理完整
- 日誌記錄完整
🕷️ 爬蟲修改檢查
- 備份現有可運作版本
- 記錄修改原因
- 保留舊選擇器作為註解
- 測試新選擇器正確性
- 驗證資料完整性
- 更新爬蟲文檔
- 監控 24 小時確保穩定
開發測試部署流程(2026-04-18 依 ADR-008 改寫)
版本: 3.0 制定日期: 2026-04-18
環境架構
| 環境 | 位置 | 用途 | 網址 |
|---|---|---|---|
| 開發環境 | /Users/ooo/.../momo-pro-system/ (macOS + iCloud) |
本地開發 | http://127.0.0.1:5000 |
| 正式環境 | /home/ollama/momo-pro/ 於 ollama@192.168.0.188(Docker Compose) |
生產服務 | https://mo.wooo.work / https://momo.wooo.work |
完整開發部署流程
階段 1:本地開發
cd "/Users/ooo/Library/Mobile Documents/com~apple~CloudDocs/momo-pro-system"
source venv/bin/activate
python app.py
階段 2:本地測試
./run_security_tests.sh # 若有
# 手動測試主要流程 / UI
階段 3:同步到 188(經 110 跳板)
# 單檔 Python
scp -o ProxyJump=wooo@192.168.0.110 app.py ollama@192.168.0.188:/home/ollama/momo-pro/
# 整個目錄(routes / services / templates 等)
scp -o ProxyJump=wooo@192.168.0.110 -r routes/ ollama@192.168.0.188:/home/ollama/momo-pro/
階段 4:重啟容器(volume mount 後)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker restart momo-pro-system"
若新增套件或改 Dockerfile:
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "cd /home/ollama/momo-pro && docker compose build momo-app && docker compose up -d momo-app"
階段 5:驗證部署
# 容器狀態
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker ps --filter name=momo"
# 應用日誌
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker logs -f momo-pro-system --tail 50"
# 對外健康檢查
curl -s https://mo.wooo.work/health
curl -s https://momo.wooo.work/health
常用命令速查
Docker 管理(188)
# 跳板登入
ssh -J wooo@192.168.0.110 ollama@192.168.0.188
# 容器清單
docker ps
# 即時日誌
docker logs -f momo-pro-system --tail 100
# 進入容器
docker exec -it momo-pro-system /bin/bash
# 重啟(volume mount 更新後)
docker restart momo-pro-system
# 重建映像
cd /home/ollama/momo-pro && docker compose build momo-app && docker compose up -d momo-app
回滾流程
方法:以檔案版本回滾(因為是 volume mount,無需 K8s rollout)
# 在本地 Mac 用 git 找回舊版本
git log -- app.py
git show <commit>:app.py > /tmp/app.py.old
# 推回 188
scp -o ProxyJump=wooo@192.168.0.110 /tmp/app.py.old ollama@192.168.0.188:/home/ollama/momo-pro/app.py
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker restart momo-pro-system"
Google Drive API 設定指南 (GOOGLE_DRIVE_SETUP.md)
功能說明
系統會:
- 每 30 分鐘自動檢查 Google Drive 指定資料夾
- 自動下載 Excel 檔案到本地
- 自動匯入資料到資料庫
- 自動刪除 Google Drive 上的原始檔案
目前認證狀態
| 項目 | 值 |
|---|---|
| Google Cloud 專案 | wooo-481204 |
| OAuth Client ID | 132823079326-h9cvj5eahigm8hp9q0b7t5rk77bhu3gp.apps.googleusercontent.com |
| 目前認證帳號 | owen.tsai@gmail.com (BA O) |
| 目標資料夾 | 當日業績匯入 |
| 檔案匹配模式 | 即時業績_當日 |
| 匯入後移至 | 當日業績匯入/已匯入 |
✅ 狀態: Google Drive 自動匯入已正常運作(2026-01-24 驗證)
K8s 環境設定(當前使用)
認證檔案位置
K8s Scheduler Pod 使用以下架構掛載 Google 認證:
┌─────────────────────────────────────────────────────────┐
│ K8s Secret: google-drive-credentials │
│ ├── google_credentials.json (OAuth 設定) │
│ └── google_token.pickle (已授權的 Token) │
└─────────────────────────────────────────────────────────┘
│
▼ initContainer 複製到
┌─────────────────────────────────────────────────────────┐
│ emptyDir: /app/config/ (可讀寫) │
│ ├── google_credentials.json │
│ └── google_token.pickle │
└─────────────────────────────────────────────────────────┘
相關 K8s 檔案
k8s/08-google-drive-secret.yaml- Google 認證 Secretk8s/05-scheduler.yaml- Scheduler Deployment(含 initContainer)
更換 Google 帳號步驟
-
本地重新認證(取得新的 token.pickle)
cd /Users/ogt/momo-pro-system # 刪除舊的 token rm -f config/google_token.pickle # 重新認證(會開啟瀏覽器) python3 -c " from services.google_drive_service import drive_service drive_service.authenticate() " -
更新 K8s Secret
# 將新的 token 編碼為 base64 CREDENTIALS_B64=$(base64 -i config/google_credentials.json) TOKEN_B64=$(base64 -i config/google_token.pickle) # 更新 k8s/08-google-drive-secret.yaml # 將 base64 值更新到 data 區段 # 套用新的 Secret kubectl apply -f k8s/08-google-drive-secret.yaml # 重啟 Scheduler(讓 initContainer 重新複製) kubectl rollout restart deployment/momo-scheduler -n momo -
驗證認證
kubectl exec -n momo deploy/momo-scheduler -c scheduler -- \ sh -c 'cd /app && python -c " from services.google_drive_service import drive_service drive_service.authenticate() service = drive_service.service about = service.about().get(fields=\"user\").execute() print(\"認證帳號:\", about[\"user\"][\"emailAddress\"]) "'
設定步驟摘要(本地/Docker 環境)
1. 建立 Google Cloud 專案
- 前往 Google Cloud Console
- 建立新專案(例如:
momo-auto-import)
2. 啟用 Google Drive API
- 前往「API 和服務」→「程式庫」
- 搜尋並啟用「Google Drive API」
3. 建立 OAuth 2.0 憑證
- 前往「API 和服務」→「憑證」
- 建立 OAuth 用戶端 ID(桌面應用程式)
- 下載 JSON 並放到
config/google_credentials.json
4. 首次認證
python3 -c "
from services.google_drive_service import drive_service
drive_service.authenticate()
"
5. 設定 Google Drive 資料夾
必須在認證帳號的 Google Drive 建立以下結構:
我的雲端硬碟/
└── 業績報表/
└── 當日業績/
└── 即時業績_當日.xlsx ← 放置要匯入的檔案
常見問題
| 問題 | 解決方法 |
|---|---|
| 認證失敗,找不到認證檔案 | 確認 config/google_credentials.json 存在 |
| 找不到 Google Drive 資料夾 | 確認路徑正確(區分大小寫),確認用正確的 Google 帳號 |
| 重新授權 | 刪除 config/google_token.pickle 並重新認證 |
| K8s 認證錯帳號 | 依照「更換 Google 帳號步驟」重新設定 |
Docker 部署指南(2026-04-18 依 ADR-008 改寫)
部署架構
本機 (Mac/iCloud) 188 伺服器 (ollama@192.168.0.188)
┌──────────────────────┐ scp 經110 ┌──────────────────────────────┐
│ 開發環境 │ 跳板 │ Docker Compose (V12.0) │
│ momo-pro-system/ │ ────────────► │ ┌──────────────────────────┐│
│ │ │ │ momo-pro-system ││
│ app.py / services/ │ │ │ Gunicorn 4 workers :80 ││
│ routes/ templates/ │ │ │ (host 127.0.0.1:5003) ││
│ database/ config.py │ │ └──────────────────────────┘│
└──────────────────────┘ │ momo-db (pgvector/pg14) │
│ momo-scheduler / openclaw │
└──────────────────────────────┘
同步檔案到 188
# 單檔
scp -o ProxyJump=wooo@192.168.0.110 app.py ollama@192.168.0.188:/home/ollama/momo-pro/
# 整個目錄
scp -o ProxyJump=wooo@192.168.0.110 -r services ollama@192.168.0.188:/home/ollama/momo-pro/
scp -o ProxyJump=wooo@192.168.0.110 -r routes ollama@192.168.0.188:/home/ollama/momo-pro/
scp -o ProxyJump=wooo@192.168.0.110 -r templates ollama@192.168.0.188:/home/ollama/momo-pro/
重啟 / 重建
# Python 檔案熱更新(最常用)
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 "docker restart momo-pro-system"
# 新套件 / Dockerfile 變更
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 \
"cd /home/ollama/momo-pro && docker compose build momo-app && docker compose up -d momo-app"
# 完整重啟所有 momo-* 容器
ssh -J wooo@192.168.0.110 ollama@192.168.0.188 \
"cd /home/ollama/momo-pro && docker compose restart momo-app momo-scheduler"
Volume Mount 檔案清單(這些 host 目錄會即時反映到容器)
ro(唯讀)掛載 — 改完 scp + docker restart 即生效:
app.py,scheduler.py,config.py,auth.pyservices/,routes/,database/,templates/
rw(讀寫)掛載 — 容器與 host 雙向:
config/,data/,logs/,backups/
未掛載(修改 host 無效):
docs/(CLAUDE.md / ADR 為人工參考,不影響 runtime)static/,web/(編譯進 image,改動需重建)
app.py 重構計畫 (docs/APP_REFACTOR_PLAN.md)
現況分析
- 總行數: 7,253 行
- 路由數量: 49 個
- 函數數量: 約 70 個
最大函數(需優先拆分)
| 排名 | 函數名稱 | 行數 | 建議模組 |
|---|---|---|---|
| 1 | sales_analysis() |
1,020 行 | sales_routes.py |
| 2 | get_monthly_summary_data() |
388 行 | monthly_routes.py |
| 3 | import_excel() |
288 行 | import_routes.py |
| 4 | get_sales_table_data() |
267 行 | sales_routes.py |
| 5 | edm_dashboard() |
244 行 | edm_routes.py |
目標目錄結構
momo-pro/ # (188: /home/ollama/momo-pro/)
├── app.py # 主應用程式 (精簡後約 500 行)
├── routes/ # 🆕 路由模組目錄
│ ├── __init__.py # Blueprint 註冊中心
│ ├── dashboard_routes.py # 商品看板 (首頁)
│ ├── sales_routes.py # 業績分析相關
│ ├── daily_sales_routes.py # 當日業績相關
│ ├── monthly_routes.py # 月結分析相關
│ ├── edm_routes.py # EDM 儀表板
│ ├── export_routes.py # 匯出功能
│ ├── import_routes.py # 匯入功能
│ ├── system_routes.py # 系統管理
│ └── api_routes.py # 通用 API
├── services/ # 服務層
│ ├── cache_service.py # 🆕 快取服務
│ ├── sales_service.py # 🆕 業績計算服務
│ └── ...
└── utils/ # 工具函數
├── validators.py # 🆕 驗證函數
└── ...
重構執行步驟
| 順序 | 模組 | 複雜度 |
|---|---|---|
| 1 | system_routes.py | 低 |
| 2 | api_routes.py | 低 |
| 3 | export_routes.py | 中 |
| 4 | import_routes.py | 中 |
| 5 | edm_routes.py | 中 |
| 6 | monthly_routes.py | 中 |
| 7 | dashboard_routes.py | 高 |
| 8 | daily_sales_routes.py | 高 |
| 9 | sales_routes.py | 高 |
預期效益
| 指標 | 重構前 | 重構後 |
|---|---|---|
| app.py 行數 | 7,253 | ~500 |
| 最大函數行數 | 1,020 | ~200 |
| 模組數量 | 1 | 10 |
| 可測試性 | 低 | 高 |
Google Drive 自動匯入功能 (AUTO_IMPORT_README.md)
功能概述
- 🔄 自動化流程:每 30 分鐘自動檢查 Google Drive
- 📥 自動下載:發現新檔案立即下載到本地
- 💾 自動匯入:解析 Excel 並匯入到資料庫
- 🗑️ 自動清理:匯入完成後刪除 Google Drive 原檔
新增檔案清單
後端服務
services/google_drive_service.py- Google Drive API 服務services/import_service.py- 自動匯入服務邏輯database/import_models.py- 匯入任務與配置資料表auto_import_routes.py- API 路由(Blueprint)
前端介面
web/auto_import_index.html- 自動匯入管理頁面
API 端點
| 端點 | 方法 | 說明 |
|---|---|---|
/api/import_jobs |
GET | 查詢任務清單 |
/api/import_jobs/{id} |
GET | 查詢單一任務 |
/api/import_config |
GET/POST | 取得/設定配置 |
/api/test_drive_connection |
POST | 測試連接 |
/api/list_drive_files |
POST | 列出檔案 |
/api/manual_import |
POST | 手動觸發匯入 |
資料表結構
import_jobs(匯入任務)
id,job_type,status,drive_file_id,drive_file_nameprogress_percent,current_step,total_rows,success_rowscreated_at,started_at,completed_at,error_message
import_config(匯入配置)
config_key,config_value,config_type,description
工作流程
Google Drive 新檔案上傳
↓
排程任務執行 (每 30 分鐘)
↓
建立匯入任務 (import_jobs)
↓
下載到本地 (data/temp/)
↓
解析 Excel 並匯入資料庫
↓
刪除 Drive 原檔
↓
任務完成,更新狀態記錄
故障排除
| 問題 | 解決方法 |
|---|---|
| 認證失敗 | 確認 config/google_credentials.json 存在 |
| 找不到資料夾 | 確認路徑正確(區分大小寫) |
| 檔案沒有被刪除 | 檢查任務狀態是否為「已完成」 |
| 匯入失敗 | 檢查 Excel 格式是否正確 |
一鍵部署自動化腳本 (2026-01-26 新增)
功能概述
完整的部署自動化系統,支援將 MOMO Pro System 一鍵部署到新的 VM 環境。
支援的部署模式
| 模式 | 說明 | 使用場景 |
|---|---|---|
| 本地部署 | 在當前主機執行部署 | 開發/測試環境 |
| SSH 遠端部署 | 透過 SSH 部署到遠端主機 | UAT/正式環境 |
| 匯出部署包 | 生成可攜式 tar.gz 壓縮包 | 無網路直連環境 |
檔案結構
deploy/
├── deploy.sh # 主入口腳本
├── README.md # 部署說明文檔
├── configs/
│ └── .env.template # 環境變數模板
└── lib/
├── common.sh # 通用函數 (日誌、進度條)
├── check.sh # 環境檢查 (Docker、記憶體、端口)
├── config.sh # 配置生成 (互動式 + 模板)
├── docker.sh # Docker 操作 (構建、啟動、同步)
├── database.sh # 資料庫備份/還原 (完整+CSV)
├── ssl.sh # SSL 憑證 (Let's Encrypt)
└── health.sh # 健康檢查 (容器、端點、資料庫)
常用命令
部署
# 本地部署(互動式配置)
./deploy/deploy.sh deploy
# 使用自訂配置部署
./deploy/deploy.sh -e .env.production deploy
# SSH 遠端部署
./deploy/deploy.sh --ssh -h 192.168.1.100 -u root deploy
# 匯出部署包(含資料)
./deploy/deploy.sh --export --with-data
備份與還原
# 完整備份(資料庫 + 配置 + n8n 工作流)
./deploy/deploy.sh backup
# 輸出: backups/momo_backup_20260126_143000.tar.gz
# 從備份還原
./deploy/deploy.sh -b backups/momo_backup_20260126.tar.gz restore
SSL 憑證
# 申請 Let's Encrypt 憑證
./deploy/deploy.sh -d momo.example.com ssl
# 健康檢查
./deploy/deploy.sh health
命令選項
| 選項 | 說明 |
|---|---|
--local |
本地部署(預設) |
--ssh |
SSH 遠端部署 |
--export |
匯出部署包 |
-h, --host |
SSH 目標主機 |
-u, --user |
SSH 用戶名 |
-p, --path |
遠端部署路徑 |
-e, --env-file |
自訂環境變數檔案 |
-d, --domain |
域名(SSL 用) |
-b, --backup |
備份檔案路徑 |
--no-monitoring |
不部署監控服務 |
--with-data |
包含資料庫備份 |
-y, --yes |
跳過確認提示 |
資料庫備份特點
- 完整 SQL 備份: 結構 + 資料 (pg_dump)
- CSV 分表匯出: 每個資料表獨立 CSV 檔案,方便檢視
- 備份摘要報告: 資料表行數、大小統計
- 自動壓縮: 生成
.tar.gz壓縮包
備份內容
backups/momo_backup_20260126_143000/
├── database/
│ ├── postgres_full_20260126_143000.sql # 完整 SQL
│ ├── backup_summary.txt # 備份摘要
│ └── tables/
│ ├── users.csv
│ ├── products.csv
│ ├── daily_sales_snapshot.csv
│ └── ... # 所有資料表
├── configs/
│ ├── .env
│ ├── docker-compose.yml
│ └── config/
└── n8n/
└── *.json # 所有工作流程
環境需求
硬體需求
| 項目 | 最低需求 | 建議配置 |
|---|---|---|
| CPU | 4 核心 | 8 核心 |
| RAM | 8 GB | 16 GB |
| 硬碟 | 50 GB SSD | 100 GB SSD |
端口需求
| 端口 | 服務 | 必要 |
|---|---|---|
| 5001 | Flask App | ✓ |
| 5432 | PostgreSQL | ✓ |
| 80/443 | Nginx | ✓ |
| 3000 | Grafana | 選填 |
| 9090 | Prometheus | 選填 |
| 5678 | n8n | 選填 |
PostgreSQL 慢查詢監控 (2026-01-26 新增)
功能概述
新增 PostgreSQL 慢查詢監控 API 及 n8n 自動修復工作流程。
API 端點
| 端點 | 方法 | 說明 |
|---|---|---|
/api/system/db/slow_queries |
GET | 取得慢查詢列表 |
/api/system/db/optimize |
POST | 執行 VACUUM ANALYZE |
/api/system/db/stats |
GET | 資料庫統計資訊 |
/api/system/monitor/overview |
GET | 監控總覽(整合所有狀態) |
n8n 工作流程
名稱: PostgreSQL 慢查詢監控 (含自動修復)
檔案: n8n-workflows/13-slow-query-monitor.json
工作流程:
- 每 15 分鐘執行
- 呼叫
/api/system/db/slow_queries取得慢查詢 - 分析是否需要優化(≥3 個慢查詢或重複模式)
- 發送 Telegram 告警
- 自動執行 VACUUM ANALYZE(如需要)
- 通知優化結果
慢查詢檢測邏輯
// 閾值設定
const threshold = 5; // 秒
// 觸發優化條件
if (slowQueries.length >= 3) {
needsOptimize = true;
}
// 重複慢查詢檢測(可能需要索引)
if (repeatedSlowQueries.length > 0) {
needsOptimize = true;
}
Monitor 頁面更新
檔案: docker/nginx/html/monitor-index.html
新增功能:
- 即時服務狀態面板(Registry、Grafana、Prometheus、n8n、MOMO App、Database)
- Prometheus 告警顯示面板
- n8n 工作流程狀態面板
- 每 30 秒自動刷新
n8n 監控工作流程清單
| 檔案 | 名稱 | 排程 | 功能 |
|---|---|---|---|
11-registry-health-monitor.json |
Registry 健康監控 | 每 10 分鐘 | Docker Registry 健康檢查 |
12-google-drive-import-monitor.json |
Google Drive 匯入監控 | 每 30 分鐘 | 自動匯入失敗告警 |
13-slow-query-monitor.json |
PostgreSQL 慢查詢監控 | 每 15 分鐘 | 慢查詢告警 + 自動 VACUUM |
CI/CD 與一鍵部署自動化 (2026-02-06 新增)
概述
完整的部署自動化系統,包含:
- CI/CD 流程: GitLab 已撤除,新方案待定
- 環境自動安裝: 在全新主機上自動安裝所有必要套件
- 一鍵完整部署: 環境安裝 + 應用部署一次完成
CI/CD 流程(待定)
2026-04-18 備註: 原 GitLab CI/CD(含
.gitlab-ci.yml、.gitlab-ci-simple.yml)已隨 GitLab 撤除而退役。下列 Pipeline 骨架保留作為新 CI/CD 方案的參考需求。
預期階段骨架
git push main (remote 待定)
│
▼
╔═══════════════════════════════════════╗
║ CI/CD Pipeline (待新方案定案) ║
╠═══════════════════════════════════════╣
║ Stage: test ║
║ • pytest 測試 (允許失敗) ║
╠═══════════════════════════════════════╣
║ Stage: deploy ║
║ • rsync 同步程式碼到 K3s 主機 ║
║ • docker build (在 K3s 主機建置) ║
║ • k3s ctr images import (匯入映像) ║
║ • kubectl rollout restart (重啟) ║
║ • 健康檢查 ║
║ • Telegram 通知 ║
╚═══════════════════════════════════════╝
關鍵特點(設計需求)
| 特點 | 說明 |
|---|---|
| 不依賴 Registry | 本地建置 + K3s containerd 直接匯入(可選) |
| 自動健康檢查 | 部署後自動驗證服務狀態 |
| Telegram 通知 | 部署成功/失敗即時通知 |
| 自動回滾 | 部署失敗可快速回滾 |
相關檔案
| 檔案 | 說明 |
|---|---|
scripts/deploy/build-and-deploy.sh |
快速部署腳本(手動執行) |
scripts/verify-cicd.sh |
CI/CD 驗證腳本(原 GitLab CI 用,待改寫) |
一鍵部署到新主機
完整部署命令
# 1. 複製專案到新主機
scp -r momo-pro-system root@新主機IP:/opt/
# 2. SSH 到新主機執行完整部署
ssh root@新主機IP
cd /opt/momo-pro-system
sudo ./deploy/scripts/full-deploy.sh --domain mo.example.com --ssl
一個命令完成:環境安裝 + K8s 部署 + Nginx + SSL + 監控 + 自動啟動
部署流程
執行 full-deploy.sh
│
▼
Phase 1: 環境安裝 ─────────────────────────────────────────────
• 檢測 OS (Ubuntu/Debian)
• 安裝基礎套件 (curl, git, vim, htop, jq...)
• 安裝 Docker + Docker Compose
• 安裝 K3s + Helm
• 安裝 Nginx + 安全配置
• 安裝 Certbot (Let's Encrypt)
• 設定 UFW 防火牆
• 設定 Fail2Ban
• 系統優化 (核心參數、檔案限制)
│
▼
Phase 2: K8s 配置 ─────────────────────────────────────────────
• 建立 momo namespace
• 部署 Secrets + ConfigMap
• 部署 PostgreSQL StatefulSet
• 部署 momo-app Deployment
• 部署 momo-scheduler Deployment
│
▼
Phase 3: 映像建置 ─────────────────────────────────────────────
• docker build -t momo-pro-system:local
• docker save | k3s ctr images import
• kubectl rollout restart
│
▼
Phase 4-5: 網路配置 ───────────────────────────────────────────
• Nginx 反向代理配置
• Let's Encrypt SSL 證書
│
▼
Phase 6: 監控系統 ─────────────────────────────────────────────
• Prometheus + Grafana (Helm)
• Alertmanager 告警
│
▼
Phase 7-8: 自動化 ─────────────────────────────────────────────
• systemd 開機自動啟動
• 健康檢查
• Telegram 通知
自動安裝的套件清單
基礎套件
| 套件 | 用途 |
|---|---|
| curl, wget | 檔案下載 |
| git | 版本控制 |
| vim, htop, iotop | 編輯器與系統監控 |
| jq | JSON 處理 |
| rsync | 檔案同步 |
| unzip, tar, gzip | 壓縮解壓縮 |
| net-tools, dnsutils | 網路工具 |
| build-essential | 編譯工具 |
| cron, logrotate | 排程與日誌管理 |
容器與 Kubernetes
| 套件 | 版本 | 用途 |
|---|---|---|
| Docker CE | 最新 | 容器運行環境 |
| Docker Compose | Plugin | 多容器編排 |
| K3s | 最新 | 輕量級 Kubernetes |
| Helm | v3 | K8s 套件管理 |
Python
| 套件 | 用途 |
|---|---|
| python3 | Python 執行環境 |
| pip | Python 套件管理 |
| venv | 虛擬環境 |
Web 伺服器與 SSL
| 套件 | 用途 |
|---|---|
| Nginx | 反向代理 + 負載均衡 |
| Certbot | Let's Encrypt SSL 自動證書 |
安全
| 套件 | 用途 |
|---|---|
| Fail2Ban | 防暴力破解 (SSH 3次失敗封鎖1小時) |
| UFW | 防火牆 |
監控
| 套件 | 用途 |
|---|---|
| Node Exporter | 主機指標收集 |
| Prometheus | 指標儲存與查詢 (Helm) |
| Grafana | 監控儀表板 (Helm) |
資料庫
| 套件 | 用途 |
|---|---|
| postgresql-client | PostgreSQL 客戶端工具 |
部署腳本說明
1. 環境安裝腳本
檔案: deploy/scripts/setup-environment.sh
只安裝環境,不部署應用:
sudo ./deploy/scripts/setup-environment.sh [選項]
選項:
--user <name> 部署用戶(預設: wooo)
--domain <domain> 域名
--no-docker 不安裝 Docker
--no-k3s 不安裝 K3s
--no-nginx 不安裝 Nginx
--no-certbot 不安裝 Certbot
--no-monitoring 不安裝監控工具
--no-firewall 不設定防火牆
2. 完整部署腳本
檔案: deploy/scripts/full-deploy.sh
環境安裝 + 應用部署:
sudo ./deploy/scripts/full-deploy.sh [選項]
選項:
--user <name> 部署用戶(預設: wooo)
--domain <domain> 域名
--ssl 設定 SSL 證書
--skip-env 跳過環境安裝(環境已準備好時使用)
3. 快速部署腳本
檔案: scripts/deploy/build-and-deploy.sh
日常更新用(環境已準備好):
./scripts/deploy/build-and-deploy.sh
# 功能:
# 1. 本地 Docker 建置
# 2. 映像傳輸到 K3s 主機
# 3. 匯入 K3s containerd
# 4. 重啟服務
# 5. 健康檢查
# 6. Telegram 通知
4. CI/CD 驗證腳本
檔案: scripts/verify-cicd.sh
驗證 CI/CD 流程完整性:
./scripts/verify-cicd.sh
# 驗證項目:
# 1. 本地環境 (Docker, Git, SSH)
# 2. SSH 連線 (K3s 主機)
# 3. K8s 服務狀態
# 4. 應用健康檢查
# 5. CI/CD 檔案完整性
# 6. 自動啟動設定
# 7. 端對端部署測試
# 8. 監控系統
日常更新流程
環境已安裝後,日常更新只需:
# 方法 1: 使用快速部署腳本
./scripts/deploy/build-and-deploy.sh
# 方法 2: 手動步驟
docker build -t momo-pro-system:local .
docker save momo-pro-system:local | sudo k3s ctr images import -
kubectl rollout restart deployment/momo-app deployment/momo-scheduler -n momo
系統需求
硬體需求
| 項目 | 最低需求 | 建議配置 |
|---|---|---|
| CPU | 2 核心 | 4+ 核心 |
| RAM | 4 GB | 8+ GB |
| 硬碟 | 30 GB | 50+ GB SSD |
支援的作業系統
| OS | 版本 | 狀態 |
|---|---|---|
| Ubuntu | 22.04, 24.04 | ✅ 完全支援 |
| Debian | 11, 12 | ✅ 完全支援 |
防火牆規則 (自動設定)
| 端口 | 服務 | 存取範圍 |
|---|---|---|
| 22 | SSH | 公開 |
| 80 | HTTP | 公開 |
| 443 | HTTPS | 公開 |
| 6443 | K3s API | 僅內網 |
部署檔案清單
deploy/
├── deploy.sh # 進階部署主腳本
├── README.md # 部署說明文檔
├── QUICK_START.md # 快速部署指南
├── configs/
│ └── .env.template # 環境變數模板
├── lib/
│ ├── common.sh # 通用函數
│ ├── check.sh # 環境檢查
│ ├── config.sh # 配置生成
│ ├── docker.sh # Docker 操作
│ ├── database.sh # 資料庫備份還原
│ ├── ssl.sh # SSL 憑證
│ ├── health.sh # 健康檢查
│ ├── k8s.sh # K8s 管理
│ ├── monitoring.sh # 監控部署
│ ├── systemd.sh # Systemd 服務
│ └── registry.sh # Registry 管理
└── scripts/
├── setup-environment.sh # 🆕 環境自動安裝
├── full-deploy.sh # 🆕 完整一鍵部署
└── setup-firewall.sh # 防火牆設定
scripts/
├── deploy/
│ └── build-and-deploy.sh # 快速部署腳本
├── verify-cicd.sh # 🆕 CI/CD 驗證腳本
└── tools/
├── system_startup_complete.sh # 系統啟動腳本
└── momo-startup-complete.service # systemd 服務
🚀 WOOO AIOps - 智能運維 SaaS 產品 (2026-02-13 新增)
產品概覽
WOOO AIOps 是基於 MOMO Pro System 監控與自動修復經驗打造的 SaaS 產品, 讓新網站能夠即時接入監控、告警、自動修復與一鍵部署功能。
| 項目 | 說明 |
|---|---|
| 產品名稱 | WOOO AIOps (AI Operations Platform) |
| 目標客戶 | 需要快速建立監控的中小型網站 |
| 核心價值 | 10 分鐘內完成監控 + 自動修復配置 |
| 技術棧 | FastAPI + React/Next.js + K8s + Prometheus |
產品特點
| 功能 | 說明 |
|---|---|
| 一鍵部署 | 支援 FastAPI、Flask、Express、Next.js 等主流框架 |
| 智能監控 | 自動整合 Prometheus + Grafana |
| AI 告警 | 基於歷史資料的智能告警 |
| 自動修復 | 重啟、擴容、回滾、記憶體調整等 8 種修復策略 |
| 多租戶 | 完整的用戶隔離與計費系統 |
架構圖
┌─────────────────────────────────────────────────────────────────────────────┐
│ WOOO AIOps Platform │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Web Portal (React/Next.js) │
│ ├── Dashboard # 總覽儀表板 │
│ ├── Apps Management # 應用管理 │
│ ├── Monitoring # 監控中心 │
│ ├── Repairs History # 修復記錄 │
│ └── Settings # 系統設定 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ FastAPI Backend │ │
│ │ /api/auth/* # 認證 (JWT) │ │
│ │ /api/apps/* # 應用 CRUD │ │
│ │ /api/deployments/* # 部署管理 │ │
│ │ /api/monitoring/* # 監控資料 │ │
│ │ /api/repairs/* # 修復記錄 │ │
│ │ /api/users/* # 用戶管理 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Deploy Engine │ │ Monitor Engine│ │ Repair Engine │ │
│ │ │ │ │ │ │ │
│ │ • Template │ │ • Prometheus │ │ • 8 種策略 │ │
│ │ Renderer │ │ Client │ │ • 自動觸發 │ │
│ │ • K8s Client │ │ • Alertmanager│ │ • 執行追蹤 │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Kubernetes Cluster │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ User App A │ │ User App B │ │ User App C │ │ │
│ │ │ (FastAPI) │ │ (Next.js) │ │ (Express) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Prometheus │ │ Grafana │ │Alertmanager │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
目錄結構
aiops-core/
├── README.md # 產品說明文檔
├── requirements.txt # Python 依賴
│
├── api/ # FastAPI 後端
│ ├── main.py # FastAPI 入口
│ └── routers/
│ ├── auth.py # JWT 認證
│ ├── apps.py # 應用 CRUD
│ ├── deployments.py # 部署管理
│ ├── monitoring.py # 監控 API
│ ├── repairs.py # 修復記錄
│ └── users.py # 用戶管理
│
├── database/ # 資料庫層
│ ├── models.py # SQLAlchemy 模型
│ └── session.py # 資料庫連線
│
├── deploy_engine/ # 部署引擎
│ ├── deploy_service.py # 部署服務
│ ├── template_renderer.py # Jinja2 模板渲染
│ └── k8s_client.py # kubectl 封裝
│
├── monitor_engine/ # 監控引擎
│ ├── monitor_service.py # 監控服務
│ ├── prometheus_client.py # Prometheus API
│ └── alert_manager.py # Alertmanager API
│
├── repair_engine/ # 修復引擎
│ ├── repair_service.py # 修復服務
│ ├── repair_executor.py # 修復執行器
│ └── repair_strategies.py # 修復策略
│
├── templates/ # K8s 模板 (Jinja2)
│ ├── base/
│ │ ├── namespace.yaml.j2
│ │ ├── service.yaml.j2
│ │ └── ingress.yaml.j2
│ └── frameworks/
│ ├── fastapi/deployment.yaml.j2
│ ├── flask/deployment.yaml.j2
│ ├── express/deployment.yaml.j2
│ └── nextjs/deployment.yaml.j2
│
└── web/ # React/Next.js 前端
├── package.json
├── tailwind.config.js
└── src/
├── lib/api.ts # API 客戶端
└── pages/
├── index.tsx # Dashboard
├── monitoring.tsx # 監控中心
├── repairs.tsx # 修復記錄
└── apps/
├── index.tsx # 應用列表
└── new.tsx # 創建應用精靈
資料庫模型
核心表
| 表名 | 說明 | 主要欄位 |
|---|---|---|
users |
用戶帳號 | id, email, password_hash, plan, company |
apps |
應用配置 | id, user_id, name, framework, status, domain |
deployments |
部署記錄 | id, app_id, version, status, started_at |
alerts |
告警記錄 | id, app_id, name, severity, status |
repairs |
修復記錄 | id, app_id, action, status, attempt |
api_keys |
API 金鑰 | id, user_id, key_hash, scopes |
列舉類型
class PlanType(str, Enum):
FREE = "free" # 最多 2 個應用
STARTER = "starter" # 最多 5 個應用
PRO = "pro" # 最多 20 個應用
ENTERPRISE = "enterprise" # 無限制
class Framework(str, Enum):
FASTAPI = "fastapi"
FLASK = "flask"
EXPRESS = "express"
NEXTJS = "nextjs"
DJANGO = "django"
NESTJS = "nestjs"
class AppStatus(str, Enum):
PENDING = "pending"
DEPLOYING = "deploying"
RUNNING = "running"
STOPPED = "stopped"
ERROR = "error"
class RepairAction(str, Enum):
RESTART = "restart"
SCALE_UP = "scale_up"
SCALE_DOWN = "scale_down"
ROLLBACK = "rollback"
INCREASE_MEMORY = "increase_memory"
INCREASE_CPU = "increase_cpu"
VACUUM_DB = "vacuum_db"
CLEAR_CACHE = "clear_cache"
API 端點
認證 API
| 端點 | 方法 | 說明 |
|---|---|---|
/api/auth/login |
POST | 登入取得 JWT |
/api/auth/register |
POST | 註冊新用戶 |
/api/auth/refresh |
POST | 刷新 Token |
/api/auth/me |
GET | 取得當前用戶 |
應用 API
| 端點 | 方法 | 說明 |
|---|---|---|
/api/apps |
GET | 列出所有應用 |
/api/apps |
POST | 創建新應用 |
/api/apps/{id} |
GET | 取得應用詳情 |
/api/apps/{id} |
PUT | 更新應用 |
/api/apps/{id} |
DELETE | 刪除應用 |
/api/apps/{id}/start |
POST | 啟動應用 |
/api/apps/{id}/stop |
POST | 停止應用 |
/api/apps/{id}/restart |
POST | 重啟應用 |
部署 API
| 端點 | 方法 | 說明 |
|---|---|---|
/api/deployments |
GET | 列出部署記錄 |
/api/deployments |
POST | 觸發新部署 |
/api/deployments/{id} |
GET | 部署詳情 |
/api/deployments/{id}/cancel |
POST | 取消部署 |
/api/deployments/{id}/rollback |
POST | 回滾到此版本 |
監控 API
| 端點 | 方法 | 說明 |
|---|---|---|
/api/monitoring/dashboard |
GET | 總覽資料 |
/api/monitoring/apps/{id}/metrics |
GET | 應用指標 |
/api/monitoring/apps/{id}/health |
GET | 健康狀態 |
/api/monitoring/alerts |
GET | 告警列表 |
修復 API
| 端點 | 方法 | 說明 |
|---|---|---|
/api/repairs |
GET | 修復記錄列表 |
/api/repairs/stats |
GET | 修復統計 |
/api/repairs/apps/{id}/trigger |
POST | 手動觸發修復 |
自動修復策略
告警到修復動作映射
| 告警類型 | 修復動作 | 說明 |
|---|---|---|
HighCpuUsage |
scale_up | CPU > 80%,自動擴容 |
HighMemoryUsage |
increase_memory | 記憶體 > 85%,增加限制 |
PodCrashLoopBackOff |
restart | Pod 崩潰,嘗試重啟 |
HighErrorRate |
rollback | 錯誤率 > 5%,回滾版本 |
PodOOMKilled |
increase_memory | OOM,增加 50% 記憶體 |
HighResponseTime |
scale_up | P95 > 2s,擴容 |
DatabaseHighConnections |
vacuum_db | 連線 > 80%,執行 VACUUM |
DatabaseDeadlock |
kill_query | 發現死鎖,終止查詢 |
修復執行流程
告警觸發
│
▼
repair_service.process_alert()
│
├─ 檢查是否符合自動修復條件
│
├─ 建立 Repair 記錄
│
├─ repair_executor.execute()
│ ├─ restart: kubectl rollout restart
│ ├─ scale_up: kubectl scale --replicas +1
│ ├─ rollback: kubectl rollout undo
│ ├─ increase_memory: kubectl patch +50%
│ ├─ vacuum_db: VACUUM ANALYZE
│ └─ kill_query: pg_terminate_backend()
│
└─ 更新修復狀態 + 發送通知
支援的框架
Python 框架
| 框架 | 版本 | 預設配置 |
|---|---|---|
| FastAPI | 0.100+ | Gunicorn + Uvicorn, Port 8000 |
| Flask | 2.0+ | Gunicorn, Port 5000 |
| Django | 4.0+ | Gunicorn, Port 8000 |
JavaScript 框架
| 框架 | 版本 | 預設配置 |
|---|---|---|
| Express | 4.18+ | Node.js, Port 3000 |
| Next.js | 14+ | Node.js, Port 3000 |
| NestJS | 10+ | Node.js, Port 3000 |
K8s 模板變數
| 變數 | 說明 | 範例 |
|---|---|---|
app.name |
應用名稱 | my-api |
app.namespace |
K8s 命名空間 | user-123-my-api |
app.framework |
框架類型 | fastapi |
app.replicas |
副本數 | 2 |
app.port |
容器端口 | 8000 |
app.domain |
自訂域名 | api.example.com |
resources.cpu_request |
CPU 請求 | 100m |
resources.memory_request |
記憶體請求 | 256Mi |
運行方式
後端 (FastAPI)
cd aiops-core
# 安裝依賴
pip install -r requirements.txt
# 設定環境變數
export DATABASE_URL="postgresql://user:pass@localhost/aiops"
export JWT_SECRET="your-secret-key"
export PROMETHEUS_URL="http://prometheus:9090"
export ALERTMANAGER_URL="http://alertmanager:9093"
# 啟動服務
uvicorn api.main:app --host 0.0.0.0 --port 8000 --reload
前端 (Next.js)
cd aiops-core/web
# 安裝依賴
npm install
# 設定環境變數
echo 'NEXT_PUBLIC_API_URL=http://localhost:8000/api' > .env.local
# 開發模式
npm run dev
# 生產建置
npm run build
npm start
開發狀態
已完成 ✅
| 模組 | 檔案數 | 狀態 |
|---|---|---|
| Deploy Engine | 4 | ✅ 完成 |
| Monitor Engine | 4 | ✅ 完成 |
| Repair Engine | 4 | ✅ 完成 |
| FastAPI Backend | 8 | ✅ 完成 |
| Database Models | 3 | ✅ 完成 |
| K8s Templates | 7 | ✅ 完成 |
| Web Portal | 8 | ✅ 完成 |
| 總計 | 38 | ✅ |
待開發 ⏳
| 功能 | 優先級 | 說明 |
|---|---|---|
| 計費系統整合 | 高 | Stripe/金流整合 |
| 多租戶隔離 | 高 | K8s namespace 隔離 |
| 自訂告警規則 | 中 | 用戶自定義閾值 |
| Slack/Discord 通知 | 中 | 多渠道告警 |
| 日誌聚合 | 中 | Loki 整合 |
| 效能分析 | 低 | APM 功能 |
更新記錄
-
2026-02-13:
- 🆕 新增 WOOO AIOps 產品核心模組 (38 個檔案)
- 🆕 Deploy Engine: 支援 4 種框架的 K8s 部署
- 🆕 Monitor Engine: Prometheus + Grafana + Alertmanager 整合
- 🆕 Repair Engine: 8 種自動修復策略
- 🆕 FastAPI Backend: 6 個 API 路由模組
- 🆕 Web Portal: Dashboard、應用管理、監控、修復記錄頁面
- 🆕 Database Models: User、App、Deployment、Alert、Repair
-
2026-02-06:
- 新增 CI/CD 完整驗證腳本 (
scripts/verify-cicd.sh) - 新增環境自動安裝腳本 (
deploy/scripts/setup-environment.sh) - 新增完整一鍵部署腳本 (
deploy/scripts/full-deploy.sh) - 新增快速部署腳本 (
scripts/deploy/build-and-deploy.sh) - K8s 優化配置 (
k8s/optimized/) - 完整 K8s 配置檔案 (
k8s/00-namespace.yaml,k8s/01-secrets.yaml,k8s/03-postgres.yaml) - 系統自動啟動機制 (systemd)
- 完整部署文檔更新
- 新增 CI/CD 完整驗證腳本 (
-
2026-01-26:
- 新增一鍵部署自動化腳本系統
- 新增 PostgreSQL 慢查詢監控 API
- 新增 n8n 慢查詢自動修復工作流程
- 更新 Monitor 頁面整合所有監控狀態
⚖️ 第十三章:AI 架構完整憲法(2026-04-18 加入 + 統帥批准)
第 40 條:AI 學習數據雙寫規範(絕對禁止違反)
- ✅ 正確:所有 AI 產出(PPT 洞察、競品分析、對話記錄)必須雙寫 PostgreSQL
ai_insights+ pgvector embedding - ❌ 禁止:只寫 DB 不寫 KM(RAG 無法語意搜尋)
- ❌ 禁止:只寫 KM 不寫 DB(精確 period/sku 查詢無法命中)
- 理由:DB 是精準命中,KM 是語意搜尋,兩者互補缺一不可(ADR-007)
- 實作:NemoTron
store_insighttool call 觸發雙寫;Hermes 非同步補 embedding
第 41 條:架構決策 ADR 規範(強制要求)
- ✅ 正確:任何重大架構決策(引入新依賴、改資料庫 schema、改 AI 路由邏輯)必須建立
docs/adr/ADR-XXX-*.md - ✅ 正確:ADR 建立後同步更新
docs/adr/README.md索引 + 相關 SOT + Memory - ❌ 禁止:口頭決策不留文字記錄
- 格式:Context → Decision → Alternatives Considered → Consequences
- 目錄:
docs/adr/(2026-04-18 已建立 ADR-001 ~ ADR-007)
第 42 條:Memory 跨 Session 持久化規範(強制要求)
- ✅ 正確:重大協作 context、統帥偏好、技術決策必須寫入 Memory 目錄
- ✅ 目錄:
~/.claude/projects/.../memory/ - ✅ 索引:
MEMORY.md必須保持最新索引 - ❌ 禁止:依賴 Claude 對話 session 記憶(必有 context window 截斷問題)
- 類型分類:
user(統帥偏好)、feedback(決策回饋)、project(專案技術)、reference(地圖參考)
第 43 條:Embedding 必須本地化到 Hermes(強制要求)
- ✅ 正確:使用
bge-m3(或nomic-embed-text)掛載在192.168.0.111Ollama - ❌ 禁止:呼叫外部 Embedding API(成本 + 數據隱私雙重問題)
- 維度:
vector(1024)(ADR-003) - 理由:統帥明確要求「Hermes 機器徹底包辦所有苦力運算,把數據隱私與成本降到絕對的零」
第 44 條:NemoTron 配額耗盡 Fallback 鏈(強制要求)
- ✅ 正確:
nemoton_dispatcher_service.py必須有 try-except,HTTP 429 → 立刻切換_hermes_rule_fallback() - ❌ 禁止:配額耗盡時讓告警管線中斷(雙 11 等節慶高峰時風險最高)
- 標記:降級模式告警需帶
🟡前綴,讓統帥識別(ADR-004)
第 45 條:KM 品質分數時間衰減(強制要求)
- ✅ 公式:
effective_score = base_score × e^(-decay_rate × days_passed) - 預設 decay_rate:
0.005;decay_exempt=True用於結構性/憲法類知識 - 理由:確保 RAG 優先抓取最新適用洞察,避免歷史偏誤(ADR-005)
📌 遊戲規則全文見第零章(文件最頂部)。本章條款是第零章的 AI 專項細化。
🏷️ 專案正名記錄
- 2026-04-18:正式更名為 EwoooC(ADR-006)
- Docker image tag 維持
momo-pro-system(延後處理) - Domain 維持
mo.wooo.work與momo.wooo.work(皆指向 UAT)