Files
vps/plans/2026-08-02-vps-maintenance-ansible-restic-refactor-v1.md
T

8.3 KiB
Raw Blame History

VPS 維護專案重構:Ansible + systemd timers + Restic

Objective

將現有 VPS 維運知識庫漸進重構為一個以 Ansible 管理一致性、以 systemd timers 執行每日唯讀檢查、以 Restic 建立加密異機備份的個人 SRE 維運專案。現納管 mx2、us2、hk2 與 Matrix K3s 主機。自動化預設只能觀測與告警;受 allowlist 和顯式確認保護的 Compose reconciliation 可處理已審查的服務重建,DNS、機密與破壞性資料操作仍需人工確認。

Confirmed Decisions

  • 定位為個人 SRE/維運手冊庫,而非全自動修復平台。
  • 已納管 mx2、us2、hk2 與 Matrix K3smx、us1、us4 待完成盤點與緊急存取驗證後才納管。
  • 每日自動做唯讀檢查與 Email 通知;每週人工審查、每月人工維護、每季復原演練與權限盤點。
  • 以 Email 作為唯一告警與摘要通道。
  • 採用本機快速復原加密異機副本的 3-2-1 最小可行策略。
  • 真實機密不進 Git;repo 只保存去敏設定結構與操作/驗證紀錄。
  • 日常存取使用非 root SSH key;禁止 root/password SSH,維護 provider/recovery console 緊急存取。
  • 採用 Ansible + systemd timers + Restic 作為技術基線。

Implementation Plan

  • Status: Done — 建立去敏 Ansible inventory。 為 mx2、us2、hk2 與 Matrix 建立主機與服務群組,將非機密主機資料與現有人類可讀的 inventory/hosts.md 對應;理由是提供可審查的機器可讀編排層,且不取代既有事實來源。
  • Status: Done — 實作 audit-only Ansible playbook。 只收集連線、OS、磁碟、systemd、Docker Compose 和依賴命令狀態,不做設定或服務改動;理由是先確認控制面與真實現況。
  • Status: Done — 定義跨服務健康檢查結果合約。 統一去敏結構化結果、日誌位置、嚴重度及 exit code,讓人工執行、systemd 和 Ansible audit 可共同消費;理由是避免各服務告警語意漂移。
  • Status: Done — 保留並模組化 Mailcow 健康檢查。 持續檢查 Compose、watchdog、queue、listeners、HTTP/HTTPS、TLS、SMTP、DNS/PTR/MX/SPF;理由是現有腳本已覆蓋關鍵郵件服務面向。
  • Status: Done — 實作 Vaultwarden 唯讀健康檢查。 驗證 Compose/Postgres、HTTPS、有效設定、SMTP AUTH、備份新鮮度及機密指紋一致性,禁止輸出機密;理由是 config.json 優先於 .env,且 SMTP 漂移已有已知風險。
  • Status: Done — 實作 PowerDNS 唯讀健康檢查。 驗證容器、版本與安全公告、ns1/ns2 served SOA、API、Web UI、備份新鮮度與必要設定;理由是同時覆蓋公開 DNS 與 secondary 同步。
  • Status: Done — 使用 Ansible 部署 systemd healthcheck service/timer。 每台主機本機執行每日檢查,具 persistent 排程、權限、logrotate 和一致錯誤處理;理由是控制端離線不應阻止巡檢。
  • Status: Done — 部署 Email 告警與每日摘要。 Critical/unknown 立即通知、健康狀態每日摘要、重複失敗抑制;SMTP 真實認證僅在各主機受限路徑保存;理由是已選定 Email 為唯一通知通道。
  • [!] Status: Blocked — 決定 Restic 異機 repository 與存取隔離。 選擇具加密傳輸、權限隔離與可承受保留需求的 S3/B2/SFTP 或等價目的地;理由是無異機 repository 即無法滿足已確認的 3-2-1 政策。阻塞:本地實作依要求未虛構 backend、repository 或 credentials。
  • Status: Done (templates gated) — 部署 Vaultwarden 與 PowerDNS 的 Restic 備份。 將既有一致性資料庫 dump、必要資料目錄及復原元資料加密同步,並加入 snapshot 年齡和 restic check 驗證;理由是兩者已有本機備份但缺少異機保護。啟用被 repository 決策和主機端受限設定檔阻擋。
  • [!] Status: Blocked — 完成 Mailcow 備份設計審查。 官方流程已確認:以 /opt/mail/helper-scripts/backup_and_restore.sh backup all(或經明確核准的元件集)先產生一致性備份,再由 Restic 同步該輸出;不得直接複製 Docker volumes。阻塞:仍需決定本機備份位置、保留期、排程及異機 Restic repository。
  • Status: Done (templates gated) — 部署 Restic backup、retention、forget/prune 與 check timers。 與現有資料庫 dump 時段錯開,所有 repository 認證與密碼留在伺服器端受限檔案;理由是保持備份可用與成本可控。啟用被 repository 決策和主機端受限設定檔阻擋。
  • [!] Status: Blocked — 補齊服務級復原 runbook。 阻塞:需在選定 Restic repository、建立實際 snapshot 並確認各服務的實際備份輸出後,才能編寫可驗證的 restore 前置條件、順序與 rollback;禁止臆造 backend/credentials 或未驗證還原命令。
  • [!] Status: Blocked — 執行隔離式復原演練。 阻塞:尚未選定/配置 Restic 異機 repository,亦尚無可供還原的異機 snapshot;演練不得對現有生產資料執行。
  • Status: Done — 實作受控 common baseline 與 maintenance playbook。 僅在 audit 穩定後納入 SSH 稽核、時間同步、logrotate、更新預覽與人工確認的維護操作;理由是避免工具導入期間同時改變服務狀態。
  • Status: Done (2026-08-03) — 將例行操作收斂為 Ansible 入口。 新增 on-demand health report 與 allowlisted Compose reconciliationhealth、maintenance preview、baseline 現可涵蓋 Matrix。互動式 Mailcow 更新、資料遷移、DNS 與機密操作保留人工程序。
  • Status: Done (separate change defined) — 將 PowerDNS API key、DB password 與 TSIG 輪替列為分離變更。 已明確保持 API key、DB password 與 TSIG 為三項獨立、需人工核准的變更,並要求逐步驗證 Auth、Poweradmin、AXFR/NOTIFY、DNSSEC 與 ns2 同步;未輪替任何機密。
  • [!] Status: Blocked — 盤點 mx、us1、us4。 阻塞:inventory 僅記錄 TBD SSH/角色或缺少完整事實,尚未提供可驗證的存取方式與 provider/recovery console 資訊;不得猜測或嘗試未授權存取。

Verification Criteria

  • 四台 active 主機能被 Ansible 正確解析;Compose 主機可執行 audit,且 audit 不產生主機變更。
  • 四台主機每日產生去敏健康結果;服務、容量、TLS、公開端點和備份新鮮度異常均能被偵測。
  • 正常狀態寄送 Email 摘要;受控測試異常能觸發一次可讀且不含機密的 Email 告警。
  • 每個核心服務至少有一份加密、異機、可列出且通過完整性檢查的 Restic snapshot。
  • 至少完成一次隔離式實際還原,並確認其結果符合或明確量化偏離服務 RPO/RTO。
  • 自動化排程不包含更新、重啟、修復、秘密輪替或 DNS 變更。
  • Repo、Ansible vars、產出日誌及 Email 均不包含任何真實機密。

Potential Risks and Mitigations

  1. Mailcow 備份未保持資料一致性。
    Mitigation: 先依官方方式完成備份範圍與還原設計,再上線排程;以隔離還原驗證作為完成門檻。

  2. Ansible 設定錯誤改動生產系統。
    Mitigation: 先導入 audit-only;變更 playbook 必須使用 dry-run/diff、明確 tag 與人工確認,且先限制單一 host。

  3. 機密出現在 Git、Ansible output 或 Email。
    Mitigation: 真實值只存主機受限檔案;去敏輸出、no-log 機制和測試用機密掃描為強制要求。

  4. Timer 成功但公開服務實際不可用。
    Mitigation: 同時執行本機 Compose/DB 檢查與外部 HTTP、SMTP、TLS、DNS 檢查。

  5. PowerDNS 密鑰輪替中斷 DNS 管理或 zone transfer。
    Mitigation: API key、DB password、TSIG 分批處理;每步都驗證 primary/secondary 同步、DNSSEC 和管理 UI。

Alternative Approaches

  1. 純 shell + systemd,不使用 Ansible:初期較快,但設定與排程容易跨主機漂移,且難以審查或擴充;不建議作為長期方案。
  2. Ansible + 集中式監控平台:可增加儀表板與趨勢,但平台本身需額外維護;等 Email 摘要無法滿足需求時再評估。
  3. 立即導入 SOPS + age:可使加密設定進 Git,但需先完成密鑰生命週期與緊急存取設計;建議列為後續階段。