如果你只是做一个小 MVP、团队里没人想长期盯着备份和升级,那就别急着自建,直接用 Supabase Cloud 更省心。只有当你已经明确需要数据控制、稳定负载、特殊网络策略,或者必须把组件和备份节奏握在自己手里时,VPS 自托管才值得开始。
这也是很多人最容易算错的地方:Supabase 自托管不是“买一台 2 核 4G 就省钱了”,而是把数据库、网关、认证、对象存储、邮件、备份和升级责任一起接过来。下面这篇按 2026 年官方 Docker 路线来讲,尽量把坑一次说清楚。
| 方案 | 月成本主要由什么组成 | 运维责任 | 备份和恢复 | 升级节奏 | 数据位置与网络 | 更适合谁 |
|---|---|---|---|---|---|---|
| Supabase Cloud | 平台套餐、超额用量、附加能力 | 平台负责底层服务可用性,你主要管业务 | 平台能力更多,自己重点做业务层导出和演练 | 跟平台节奏走 | 区域选择有限,但省去公网入口和反向代理细节 | 小团队、MVP、没人轮值的项目 |
| VPS 自托管 | VPS、异地备份、SMTP、可选对象存储、维护时间 | 你自己负责 Docker、HTTPS、监控、密钥和恢复 | 数据库、Storage、Functions、密钥都要自己管 | 你决定何时升级,也要自己承担回滚 | 可以自己挑机房、DNS、入口和防火墙,但也要自己兜底 | 有运维能力、负载较稳定、必须掌控数据位置的团队 |
再拆细一点看:
- 月成本:云版主要是套餐和超额用量;自建至少要算上 VPS、异地备份、SMTP、可选对象存储,还有维护时间。
- 备份:云版很多事平台帮你做;自建必须自己证明数据库、文件和密钥都能恢复。
- 升级:云版点几下就结束的事,自建要自己看
CHANGELOG.md、核对版本组合、做回滚准备。 - 数据位置:云版按可选区域走;自建可以自己选机房和网络策略,但故障也归你处理。
所以我更建议这样判断:如果你现在还在纠结“要不要学 Docker、要不要再装 Caddy、SMTP 麻不麻烦”,大概率先用云版更合适。自建只有在两个前提同时成立时才值得:一是你真的需要数据控制、网络边界或更灵活的组件接入;二是你能接受以后每次升级前都要备份、核对版本和做回滚。
真要买机子,先把基础配置思路过一遍,可以顺手看这篇 VPS 配置选择指南。
按照当前官方自托管栈,2 vCPU、4GB RAM、40GB SSD 是完整组件能跑起来的起点,当前数据库基线是 Postgres 17。如果你打算长期跑正式项目,我更推荐从 4 vCPU、8GB RAM、80GB SSD 起步。
这两个档位都只是起点,不是容量承诺,更不是 QPS 保证。原因很简单:Supabase 不是单容器应用,它至少会拉起 Postgres、Studio、Kong、Auth、PostgREST、Realtime、Storage、imgproxy、Edge Runtime 和 Supavisor。
也就是说,2 核 4G 更像“完整栈能落地、可以验证和小流量运行”的线;4 核 8G 才是你做升级、跑备份、开监控时不容易手忙脚乱的线。如果你平时还要在同一台机子上跑别的 Docker 服务,内存余量一定要留出来。
磁盘也别只盯着系统镜像体积。数据库数据目录、WAL、Storage 文件、Functions、备份压缩包都会持续增长,40GB 很快就能被吃掉一大截。正式环境直接从 80GB 起步,后面做备份和恢复演练时会舒服很多。
很多人第一次看 Supabase,会误以为它只是“Postgres + 一个管理后台”。实际上不是。
- Postgres 17 是核心数据层;
- Kong 负责 API 网关;
- Auth 负责注册、登录和 OAuth 回调;
- PostgREST 暴露 REST API;
- Realtime 负责订阅和 WebSocket;
- Storage 处理文件;
- imgproxy 处理图片变换;
- Studio 是管理界面;
- Edge Runtime 跑 Functions;
- Supavisor 负责连接池。
所以这类项目不能只盯着“容器能不能起来”,还要看健康检查、磁盘空间、连接池模式、SMTP 和备份链路。Docker 生产环境里最容易被忽略的就是这些外围开销,相关思路可以对照这篇 Docker Compose 生产健康检查与资源限制指南。
正式开搞之前,先把下面几项准备好:
- 一台干净的 Linux VPS;
- Git、Docker Engine、Docker Compose v2;
- 已经解析到 VPS 的正式域名;
- 公网入口只开放 80/443,SSH 22 只允许可信 IP、堡垒机、VPN 或云防火墙白名单访问;
- 一个单独的部署目录和可持续增长的磁盘空间。
这里的“只开放 80/443”不是口号,而是为了避免后面一路把 Kong 开发端口、数据库端口和连接池端口一起暴露出去。很多人第一次自建,容器一起来就顺手把 5432、6543、8000、8443 都放到公网,短期省事,长期是事故来源。
主流程建议直接跟官方 Docker 目录走,而且用 sparse clone,只拿 docker/ 这部分,不要把整个仓库都拉下来,也不要把来源不明的一键脚本当主路径。
git clone --filter=blob:none --no-checkout --depth=1 --quiet https://github.com/supabase/supabase
cd supabase
git sparse-checkout init --cone
git sparse-checkout set docker
git checkout --quiet
cd ..
mkdir supabase-project
cp -rf supabase/docker/* supabase-project
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project
接下来先别急着 up -d。.env.example 里的默认值只是开发示例,尤其是邮件、URL 和密钥,生产环境直接照抄,后面注册、找回密码和 OAuth 会一起出问题。
另外,部署目录最好单独放,不要和杂七杂八的应用混在一起。后面做备份、迁移、清理旧包和权限收紧时,目录边界越清楚越省心。
官方已经给了 helper scripts,直接在复制出来的 Docker 目录里跑:
sh utils/generate-keys.sh
sh utils/add-new-auth-keys.sh --update-env
第二个脚本会在生成新 auth keys 后同步更新 .env,所以跑完脚本再回头核对变量最省事。然后把 .env 至少分组检查一遍:
- 数据库密码;
- JWT / API keys;
- Studio 登录凭据;
- 各类加密 keys;
SUPABASE_PUBLIC_URL;API_EXTERNAL_URL;SITE_URL;- redirect allow-list;
- SMTP;
- 可选的 S3 兼容存储凭据。
这一步最好的做法不是“先随便填、等报错再改”,而是一次把对外地址、发信、密钥和管理后台账号都梳理完。因为 Supabase 里很多问题不是单点失败,而是链路失败:比如你只改了 SITE_URL 没改 API_EXTERNAL_URL,表面上控制台能开,实际邮箱链接和 OAuth 回调还是错的。
这里有两个特别容易写错:
API_EXTERNAL_URL必须是一个带协议的有效外部地址,而且路径要以/auth/v1结尾。SITE_URL指向你的应用来源,不是随便填一个控制台地址。
另外,SERVICE_ROLE_KEY 只能放服务端,别写进前端构建变量、静态页面或者公开仓库。
按当前官方基线,Supavisor 的 5432 是 session 模式,6543 是 transaction 模式。这两个端口都不应该直接暴露给整个公网,更不该在安全组里写成 0.0.0.0/0。
如果你只是容器内部访问,走默认内部网络就行;如果你确实需要远程数据库访问,至少也要加上可信来源规则、VPN、SSH 隧道或者私网。
这里再强调一次:不要把“能从外网连上数据库”当成部署成功标准。对大多数业务来说,真正应该暴露到公网的只有站点入口,数据库和连接池应该尽量留在内网边界里。
启动和健康检查命令保持官方顺序:
docker compose pull
docker compose up -d --wait
docker compose ps
这一步如果有容器反复重启,不要先想着重置数据,先查日志和磁盘。reset.sh 不是日常排障按钮,误用就是清数据。
生产环境建议直接加官方 Caddy overlay:
sh run.sh config add caddy
sh run.sh start
这个阶段你要确认三件事:
- DNS 已经指到当前 VPS;
- 公网只需要
80/443; - Realtime 的 WebSocket 也会通过反向代理走 HTTPS。
开发阶段常见的 8000/8443、数据库相关的 5432/6543,都不该直接对全网开放。Kong 开发端口要收回去,外部入口统一交给 Caddy。想把反向代理和自动证书流程理顺,可以对照这篇 Caddy 反向代理自动 HTTPS 指南。
如果你还有 Realtime 订阅、管理后台和 API 同时可用的要求,也别另外开第二套公网端口,统一让 Caddy 处理 TLS 和入口更清晰。这样出了证书、跳转或 WebSocket 问题,排查也只需要盯一层入口。
先说邮件。很多人安装成功后发现注册邮件不发、重置密码链接无效,本质上不是 Supabase “坏了”,而是还在用 .env.example 里的假 SMTP 配置。生产环境必须换成真实 SMTP 服务,并核对发件域名、端口、认证方式和回信地址。
再说 URL。SUPABASE_PUBLIC_URL、API_EXTERNAL_URL、SITE_URL 和 OAuth 回调必须是同一套对外逻辑里的有效地址,不然最常见的问题就是:控制台能打开,但邮箱链接跳错域名,或者第三方登录回调 400。
再补一句经验判断:如果你未来会把应用和 Supabase 分开域名部署,那就更要早点把这几个地址理顺。开发阶段偷懒硬填一个临时地址,等上线切正式域名时,往往要把邮件模板、重定向白名单和第三方登录一起返工。
Storage 默认会把文件放到本地 ./volumes/storage/。如果只是单机项目,这样最省事;只有当你明确需要把文件和主机生命周期解耦、想做跨机共享,或者备份策略已经要求对象存储时,再切到 S3 兼容后端,比如 S3 或 R2。没必要为了“架构完整”在同一台 VPS 上再塞一个 MinIO。什么时候该上对象存储,可以顺着看这篇 VPS 什么时候需要对象存储。
自托管 Supabase 最容易漏掉的不是 SQL,而是恢复完整实例所需的其他文件。最少要把下面几类分开保存:
- 数据库逻辑备份;
pgsodium_root.key;volumes/storage;volumes/functions;.env、docker-compose.yml、docker-compose*.yml、volumes/api、volumes/proxy、volumes/pooler等当前生效配置。
命令可以先按下面这组做:
mkdir -p backups
docker exec supabase-db pg_dumpall -h localhost -U supabase_admin > "backups/supabase-$(date +%F).sql"
docker compose run --rm db cat /etc/postgresql-custom/pgsodium_root.key > "backups/pgsodium_root.key"
tar -czf "backups/supabase-files-$(date +%F).tar.gz" volumes/storage volumes/functions
tar -czf "backups/supabase-config-$(date +%F).tar.gz" .env docker-compose.yml docker-compose*.yml volumes/api volumes/proxy volumes/pooler
这几份文件都要加密或严格控权,而且要复制到另一个故障域,不能只躺在同一台 VPS 上。.env 和 pgsodium_root.key 更不能提交到 Git。备份策略怎么做恢复演练,可以参考这篇 VPS 备份、恢复与演练指南。
很多团队说自己“有备份”,实际只是每天导出一个 SQL 文件到本地磁盘。真出问题时,你还得面对 Storage 文件没了、Functions 丢了、加密 root key 不见了、SMTP 配置也忘了的情况。能不能恢复完整实例,决定权不在 pg_dumpall 跑没跑,而在你有没有把这些拼图一起留住。
生产升级时,正确顺序应该是:先看官方 Docker 目录里的 CHANGELOG.md 和 versions.md,确认这次变更影响了什么;然后做完整备份;再更新官方 Compose 配置,拉取同一套已测试版本;最后重启并验证健康状态。顺便提醒一下,部分 Restore 文档现在还会提到 PG15,但当前 Docker 部署指南、Docker 的 CHANGELOG.md/versions.md 和 PG17 升级指南,已经把 PG17 作为现行基线,判断版本时以后者为准。
千万别图快,直接把镜像改成 latest。Supabase 的 Docker 目录本来就是按成组版本测试的,你单独追某一个最新镜像,很容易把 Auth、网关或数据库兼容性搞乱。
升级后的基础检查至少包含这些:
docker compose ps
docker stats --no-stream
docker compose logs --since=30m kong auth db supavisor
df -h .
df -i .
如果是 OOM,先看是不是 2 核 4G 已经被 Studio、备份任务、数据库和业务流量一起压满;如果是 Storage 上传失败,先排查磁盘权限、剩余空间和本地 volumes/storage;如果是 OAuth 回调异常,第一时间回头检查外部 URL 和回调白名单。
这里的核心思路是:先查状态,再决定是否回滚。不要一看到升级后有异常,就直接删容器或重跑初始化脚本。只要数据库卷和配置没先保护好,错误排查很容易变成二次事故。
Supabase 自托管上线后,最少要盯四类信号:
- 容器是否持续健康;
- 内存有没有逼近上限;
- 磁盘空间和 inode 是否吃紧;
kong、auth、db、supavisor是否持续报错。
如果你现在还没有完整监控栈,先用上面那组命令把基础巡检做起来也行。等业务稳定后,再补更系统的采集和告警,不然第一次出 OOM 或证书异常时,你只能靠猜。对应的监控扩展思路,后面也可以接入更完整的采集体系,但前提是先把最关键的容器和磁盘信号跑通。
能跑完整栈,但更适合验证、小流量或内部项目。只要你还要备份、看日志、顺手跑别的容器,4 核 8G 会稳很多。
先别重装。先看 docker stats --no-stream 和最近 30 分钟日志,确认是不是内存被 Studio、备份任务、数据库和业务峰值一起顶满。2 核 4G 机器最常见的解法不是“再调一堆神秘参数”,而是先减并发、停掉无关容器,必要时直接升到 4 核 8G。
按当前官方基线,Supavisor 的 5432 是 session,6543 是 transaction。大多数应用优先按官方推荐场景选,不要两个都裸露到公网。
先查 SMTP,不要先怪 Auth。假发件地址、端口被封、TLS 配错,都会让注册和找回密码一起失效。
先对照 SUPABASE_PUBLIC_URL、API_EXTERNAL_URL、SITE_URL、redirect allow-list 和第三方平台里的回调地址。大多数 400 或跳错页的问题,根源都在外部 URL 没统一。
优先查三件事:本地 ./volumes/storage/ 权限对不对,磁盘和 inode 够不够,上传入口是不是仍然经过正确的 HTTPS 反向代理。如果你已经切到 S3 或 R2,再补查凭据、bucket 权限和 endpoint。
当你的主要矛盾还是“先把产品做出来”,而不是“必须自己掌握数据位置、网络和升级节奏”时,优先云版。
一句话总结:没运维人手、项目还在试错期,用 Supabase Cloud;业务已经稳定,而且你愿意长期承担备份、升级、SMTP 和安全责任,再上 VPS 自托管。
自建真正值钱的不是“看起来省了一层平台”,而是你知道自己为什么要接管这些责任,也准备好了对应的 SOP。只要这个前提没想清楚,云版通常更划算。
反过来说,如果你已经有明确的数据位置要求、要把入口、SMTP、对象存储和备份策略都收回到自己的标准流程里,那这篇路线就是值得落地的。别追求一步到位的“完美架构”,先按官方 Docker、官方密钥脚本、官方 Caddy overlay 和完整备份链路把第一版跑稳,比什么都重要。
