VPS 用 Docker 自行代管 Supabase 完整指南
在自有伺服器執行官方 Supabase Docker 堆疊,了解必須替換的示範密鑰、14 個服務、建議 8 GB RAM、備份與安全更新方式。
您要建置的內容
自行代管 Supabase,表示在自己的伺服器上執行官方 Docker Compose 堆疊:Postgres、其前端的 REST API、驗證服務、檔案儲存、即時 websocket,以及 Studio 儀表板。您只需複製一個存放庫、編輯一個 .env 檔案,然後啟動約 14 個容器。這些容器會共同運作,形成一個由您控制的 Supabase 專案。
安裝程序很簡短。最容易出問題的是 .env 檔案。該檔案內含已發布於存放庫中的示範密鑰。使用這些預設值啟動的堆疊,任何找到它的人都能存取。本指南說明您必須替換的密鑰、各服務的用途、堆疊實際需要的記憶體容量,以及如何在不刪除資料庫的情況下進行更新。
如果您不熟悉 Compose,請先閱讀 VPS 上的 Docker Compose 基礎知識。以下內容均假設 docker compose version 已能輸出版本資訊。
實際包含的堆疊元件
Supabase 不是單一程式。Compose 檔案會在同一個網路上啟動一組獨立服務。了解各服務的用途後,才能將一長串容器名稱轉化為可供除錯的資訊。
db是載入 Supabase 擴充功能的 PostgreSQL。其他所有服務都會與它通訊。如果此容器狀態不正常,其他服務也都會失敗。kong是 API 閘道。它監聽 port 8000,並將/rest/v1/、/auth/v1/和/storage/v1/路由至正確的後端。這是唯一應該對外公開的容器。rest是 PostgREST。它讀取 PostgreSQL 結構描述,並將其提供為 REST API,因此建立新資料表後,不需撰寫程式碼即可產生新的端點。auth是 GoTrue。它會簽發用於識別使用者的 JSON Web Token (JWT)。storage和imgproxy負責處理檔案上傳與影像調整大小。realtime會透過 websocket 串流資料庫變更。studio和meta分別是儀表板及其背後的管理 API。analytics(Logflare) 和vector會收集記錄,而supavisor是 PostgreSQL 連線集區器。
這份清單說明了下方資源數字的由來。您執行的不只是資料庫,而是資料庫加上十多個支援服務。
規模規劃:準備 8 GB RAM
截至 2026 年 7 月,在全新安裝且尚未加入您自己的資料或流量時,此堆疊閒置時約使用 2.5 至 3 GB 的常駐記憶體。分析服務和 Studio Node.js 程序是兩個最大的單一記憶體使用者。2 GB 伺服器會啟動容器,之後其中一個通常會被核心的記憶體不足終止程序終止,通常是 analytics 或 db。症狀是容器持續重新啟動,並以結束代碼 137 結束。
對於任何您需要依賴的環境,請配置 8 GB RAM 和 4 vCPU。如果可以接受繁重查詢與 Studio 工作階段同時執行時速度較慢,4 GB 也足以供個人開發環境使用。磁碟空間同樣重要,因為 Postgres、儲存磁碟區和日誌資料都位於專案目錄下。先配置 40 GB,並持續監控。
安裝:複製官方儲存庫
支援的做法是將主儲存庫中的 docker 目錄複製到您自行建立的專案目錄。這種分離很重要,因為之後的 git pull 不會覆寫您的 .env。
git clone --depth 1 https://github.com/supabase/supabase
mkdir supabase-project
cp -rf supabase/docker/* supabase-project
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project
docker compose pulldocker compose pull 會下載數 GB 的映像檔。完成時,每個服務都應標示為 Pulled。此處出現 manifest unknown 錯誤,表示上游已移除指定的映像標籤。修正方式是重新抓取較新的儲存庫副本,而不是手動編輯標籤。
首次啟動前必須變更的密鑰
請在啟動堆疊前完成這些操作,不要等到啟動後才處理。其中幾個值會在首次啟動時寫入資料,因此之後變更就必須重設資料庫。
此存放庫提供產生器,可正確產生所有值,包括必須使用新的 JWT secret 簽署的 2 個 API keys。
sh utils/generate-keys.sh --update-env此指令碼會將 JWT_SECRET、ANON_KEY、SERVICE_ROLE_KEY、SECRET_KEY_BASE、REALTIME_DB_ENC_KEY、VAULT_ENC_KEY、PG_META_CRYPTO_KEY 以及 Logflare tokens 的新值寫入 .env。它需要 openssl;任何標準的 Ubuntu 映像通常都已包含此項目。
以下 2 個值不會由指令碼設定,必須在 .env 中手動編輯:
POSTGRES_PASSWORD。只能使用字母和數字。此處的標點符號會破壞數個服務透過串接字串建立的連線字串。發生的錯誤看起來會像驗證錯誤,而不是剖析錯誤,導致人員在錯誤的地方尋找問題。DASHBOARD_USERNAME和DASHBOARD_PASSWORD。這些是 Studio 的基本驗證認證。預設密碼實際上就是this_password_is_insecure_and_should_be_updated。
請了解為何不能自行建立 ANON_KEY 和 SERVICE_ROLE_KEY。這 2 個值都是使用 JWT_SECRET 簽署的 JWT。閘道會在每個要求上驗證該簽章,因此與您的 secret 不相符的 key 會遭到 {"message":"Invalid authentication credentials"} 拒絕。這是自行代管時最常見的失敗原因:操作人員變更了 JWT_SECRET,卻保留示範 keys。請一律同時產生這 3 個值。
請將 SERVICE_ROLE_KEY 視同 root 密碼。它會完全繞過資料列層級安全性。只能將它放在伺服器端程式碼中,不得放在其他位置。
將 SITE_URL 和 API_EXTERNAL_URL 設定為使用者實際存取的位址,例如 https://supabase.example.com。Auth 會根據這些值建立電子郵件確認連結和 OAuth 回呼連結。若保留 http://localhost:8000,所有使用者都會被導向各自的電腦。
接著檢查目前的設定:
sh run.sh secrets啟動並確認其運作正常
sh run.sh start
docker compose psrun.sh start 會包裝 docker compose up -d --wait,因此只有在健康檢查通過後才會返回。每個服務都應顯示 running (healthy) 或 running。首次啟動需要 2 到 4 分鐘,因為 Postgres 會先執行初始化指令碼,之後其他元件才能建立連線。
如果容器正在重新啟動,請依服務名稱讀取其日誌:
docker compose logs db
docker compose logs authStudio 隨後會使用連接埠 8000,並要求輸入您設定的儀表板使用者名稱和密碼。
不要將 port 8000 暴露在公用網際網路上
Kong 在 8000 上使用純 HTTP。每個 API key 和每個使用者密碼都會以明文通過網路,Studio 憑證則使用基本驗證,也就是 base64 編碼,而非加密。
在前方配置反向 Proxy,並在該處終止 TLS(傳輸層安全性),同時將 Kong 綁定至 loopback 位址,讓其他來源無法存取。在 docker-compose.yml 中,kong port 對應會變成 127.0.0.1:8000:8000,Proxy 會將要求轉送至該位置。在數個 Compose 應用程式前配置 Traefik 說明憑證相關設定。
也要在防火牆封鎖其餘連接埠,因為 Docker 會透過寫入自己的 iptables 規則來發布 port,而簡單的 ufw 設定看不到這些規則。為什麼 Docker 容器會忽略你的 ufw 規則 說明了這個陷阱。
備份資料庫,而不是目錄
Postgres 資料位於 ./volumes/db/data 的繫結掛載中。容器執行期間複製該目錄會產生不完整的複本,因為 Postgres 會緩衝寫入,而磁碟上的檔案只有在檢查點時才保持一致。還原這些檔案通常可以成功,但有時會悄悄遺失最後幾筆交易。這是備份可能發生的最糟失敗模式。
請改用傾印。pg_dumpall 會在容器內執行,並產生一致的快照:
docker exec -t supabase-db pg_dumpall -U postgres > supabase-$(date +%F).sql在信任該檔案前,請確認檔案不是空的。接著依排程將這些傾印傳送到伺服器外部,這正是 使用 restic 進行加密的異地備份 的用途。同時備份您的 .env。遺失 JWT_SECRET 會使所有已發行的 token 失效,也會使所有儲存的加密秘密無法讀取。
上傳的檔案位於 ./volumes/storage。這些是一般檔案,因此直接複製即可。
更新且不遺失資料
Supabase 會在 docker-compose.yml 中固定映像版本,因此除非您執行更新,版本不會變更。每次都應先建立傾印。
docker compose pull
sh run.sh recreaterecreate 會停止堆疊,並使用新映像重新啟動。您的資料仍會保留,因為資料位於主機上的繫結掛載中,而不是容器內。進行主要版本升級前,請先閱讀儲存庫中的 CHANGELOG.md,因為 Postgres 主要版本升級不會自動執行,且需要先建立傾印,再還原資料。
若要套用 Compose 檔案本身的變更,請再次複製上游儲存庫,並將其中的 docker 目錄複製到您的專案中。請注意不要覆寫 .env。
完整重設會刪除包括資料庫在內的所有內容。這是另一個獨立的指令碼,執行時會要求確認:
sh reset.shFAQ
為什麼我的 API 呼叫會回傳「Invalid authentication credentials」?
您的 ANON_KEY 或 SERVICE_ROLE_KEY 並非使用目前位於 .env 的 JWT_SECRET 進行簽署。閘道會驗證每個要求的簽章,簽章不符時便拒絕要求。使用 sh utils/generate-keys.sh --update-env 重新產生這 3 個值,然後執行 sh run.sh recreate,讓服務讀取新值。
我可以在 2 GB VPS 上執行自行託管的 Supabase 嗎?
不可靠。截至 2026 年 7 月,這個堆疊在閒置時接近 3 GB,因為它會執行約 14 個服務。因此,2 GB 伺服器會因記憶體不足終止容器,您會在 docker compose ps 中看到結束代碼 137。正式環境請使用 8 GB;單人開發至少需要 4 GB。
自行託管的 Supabase 是否包含 edge functions?
是。Compose 檔案包含以 Deno 為基礎的函式執行環境,並會提供您放在 ./volumes/functions 下的任何內容。它不包含託管平台的全球部署網路,因此您的函式會在單一位置的單一伺服器上執行。
如何直接連線至 Postgres 資料庫?
在伺服器本身使用 docker exec -it supabase-db psql -U postgres 開啟互動式 shell。若使用外部用戶端,請透過連接埠 5432 上的 Supavisor 連線,並使用使用者 postgres.<POOLER_TENANT_ID> 和您的 POSTGRES_PASSWORD。不要將該連接埠開放至網際網路。請透過 VPN 或 SSH 通道存取。
為什麼我的驗證確認電子郵件會連結至 localhost?
SITE_URL 和 API_EXTERNAL_URL 在 .env 中仍使用預設值。驗證服務會根據這 2 個值建立所有確認連結和密碼重設連結,因此會傳送設定值所指定的位址。請將兩者都設為實際的公開 URL,然後重新建立堆疊。