部署
這一頁講的是 macOS 的部署方式——LaunchDaemon、cloudflared 與 Caddy。Walis 本身在 Windows 與 Linux 上也跑得動(見快速開始);下面的自我更新機制在哪個平台都 適用,差別只在用哪個服務管理器。
自己更新自己
Walis 內建一個更新 Walis 的任務。麻煩的地方在於建置是服務的子程序, 所以在腳本裡重啟服務會在結果寫回資料庫之前把自己殺掉——那次建置會永遠停在執行中。
解法是把工作拆成兩半:
| Daemon | 負責 |
|---|---|
com.walisayu.walis | 服務本體(以一般帳號執行) |
com.walisayu.walis-restarter | 盯著 var/restart.request,驗證暫存的 release、搬進 root 擁有的 releases/、切換 current 並於 8 秒後重啟服務 |
releases/ 與 current 由 root 擁有(755),建置腳本無法直接替換服務下次啟動要跑的執行檔。更新任務(以管理員限定的信任任務註冊)只做三件事——拉程式碼、建置到 var/staging/<時間戳>、touch 觸發檔——然後正常結束。restarter 不在服務的程序樹裡,驗證通過後才搬移並切換符號連結,重啟不會影響那次建置的結果;建置或驗證失敗就不會切換,服務維持在舊版本。
反向代理與 tunnel
<主機名稱>.example.com
→ cloudflared(LaunchDaemon)
→ Caddy 127.0.0.1:8080(LaunchDaemon)
→ 服務 127.0.0.1:11120三層都是 LaunchDaemon,重開機後不必有人登入就會回來。刻意不用 brew services—— 那是使用者 LaunchAgent,要登入才會跑。
兩個會咬人的地方:
AllowedHosts:Walis 本身接受任何主機名稱,但deploy/install.sh會把服務收成只回應localhost;127.0.0.1;walis.localhost。經反向代理、以公開名稱進來的請求會收到400 Invalid Hostname,要把名稱加進去,例如安裝時帶WALIS_ALLOWED_HOSTS='localhost;127.0.0.1;walis.localhost;walis.example.com'。- 第一位管理員:不論經反向代理或在伺服器本機開,設定畫面都會要求設定碼。 見第一次連線。
- 列出反向代理:只接受
Security__TrustedProxies列出的位址送來的轉送標頭;反向代理在同一台機器時 設Security__TrustedProxies=127.0.0.1,::1(macOS 安裝腳本會自動設定)。 - 沙箱路徑要先解析(僅 macOS):
/tmp與/var/folders的符號連結在路徑中間, 用沒解析過的路徑寫sandbox-exec規則會完全不生效,而且不會報錯。
備份
Walis 可以備份自己的資料庫(SQLite 用 VACUUM INTO,執行中也安全;PostgreSQL、MySQL 與 SQL Server 產出同一種格式)、產出檔案、你列出的額外路徑,以及用 pg_dump 另外備份 應用程式的 PostgreSQL。資料庫以與資料庫種類無關的格式放進壓縮檔,所以同一份備份可以還原到 SQLite、PostgreSQL、MySQL 或 SQL Server。壓縮檔用 Walis 自己的認證加密格式(PBKDF2-SHA256 與 AES-256-GCM 區塊),透過 Walis 還原(備份頁面或 POST /api/backup/restore),被改過或被截斷的 檔案會被拒絕;見備份與還原。
目的地:本機或掛載的路徑、S3 相容儲存(R2 或 AWS,在程序內自簽)、Dropbox、Google Drive 與 OneDrive。 只要啟用備份或設了任何目的地就強制要有通關密語——備份裡有密碼雜湊與雲端金鑰。