升级到 Postgres 17
Start a new self-hosted Supabase deployment with Postgres 17, or upgrade an existing Postgres 15 installation.
自托管的 Supabase 默认附带 Postgres 17。本指南涵盖两种情况:
🌐 Self-hosted Supabase ships with Postgres 17 by default. This guide covers two scenarios:
- 新部署 - 使用 Postgres 17 全新开始(没有现有数据)
- 升级现有部署 - 使用
pg_upgrade从 Postgres 15 迁移到 Postgres 17
使用 Postgres 17 的新部署 #
🌐 New deployment with Postgres 17
Postgres 17 是默认版本,所以一个新的自托管实例(没有现有数据)会从 Postgres 17 开始——不需要覆盖设置:
🌐 Postgres 17 is the default, so a new self-hosted instance with no existing data starts on Postgres 17 - no override needed:
1sh run.sh start剩下的设置保持不变(参见 Docker 安装指南)。
🌐 The rest of the setup is unchanged (see the Docker install guide).
GraphQL 默认是关闭的
在全新的 Postgres 17 部署中,pg_graphql 扩展 默认是禁用的。可以在 Studio (数据库 > 扩展) 中启用它,或者使用 create extension pg_graphql;。已经使用 GraphQL 的数据库在升级后会保留它。
🌐 On a fresh Postgres 17 deployment, the pg_graphql extension is disabled by default. Enable it from Studio (Database > Extensions) or with create extension pg_graphql;. Databases that already use GraphQL keep it after an upgrade.
如果新的 Postgres 17 容器启动失败,记得检查是否有旧的 db-config Docker 卷。具体信息请参见 Postgres 17 在残留的 db-config 卷情况下启动失败。
🌐 If the new Postgres 17 container fails to start, make sure to check for an old db-config Docker volume. See Postgres 17 fails to start with a leftover db-config volume for details.
升级现有的 Postgres 15 部署 #
🌐 Upgrade an existing Postgres 15 deployment
升级现有部署使用 pg_upgrade 来就地迁移数据。附带的升级脚本会自动补齐整个过程。
🌐 Upgrading an existing deployment uses pg_upgrade to migrate data in place. The included upgrade scripts automates the full process.
升级的作用 #
🌐 What the upgrade does
- 拉取特定的 Postgres 17 镜像并提取升级二进制文件
- 从 Supabase 的 Postgres 仓库拉取补充升级脚本
- 停止所有自托管的 Supabase 容器
- 在临时的 Postgres 15 容器中运行
pg_upgrade - 在临时的 Postgres 17 容器中运行额外任务(重新启用扩展、应用补丁、运行
VACUUM ANALYZE) - 交换数据目录(原来的会保留作为备份)
- 启动自托管的 Supabase,使用 Postgres 17
- 应用升级后的迁移并将扩展版本与目标镜像对齐
创建备份 #
🌐 Create a backup
在升级前备份你的数据
你应该自己做一个独立备份,以防硬盘故障或其他问题。
🌐 You should create your own independent backup in case of disk failure or other issues.
升级脚本会在最后一步自动将 pgsodium 密钥和原始数据目录保存为 ./volumes/db/data.bak.pg15。不过,建议 始终 在开始之前自己创建一个独立备份:
🌐 The upgrade script automatically preserves the pgsodium key and original data directory as ./volumes/db/data.bak.pg15 as the final step. However, it is recommended to always create your own independent backup before starting:
备份数据库数据目录:
🌐 Back up the database data directory:
1cp -a ./volumes/db/data ./volumes/db/data-manual-backup备份 pgsodium 加密密钥(存储在名为 Docker 的卷中):
🌐 Back up the pgsodium encryption key (stored in a Docker named volume):
1docker compose run --rm db cat /etc/postgresql-custom/pgsodium_root.key > ./pgsodium_root.key.backupdb-config Docker 命名卷包含 pgsodium 根加密密钥。如果你丢失了这个密钥,而你又有 vault 秘密数据,它们就无法恢复了。上面的 cp -a 会备份数据目录,但不会备份那个命名卷。
🌐 The db-config Docker named volume contains the pgsodium root encryption key. If you lose this key and have vault secrets, they become unrecoverable. The cp -a above backs up the data directory but NOT the named volume.
可选的话,也做一个逻辑备份:
🌐 Optionally, take a logical backup too:
1docker exec supabase-db pg_dumpall -h localhost -U supabase_admin > ./pg15_dump.sql要求 #
🌐 Requirements
- 至少需要 当前数据库大小的 2 倍 + 5 GB 的可用磁盘空间(
pg_upgrade会复制数据目录;升级压缩包大约 1.2 GB) - 脚本在每个主要步骤都会提示确认(使用
--yes可跳过提示) - 在开始升级之前,所有自托管的 Supabase 容器都必须运行
- 需要
bash - 必须以 root 用户或使用
sudo来运行
Postgres 17 中移除的扩展 #
🌐 Extensions removed in Postgres 17
以下扩展在 Postgres 17 版本中不可用。如果发现有这些扩展,升级脚本会提示你删除它们:
🌐 The following extensions are not available in Postgres 17 builds. The upgrade script will prompt you to drop them if any of these are found:
| 扩展 | 备注 |
|---|---|
timescaledb | 不支持 Postgres 17 |
plv8 | 不支持 Postgres 17 |
plcoffee | plv8 的配套 |
plls | plv8 的配套 |
在自托管的 Supabase 设置中,上述扩展默认都没有安装。如果你手动安装了其中任何一个并且需要保留它们,不要继续升级。
🌐 None of the above extensions are installed by default in the self-hosted Supabase setup. If you have installed any of them manually and need to keep them, do not proceed with the upgrade.
运行升级 #
🌐 Run the upgrade
1sudo bash utils/upgrade-pg17.sh脚本在某些步骤可能需要你的确认(例如,检查磁盘空间、是否禁用扩展,或者删除之前的备份时)。
🌐 The script might require your confirmation at some steps (e.g., while checking for disk space, or whether to disable extensions, or remove previous backups).
升级后 #
🌐 After the upgrade
要确认 Postgres 17 是否正在运行:
🌐 To verify that Postgres 17 is running:
1docker compose exec db psql -U postgres -c "SELECT version();"原来的 Postgres 15 数据保存在 ./volumes/db/data.bak.pg15。pgsodium 根密钥保存为 ./volumes/db/pgsodium_root.key.bak.pg15。升级用的二进制压缩包缓存于 ./volumes/db/pg17_upgrade_bin_*.tar.gz。一旦你确认一切正常,就可以回收磁盘空间了:
🌐 The original Postgres 15 data is preserved at ./volumes/db/data.bak.pg15. The pgsodium root key is saved as ./volumes/db/pgsodium_root.key.bak.pg15. The upgrade binaries tarball is cached at ./volumes/db/pg17_upgrade_bin_*.tar.gz. Once you have verified that everything works, you can reclaim disk space:
1rm -rf ./volumes/db/data.bak.pg15 \2./volumes/db/pgsodium_root.key.bak.pg15 \3./volumes/db/pg17_upgrade_bin_*.tar.gz在确认升级之前不要删除 data.bak.pg15。只有在备份存在时才可以回滚。
🌐 Do not delete data.bak.pg15 until you have verified the upgrade. Rollback is only possible while the backup exists.
回滚 #
🌐 Rollback
如果你需要回退到 Postgres 15(以 root 身份运行以下命令):
🌐 If you need to revert to Postgres 15 (run the following commands as root):
1docker compose down && \2rm -rf ./volumes/db/data && \3mv ./volumes/db/data.bak.pg15 ./volumes/db/data && \4sh run.sh config add pg15 && \5docker compose run --rm db chown -R postgres:postgres /etc/postgresql-custom/ && \6sh run.sh start这会恢复原始数据目录,修复 db-config 卷上的文件所有权,并配置 Supabase 使用旧的 Postgres 15 镜像。Supabase 的 Postgres 15 和 17 镜像使用不同的用户 ID,所以 chown 和启动必须以 Postgres 15 运行。
🌐 This restores the original data directory, fixes file ownership on the db-config volume, and configures Supabase to use the old Postgres 15 image. Supabase's Postgres 15 and 17 images use different user IDs, so the chown and startup must run as Postgres 15.
自定义 Postgres 配置 #
🌐 Custom Postgres configuration
Postgres 17 镜像在启动时会从 /etc/postgresql-custom/conf.d/ 加载任何 .conf 文件。这个目录在名为 db-config 的卷上,所以更改可以在重启后保留。
🌐 The Postgres 17 image loads any .conf files from /etc/postgresql-custom/conf.d/ on startup. This directory is on the db-config named volume, so changes persist across restarts.
这是 Supabase Postgres 17 的图片功能。Postgres 15 的图片无法从 conf.d/ 加载文件。
🌐 This is a Supabase Postgres 17 image feature. The Postgres 15 image does not load files from conf.d/.
要添加自定义 Postgres 设置,请在卷中创建一个 .conf 文件。由于 conf.d/ 位于 Docker 命名卷(而不是绑定挂载)上,你需要通过容器来写入:
🌐 To add custom Postgres settings, create a .conf file in the volume. Since conf.d/ is on a Docker named volume (not a bind mount), you need to write through the container:
1docker exec supabase-db bash -c 'cat > /etc/postgresql-custom/conf.d/custom.conf << EOF2max_connections = 2003EOF'重启以应用(max_connections 需要完全重启):
🌐 Restart to apply (max_connections requires a full restart):
1sh run.sh restart db核实新的设置:
🌐 Verify the new settings:
1docker compose exec db psql -U postgres -c "SHOW max_connections;"升级过程详情 #
🌐 Upgrade process details
升级脚本将核心迁移工作委托给来自 supabase/postgres 仓库的两个脚本(ansible/files/admin_api_scripts/pg_upgrade_scripts/)。
🌐 The upgrade script delegates the core migration work to two scripts from the supabase/postgres repository (ansible/files/admin_api_scripts/pg_upgrade_scripts/).
第1阶段 - 迁移数据(Postgres 15 容器):
- 禁用与
pg_upgrade不兼容的扩展(pg_graphql、pg_stat_monitor、pg_backtrace),并生成 SQL 以在升级后重新启用它们 - 暂时赋予
postgres角色超级用户权限(pg_upgrade需要) - 解压之前保存的 Postgres 17 二进制文件压缩包,并运行
initdb来创建一个新的空数据库 - 在进行更改之前运行
pg_upgrade --check来验证升级是否可以成功 - 停止 Postgres 15 并运行
pg_upgrade将所有数据迁移到新数据库 - 将 Postgres 配置和
pg_upgrade生成的 SQL 脚本复制到暂存目录,以便进行下一阶段
第二阶段 - 完成(Postgres 17 容器):
- 将升级后的数据目录放到位并启动 Postgres 17
- 为 Wrappers、
pg_net、pg_cron和 Vault 应用扩展兼容性补丁(修复所有权、权限和外部服务器选项) - 运行由
pg_upgrade生成的 SQL 脚本来更新系统目录和扩展版本 - 重新启用在第一阶段被禁用的扩展
- 授予预定义角色(
pg_monitor、pg_read_all_data、pg_signal_backend,在 Postgres 16 及以上版本还包括pg_create_subscription)并撤销临时超级用户权限 - 重启 Postgres 并运行
vacuumdb --all --analyze-in-stages来重建优化器统计信息
在两个阶段之后,升级脚本会应用通常只在全新安装时运行的迁移,并将已安装的扩展与目标镜像的版本对齐。然后,它会将原来的 Postgres 15 数据目录保留为备份,并启动包含 Postgres 17 的完整 Supabase 堆栈。
🌐 After both phases, the upgrade script applies migrations that normally run only on a fresh install, and reconciles installed extensions to the target image's versions. It then preserves the original Postgres 15 data directory as a backup and starts the full Supabase stack with Postgres 17.
故障排除 #
🌐 Troubleshooting
pg_upgrade 因复制槽错误而失败 #
🌐 pg_upgrade fails with replication slot errors
pg_upgrade 如果有活动的复制槽就无法继续。默认的自托管安装没有任何复制槽,但如果你设置了逻辑复制或者有自定义的复制配置,请在升级前删除这些复制槽:
1docker exec supabase-db psql -h localhost -U supabase_admin -d postgres -c "2 SELECT pg_drop_replication_slot(slot_name)3 FROM pg_replication_slots;4"然后重新运行升级脚本。升级后需要手动重新创建复制槽。
🌐 Then re-run the upgrade script. Replication slots will need to be manually recreated after the upgrade.
数据目录“权限被拒绝” #
🌐 "Permission denied" on the data directory
升级脚本会自动修复文件所有权(Postgres 15 和 17 使用不同的 UID)。如果你仍然看到权限错误,请运行:
🌐 The upgrade script fixes file ownership automatically (Postgres 15 and 17 use different UIDs). If you still see permission errors, run:
1docker compose run --rm db \2chown -R postgres:postgres /var/lib/postgresql/datapgsodium / Supabase Vault 错误 #
🌐 pgsodium / Supabase Vault errors
db-config 命名的卷包含位于 /etc/postgresql-custom/pgsodium_root.key 的 pgsodium 根加密密钥。在升级过程中会保留该卷。千万不要运行 docker compose down -v,因为这会破坏命名卷并导致 vault 密钥无法恢复。
🌐 The db-config named volume contains the pgsodium root encryption key at /etc/postgresql-custom/pgsodium_root.key. This volume is preserved during the upgrade. Never run docker compose down -v as this destroys named volumes and makes vault secrets unrecoverable.
升级后服务无法连接 #
🌐 Services fail to connect after upgrade
重启所有服务以使用新的数据库:
🌐 Restart all services to pick up the new database:
1sh run.sh recreate升级时的磁盘空间问题 #
🌐 Disk space issues during upgrade
升级需要空间用于:
🌐 The upgrade needs space for:
- 升级压缩包(约1.2 GB,已缓存以便重新运行)
- 你的数据库的完整副本(由
pg_upgrade创建) - 原始数据(作为备份保存)
脚本使用 /tmp(如果设置了则使用 TMPDIR)作为其暂存目录,该目录存放下载的 tar 包和升级脚本。如果你的 /tmp 文件系统较小或挂载空间有限,你可以将它指向其他位置,例如:
🌐 The script uses /tmp (or TMPDIR if set) for its staging directory, which holds the downloaded tarball and upgrade scripts. If your /tmp filesystem is small or mounted with limited space, you can point it to a different location, e.g.:
1sudo TMPDIR=/mnt/my-tmp bash utils/upgrade-pg17.sh如果在升级过程中空间用完了,最安全的方法是回滚并清理磁盘空间,然后再重试。
🌐 If you run out of space mid-upgrade, the safest path is to roll back and free up disk space before retrying.
Postgres 17 因为遗留的 db-config 卷无法启动 #
🌐 Postgres 17 fails to start with a leftover db-config volume
如果你是从头开始部署 全新的 Postgres 17(没有使用升级脚本),而容器启动失败,最可能的原因是之前 Postgres 15 安装遗留下的 db-config 卷。启动容器时不要使用 -d 选项,或者检查日志中是否有关于 postgresql.conf 或其他配置不匹配的错误。
🌐 If you are starting a fresh Postgres 17 deployment (not using the upgrade script) and the container fails to start, the most likely cause is a leftover db-config volume from a previous Postgres 15 installation. Start the containers without the -d option or check the logs for errors about postgresql.conf or other configuration mismatch.
要解决这个问题,先删除旧的卷,然后让 Postgres 17 初始化一个干净的配置:
🌐 To fix, remove the old volume and let Postgres 17 initialize a clean configuration:
1sh run.sh stop && \2docker volume rm $(docker volume ls --filter "name=db-config" --format '{{.Name}}') && \3sh run.sh start删除 db-config 卷会破坏任何自定义的 Postgres 配置和 pgsodium 根密钥。只有在没有现有数据或保管库秘钥的新安装情况下才这样做。
🌐 Removing the db-config volume destroys any custom Postgres configuration and the pgsodium root key. Only do this for fresh installations with no existing data or vault secrets.
从手动备份恢复 #
🌐 Restoring from a manual backup
如果升级失败,而脚本自带的回滚功能不足,请从在 创建备份 步骤中创建的手动备份中恢复:
🌐 If the upgrade fails and the script's built-in rollback isn't sufficient, restore from the manual backups created in the Create a backup step:
恢复数据:
🌐 Restore the data:
1docker compose down && \2rm -rf ./volumes/db/data && \3cp -a ./volumes/db/data-manual-backup ./volumes/db/data && \4sh run.sh config add pg15将 pgsodium 密钥恢复到 db-config 卷:
🌐 Restore the pgsodium key to the db-config volume:
1docker compose run --rm db \2 sh -c 'cat > /etc/postgresql-custom/pgsodium_root.key' < ./pgsodium_root.key.backup && \3docker compose run --rm db \4 chown -R postgres:postgres /etc/postgresql-custom/ && \5docker compose run --rm db \6 chmod 600 /etc/postgresql-custom/pgsodium_root.key使用 Postgres 15 启动自托管 Supabase:
🌐 Start self-hosted Supabase with Postgres 15:
1sh run.sh start