n8n 這兩年在台灣開發者圈子爆紅有幾個原因:AI 自動化的浪潮讓 workflow 工具重新洗牌、它開源且自架免費、介面比 Zapier 直覺很多,而且有完整的 AI Agent 節點。想把它架在自己的 VPS 上跑很合理。
但網路上多數 n8n Docker 部署教學的問題是:它們教你怎麼「跑起來」,沒教你怎麼「活得久」。照著官方快速開始的指令敲一敲,確實 5 分鐘就能看到 n8n 介面,但三個月後你會陸續遇到:OAuth 憑證整合失敗、webhook URL 顯示成 localhost、資料庫鎖死、或是某天重啟容器後所有憑證全部解不開。
這篇 n8n Docker 部署教學要做的,是把一個能撐住正式環境的架構一次講清楚,同時標記出新手最容易踩的三個坑。
為什麼要自架 n8n?成本算給你聽
先處理一個根本問題:n8n Cloud 每月起跳 20 歐元,自架成本有多少?
一台規格適中的台灣 VPS(2 vCPU / 4GB RAM / 40GB NVMe)大約 NT$400–600/月。考量到:
- 資料不出境:工作流經手的資料(客戶名單、API 金鑰、內部文件)完全在你自己的機器上
- 執行次數無上限:n8n Cloud 的計費是以工作流執行次數計算,自架只要硬體撐得住就沒限制
- 延遲可控:台灣到台灣 VPS 的延遲 5ms 左右,比連到歐洲的 n8n Cloud 快很多
缺點是你要自己負責維運。這也是這篇文章存在的理由。
環境需求與前置準備
以 Ubuntu 24.04 LTS 為例(其他發行版流程相似):
- 2 vCPU / 4GB RAM 是舒適下限。1GB 跑得起來但容易 OOM,特別是跑 AI Agent 節點時
- 一個指向你 VPS 的網域(例如
n8n.example.com),用於 HTTPS 與 webhook - Docker 與 Docker Compose v2 已安裝
快速安裝 Docker:
1 | curl -fsSL https://get.docker.com | sudo sh |
第一個坑:不要用預設的 SQLite
多數 n8n Docker 部署教學會直接 docker run n8nio/n8n,這會用預設的 SQLite 資料庫,存放在容器內。看起來很方便,但正式環境不該這樣做,原因有三:
- SQLite 併發寫入差:當工作流量一大,你會遇到
database is locked錯誤,工作流執行失敗 - 備份困難:SQLite 是單一檔案,熱備份容易損壞,冷備份要停服務
- 升級風險高:n8n 幾乎每週釋出 minor 版本,schema 變動時 SQLite 的 migration 比 PostgreSQL 更容易出狀況
正確做法是從一開始就用 PostgreSQL。下面的 docker-compose.yml 是我實際在 production 用的基礎版本:
1 | services: |
注意 ports 綁定到 127.0.0.1:5678,這代表 n8n 只接受本機連線,外部流量一定要經過反向代理進來。這是必要的,絕對不要把 5678 port 直接暴露到公網。
搭配 .env 檔:
1 | POSTGRES_USER=n8n |
第二個坑:N8N_ENCRYPTION_KEY 遺失等於憑證全毀
這是我看過最多人血淚交織的地雷。
n8n 把所有存在系統裡的憑證(OAuth token、API key、資料庫密碼等)都用 N8N_ENCRYPTION_KEY 加密後存到資料庫。如果你遺失了這把 key,所有憑證會變成無法解密的亂碼,即使資料庫還在,也沒辦法救回任何已存的憑證。
幾個關鍵行為:
- 第一次啟動時如果沒設定
N8N_ENCRYPTION_KEY,n8n 會自動產生一把,存在容器內的~/.n8n/config檔案 - 如果容器重建、volume 不在,那把 key 就消失了
- 之後你把
N8N_ENCRYPTION_KEY環境變數補上,但如果不是原來那把,舊憑證全部解不開
正確做法:在第一次啟動前,自己產生並明確設定:
1 | openssl rand -hex 32 |
把輸出結果放到 .env 的 N8N_ENCRYPTION_KEY= 後面。然後——這步超級重要——把這把 key 備份到獨立於伺服器的地方。密碼管理器、加密筆記、離線檔案都可以,但不要只存在這台 VPS 上,否則 VPS 掛掉你就全毀了。
反向代理設定:讓 HTTPS 和 webhook 都正常運作
n8n 不內建 HTTPS,也不處理 Let’s Encrypt,正確做法是前面擺一個反向代理。以 Nginx 為例:
1 | server { |
這裡的關鍵是四個 header:Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto。少了 X-Forwarded-Proto,n8n 會以為請求是 HTTP 進來的,即使你在 docker-compose.yml 裡設定了 N8N_PROTOCOL=https,OAuth 回調還是會生成 http:// 開頭的 URL,導致 Google、Slack 等 OAuth 認證全部失敗。
WebSocket 那兩個 proxy_set_header 少寫,n8n 編輯器會一直顯示「連線中斷」的提示,執行工作流看不到即時結果。
第三個坑:webhook URL 顯示成 localhost
照著上面的設定跑起來後,你到 n8n 建立一個 webhook 節點,可能會看到 URL 顯示為 http://localhost:5678/webhook/xxx——這是最多人在 n8n 社群論壇問的問題。
原因是 n8n 預設用請求的 host header 來組 webhook URL。即使反向代理設對了,在某些情況下它還是會抓到內部的 localhost。強制解法是直接指定 WEBHOOK_URL 環境變數:
1 | environment: |
N8N_PROXY_HOPS=1 告訴 n8n「前面有 1 層反向代理,要信任 X-Forwarded-* header」。如果你有 Cloudflare + Nginx 兩層,要設成 2。
改完後 一定要完全重啟容器(docker compose down && docker compose up -d,不是 restart),環境變數才會重新載入。
啟動與驗證
第一次啟動:
1 | docker compose up -d |
看到 Editor is now accessible via 就代表啟動成功。打開瀏覽器到 https://n8n.example.com,第一次會要你建立 owner 帳號——信箱、密碼一定要記好,n8n 自架版沒有「忘記密碼」功能,要救回只能直接改資料庫。
驗證幾件事:
- 建一個 webhook 節點,看 URL 是不是
https://n8n.example.com/webhook-test/xxx - 用外部工具(手機熱點、Postman)去打那個 URL,確認 webhook 能收到
- 設定一個 OAuth 憑證(Google Sheets 之類),看 redirect URL 是不是
https://n8n.example.com/rest/oauth2-credential/callback
備份策略
架好只是開始,備份才是真的考驗。你要備份的有三樣:
1. PostgreSQL 資料庫(放工作流、執行記錄、憑證):
1 | docker compose exec -T postgres \ |
寫成 cron,每天凌晨備份並上傳到 Object Storage。
2. N8N_ENCRYPTION_KEY:前面講過了,存到密碼管理器,而且要跟資料庫備份「分開存」。如果資料庫跟 key 都丟在同一台伺服器的同一個備份檔裡,被人拿到就全毀了。
3. .n8n volume:存放 custom nodes、設定檔。直接打包:
1 | tar czf n8n_data_$(date +%Y%m%d).tar.gz ./n8n_data |
升級的注意事項
n8n 每週幾乎都有新版,不建議用 latest tag 在 production。改用固定版本:
1 | image: docker.n8n.io/n8nio/n8n:1.72.0 |
升級時固定流程:備份 → 讀 release notes → 小版本直接 pull 新 image → 大版本(如 0.x → 1.x)要看 breaking changes 文件。
PostgreSQL 升級更要小心。如果你要從 16 升到 17,不是改個 tag 就好,要做 pg_dumpall 再匯入新版。直接改 image tag 會因為 data directory 版本不符而啟動失敗。
結語
n8n 自架其實不難,難的是撐過第一次遇到 OAuth 失敗、webhook 收不到、憑證解不開的那幾個凌晨兩點。這篇文章講的三個坑——用 PostgreSQL、備份 ENCRYPTION_KEY、設對反向代理——是我看過最多人被絆倒的地方,把它們處理好,後續維運會輕鬆很多。
跑 n8n 對網路穩定度要求不低,特別是有對接 LINE、Telegram 或 OAuth 服務時,任何斷線都會讓工作流執行失敗或 token 過期。NCSE Network 的 VPS 採用 Intel Xeon Gold CPU 與 NVMe SSD,搭配台灣是方電訊機房的低延遲網路,很適合跑長期運行的自動化服務。如果你正在找能穩定跑 n8n 的機器,歡迎到 NCSE Network VPS 方案頁 看看,或加入我們的 Discord 社群 跟其他開發者交流部署經驗。