VPS 安裝部署與安全指南
本份完整指南涵蓋在通用 VPS(虛擬專用伺服器)上部署 InsForge 以供正式環境使用、以安全最佳實務強化你的伺服器,以及透過安全的更新與回復流程長期維護。適用範圍:本指南與雲端服務商無關,適用於任何 Linux VPS——建議使用 Ubuntu/Debian——不論提供商是 DigitalOcean、Hetzner、Linode、Vultr、OVH,或是裸機伺服器。如需特定雲端平台的指南(AWS EC2、GCP、Azure、Render),請參閱本節中的其他指南。
📋 目錄
先決條件
開始之前,請確認你已具備以下條件:- 一台執行 Ubuntu 22.04 LTS 或 Ubuntu 24.04 LTS 的 VPS(Debian 12 同樣適用)
- 伺服器的 root 或 sudo 權限
- 一個已註冊的網域名稱(建議用於正式環境)
- 對 Linux 命令列與 SSH 有基本了解
第一部分 — 部署
1. 伺服器需求
💡 提示:若正式環境有多位使用者,建議從 4 GB 記憶體開始。使用 docker stats 監控用量,並依需求進行垂直擴充。
InsForge 由以下 4 項協同運作的服務組成:
2. 初始伺服器設定
2.1 連線至你的 VPS
2.2 更新系統套件
2.3 建立部署使用者(非 root)
切勿以 root 身分執行正式環境服務。請建立一個專用的使用者:2.4 設定時區
2.5 啟用自動安全性更新
3. 安裝 Docker 與 Docker Compose
3.1 安裝 Docker 引擎
3.2 將部署使用者加入 Docker 群組
3.3 驗證 Docker 安裝
⚠️ 安全性注意事項:將使用者加入 docker 群組會授予其在主機上等同於 root 的權限。對於專用的部署使用者而言這是可接受的,但不應套用於共用伺服器上的一般用途帳號。
4. 使用 Docker Compose 部署 InsForge
4.1 取得倉庫
JWT_SECRET、ENCRYPTION_KEY、ROOT_ADMIN_PASSWORD、POSTGRES_PASSWORD 產生到 .env。不啟動任何東西。
不想把腳本管線給 shell?先讀一遍再執行:
4.2 啟動 InsForge
4.3 驗證所有服務皆正常運作
running 或 healthy 狀態:
4.4 測試健康檢查端點
5. 環境變數設定
編輯你的.env 檔案,為正式環境設定 InsForge:
5.1 必要變數
在上線正式環境之前,以下變數必須從預設值修改:⚠️ 重要:JWT_SECRET與ENCRYPTION_KEY應使用不同的值。若未設定ENCRYPTION_KEY,InsForge 會退回使用JWT_SECRET——但之後若再輪替JWT_SECRET,將會永久性地損毀所有已儲存的密鑰(API 金鑰、OAuth 權杖等)。
5.2 資料庫變數
setup.sh 已經產生了 POSTGRES_PASSWORD。Postgres 僅在初始化資料叢集時讀取它,
因此在 4.2 啟動 stack 之後再修改不會變更資料庫密碼——除非你尚未啟動任何東西,
否則請勿改動。
5.3 連接埠變數
InsForge 使用的預設連接埠:💡 若這些連接埠與你 VPS 上其他服務衝突,可以自行修改。
COMPOSE_PROJECT_NAME 是所有容器、卷與網路的名稱前綴:
⚠️ 同一台機器上的第二個實例必須改成自己的值,連接埠也要另設。兩個.env共用同一個名稱時,在其中一個裡執行docker compose up會接管並重建另一個的容器。
5.4 部署功能所需的變數
以下變數僅在你打算使用 InsForge 的部署功能(透過控制台部署專案)時才需要設定。若你不需要部署功能,可以跳過本節。⚠️舊版 zip 上傳介面deploy/docker-compose/docker-compose.yml不會把PROJECT_ID傳給insforge容器。需要使用時,請加入該服務的environment區塊。
POST /api/deployments 還需要一個 S3 bucket,用 5.5 的 S3_* 變數設定。
5.5 選用變數
6. 反向代理設定
反向代理位於 InsForge 之前,負責 TLS 終止、HTTP/2,並提供不含連接埠號的簡潔網址。方案 A:Nginx(建議)
6.1 安裝 Nginx
6.2 建立站台設定
insforge.yourdomain.com 替換為你實際的網域:
6.3 啟用該站台
方案 B:Caddy(自動 HTTPS)
Caddy 是更簡單的替代方案,能自動處理 TLS 憑證。安裝 Caddy
設定 Caddy
7. HTTPS / TLS 設定
若你在第 6 步選擇了 Caddy,TLS 已自動處理完畢,請直接跳至第二部分。
7.1 安裝 Certbot(適用於 Nginx)
7.2 取得 SSL 憑證
- 透過 HTTP 挑戰驗證網域擁有權
- 從 Let’s Encrypt 取得已簽署的憑證
- 自動更新你的 Nginx 設定以提供 HTTPS 服務
- 設定 HTTP → HTTPS 重新導向
7.3 驗證自動續簽
Let’s Encrypt 憑證每 90 天到期一次。Certbot 會安裝一個用於自動續簽的 systemd 計時器:7.4 為 HTTPS 更新 InsForge 環境設定
取得憑證後,更新你的.env 以使用 HTTPS 網址:
第二部分 — 安全
8. 連接埠管理
應對外開放的連接埠(透過反向代理)
應對外部關閉的連接埠
以下連接埠僅用於 Docker 內部服務間通訊,絕不應對外公開:⚠️ 重要:預設的docker-compose.yml會將連接埠繫結至0.0.0.0(所有介面),而非127.0.0.1。這代表 Docker 會將服務直接對外公開,完全繞過 UFW(Docker 會直接操作 iptables)。你必須為docker-compose.yml中每個發布的連接埠加上127.0.0.1:前綴:若少了這個前綴,網際網路上的任何人都能直接連上這些服務——包括使用預設憑證的 PostgreSQL。詳情請參閱第 9.2 節。
9. 防火牆設定(UFW)
UFW(Uncomplicated Firewall)是在 Ubuntu 上管理 iptables 最簡單的方式。9.1 安裝並設定 UFW
⚠️ 重要:務必在啟用 UFW 之前先允許 SSH,否則你會把自己鎖在伺服器外面。
9.2 Docker 與 UFW 的注意事項
Docker 會直接操作 iptables,這可能繞過 UFW 規則。要避免此情況: 方案 1 — 將連接埠繫結至 localhost(建議): 在你的docker-compose.yml 中,為連接埠加上 127.0.0.1: 前綴:
⚠️ 停用 Docker 的 iptables 管理需要手動設定網路。對大多數情況而言,建議採用方案 1。
9.3 將 SSH 限制至你的 IP(選用)
為求最高安全性,可將 SSH 存取限制至已知的 IP 位址:10. 以非 root 使用者執行服務
InsForge 的 Docker 映像檔已遵循非 root 的最佳實務:- 正式環境的 Dockerfile 設定了
USER node(UID 1000),因此容器內的應用程式行程以非 root 使用者執行。 - 系統層級的 Docker 操作由
deploy使用者(於第 2.3 步建立)管理,該使用者透過docker群組取得對 Docker 通訊端的存取權限。
docker-compose.yml 中為每個服務加入 security_opt,以防止權限提升:
11. SSH 強化
11.1 使用 SSH 金鑰驗證
11.2 停用密碼驗證
在確認以金鑰為基礎的驗證運作正常後:11.3 安裝 Fail2Ban
Fail2Ban 會自動封鎖出現惡意行為(例如 SSH 暴力破解)的 IP:12. Docker 安全性
12.1 保持 Docker 為最新版本
12.2 限制容器資源(選用)
避免單一容器耗盡所有資源:12.3 唯讀根檔案系統(進階)
若要進一步強化,可將容器檔案系統盡可能掛載為唯讀:⚠️ 這需要經過測試——部分服務需要可寫入的目錄來存放快取或暫存檔案。
12.4 限制 CORS 來源
預設情況下,後端允許所有來源。它會將請求的Origin 標頭原樣反映回應中,並且針對函式代理回應,會設定 Access-Control-Allow-Origin: *。這對本機開發相當方便,但對正式環境而言過於寬鬆。對於正式部署,請將允許的來源限制在你實際提供服務的網域(例如你的控制台與應用程式網域),如此其他網站便無法對你的 API 發出帶有憑證的跨來源請求。
13. 憑證與密鑰管理
應做 ✅
- 將密鑰儲存在
.env檔案中,並設定chmod 600 ~/insforge/.env - 為
JWT_SECRET與ENCRYPTION_KEY使用不同的值 - 使用
openssl rand -base64 32產生密鑰 - 將你的
.env檔案備份至安全的離線位置
不應做 ❌
- 將
.env提交至版本控制系統 - 讓多個變數重複使用同一組密鑰
- 在正式環境中使用預設密碼(
change-this-password、postgres) - 透過未加密的管道分享密鑰
第三部分 — 更新與維護
14. 更新前備份
更新前務必先備份。 如此一來,若發生任何問題,你都有可回復的途徑。14.1 備份資料庫
14.2 備份環境變數與資料卷
14.3 記錄目前版本
15. 更新 InsForge
15.1 更新倉庫
先更新 checkout 再拉映像檔:它帶著 compose 檔案和 Postgres 的設定。.env.example 裡新增的變數需要手動抄進你的 .env。
15.2 拉取最新映像檔
15.3 套用更新
Ctrl+C 可停止追蹤日誌。
15.4 驗證更新
16. 回復流程
若更新造成問題,請依照以下步驟進行回復:16.1 停止異常的服務
16.2 固定回先前的版本
-
在
.env旁邊寫pin.yml,填 14.3 記錄的版本: -
附加到
.env中的COMPOSE_FILE,保留既有項目: -
docker compose up -d -
回到可用版本後,將
:pin.yml移除。
16.3 還原資料庫(如有需要)
僅當此次更新包含造成問題的資料庫遷移時,才需要還原資料庫:16.4 還原環境變數檔案(如有變更)
17. 自動化備份
設定一個 cron 工作以進行每日自動備份:17.1 建立備份腳本
17.2 使用 Cron 排程
17.3 異地備份(建議)
為了災難復原,請將備份複製到外部位置:18. 監控與健康檢查
18.1 檢查服務狀態
18.2 檢視日誌
18.3 健康檢查端點
從外部監控健康檢查端點。以下是一個簡單的 cron 檢查:https://insforge.yourdomain.com/api/health。
快速參考
常用指令
安全檢查清單
- 已建立部署使用者(非 root)
- 已啟用 SSH 金鑰驗證
- 已停用 SSH 密碼驗證
- 已停用 root 登入
- 已啟用 UFW 防火牆(僅開放 22、80、443 連接埠)
- Docker 連接埠已繫結至
127.0.0.1 - 已安裝並啟用 Fail2Ban
-
JWT_SECRET已從預設值修改(32 位元以上) - 已設定
ENCRYPTION_KEY(與JWT_SECRET不同) -
ROOT_ADMIN_PASSWORD已從預設值修改 -
POSTGRES_PASSWORD已從預設值修改 -
.env檔案權限已設定為600 - 已透過 Certbot 或 Caddy 啟用 HTTPS
- 已設定每日自動備份
- 已啟用無人值守的安全性更新
疑難排解
啟用 UFW 後無法連線
若你被鎖在伺服器外,請使用你的 VPS 提供商的網頁主控台(頻外存取)執行:Docker 繞過 UFW
Docker 會直接操作 iptables。請依照第 9.2 節所述,在docker-compose.yml 中將連接埠繫結至 127.0.0.1。
服務無法啟動
SSL 憑證無法續簽
連接埠衝突
資料庫連線問題
🆘 需要協助?
- 文件:https://docs.insforge.dev
- Discord 社群:https://discord.com/invite/MPxwj5xVvW
- GitHub Issues:https://github.com/insforge/insforge/issues