本文介绍如何使用Supabase迁移工具进行数据迁移,支持Supabase Cloud到阿里云RDS Supabase的迁移以及RDS Supabase实例间的迁移,提供CLI和Web UI两种使用方式。
背景信息
Supabase迁移工具支持以下迁移场景:
从 Supabase Cloud 迁移到阿里云 RDS Supabase(从云端迁出)
阿里云 RDS Supabase 实例间迁移(源端和目标端均为阿里云 RDS Supabase)
工具提供两种使用方式:
CLI模式:终端直接执行迁移,适用于CI/CD、K8s Job、脚本自动化场景。
Web UI模式:提供可视化配置界面、一键迁移和实时进度日志。
迁移覆盖用户认证数据、业务数据、对象存储文件和边缘函数四类核心数据资产。
功能特性
Web UI:提供可视化配置、一键迁移、实时进度和日志查看。
CLI模式:支持终端直接执行迁移,适用于CI/CD、K8s Job和脚本自动化场景。
支持按需指定 schemas、buckets 和 functions 的迁移范围,无需整库全量迁移。
支持在恢复前清理目标端,避免与已有对象冲突。
Storage 迁移自动保留正确的 MIME Content-Type,文件迁移后可直接在线预览。
Edge Functions 支持 CLI 和 API 两种部署方式,迁移到 RDS Supabase 时推荐使用 API 方式。
支持通过环境变量(
MIGRATOR_前缀)覆盖配置项,便于在容器化部署中传入凭据。版本检查:自动检测
pg_dump与源端、目标端数据库服务器版本的兼容性,避免因版本不匹配导致迁移失败。
迁移管道
迁移工具支持以下4条迁移管道,按照固定顺序依次执行:
顺序 | 管道 | 说明 |
1 | Auth | 迁移 |
2 | Database | 使用 |
3 | Storage | 通过 Supabase Storage REST API 流式下载源端所有 bucket 中的文件,并上传至目标端,自动保留 MIME Content-Type。 |
4 | Edge Functions | 下载源端函数的 eszip 包,通过 API 或 Supabase CLI 部署到目标端。 |
Auth 管道必须在 Database 管道之前执行。原因是业务表通常包含指向 auth.users 的外键,若先恢复业务表则会因外键约束失败。
Auth 用户数据迁移
仅迁移 auth 表的数据(不含 DDL),因为目标端 GoTrue 服务已自动初始化并管理 auth schema。
默认迁移
auth.users和auth.identities。可选包含
auth.mfa_factors。使用
SET session_replication_role = replica跳过触发器与约束检查,加快批量插入。冲突(duplicate key)作为 warning 处理,不中断迁移。
数据库迁移
使用 pg_dump/pg_restore 完整迁移数据库 schema 和 data。
支持
custom(推荐)和plain两种 dump 格式。可指定特定 schemas(例如仅迁移
public),无需整库迁移。可选在恢复前清理目标端(
DROP SCHEMA CASCADE+CREATE),避免与已有对象冲突。可选包含 roles。
Storage 文件迁移
通过 Supabase Storage REST API 完成 bucket 与文件的复制。
自动创建目标端不存在的 bucket,已存在的 bucket 不修改属性。
流式传输文件内容,支持大文件迁移而不会占满内存。
并发控制:默认 5 个 worker 并行传输。
保留正确的
Content-Type,文件迁移后可直接在线预览。上传使用 upsert 策略(
x-upsert: true),重复迁移会覆盖同名文件。支持按 object 清单迁移:除按 bucket 过滤外,还可精确指定要迁移的 object,适合补迁失败文件或只迁移部分文件场景。配置
storage.objects(bucket/path清单,支持多级目录路径)后,工具将跳过全量扫描、只迁移清单内的 object,且优先级高于buckets(忽略 bucket 过滤)。详细使用方式请参见按 object 清单迁移。
按 object 清单迁移
对于补迁失败文件或仅需迁移少量文件的场景,可通过 object 清单精确指定要迁移的 object,跳过全量扫描。工具提供以下三种入口,任选其一即可:
命令行内联(逗号分隔):适合临时迁移少量 object。
rds-supabase-migrator migrate storage -c config/rds-to-rds.yaml \ --objects "course-videos/test-course/Lesson1.mp4,student-answers/uuid/file.png"从文件读取:适合大量 object 的场景,每行一个
bucket/path,以#开头的行和空行自动忽略。rds-supabase-migrator migrate storage -c config/rds-to-rds.yaml --objects-file objects.txt在配置文件中设置
storage.objects:全局生效,CLI 与 Web UI 都会读取该清单;在 Web UI 的 Storage 配置区亦可填写。migration: storage: enabled: true objects: - "course-videos/test-course/Lesson1.mp4" - "student-answers/uuid/file.png"
对于临时或一次性的失败重试,也可使用工具内置的 scripts/retry_storage.py 脚本。常规场景推荐直接使用上述内置能力。
Edge Functions 部署
支持两种部署方式,迁移到 RDS Supabase 时推荐 API 方式。
API 方式(推荐):通过
POST /functions/v1/manage/deploy?slug={slug}接口以 multipart/form-data 方式上传函数包。CLI 方式:调用
supabase functions deploy命令完成部署。
前提条件
已创建 RDS Supabase 项目并处于运行中状态。创建方法请参见开通RDS Supabase项目。
已将运行迁移工具的机器出口 IP 添加到下列实例的白名单中:
RDS Supabase 项目托管的 RDS PostgreSQL 实例白名单,用于
pg_restore直连。添加方法,请参见设置IP白名单。RDS Supabase实例配置白名单,添加方式为在 RDS Supabase 项目详情页的白名单信息区域添加。
源端 Supabase 项目侧也需放通迁移工具的出口 IP。
说明RDS 实例间迁移场景:源端和目标端 RDS Supabase 托管的 PostgreSQL 实例均需开通公网端点,并将迁移工具机器的出口 IP 分别加入源端和目标端的白名单。
运行迁移工具的机器已安装 Python 3.10 及以上版本。
运行迁移工具的机器已安装 PostgreSQL 客户端工具(
pg_dump、pg_restore、psql),且客户端版本不低于源端和目标端 PostgreSQL 服务器版本中的较高者。
注意事项
RDS Supabase 默认数据库为
supabase_db,目标端连接串中必须使用该数据库名,例如postgresql://postgres:PASSWORD@pgm-xxx.pg.rds.aliyuncs.com:5432/supabase_db。若误连到postgres库,会导致业务表恢复到错误的数据库。谨慎使用清理目标端选项。配置项
clean_target_before_restore启用后会在恢复前执行DROP SCHEMA ... CASCADE,目标端该 schema 下的所有对象和数据将被永久删除且不可恢复。首次迁移到空实例时可开启,已有业务数据时请务必关闭。迁移管道顺序不可调整。Auth 必须先于 Database 执行,否则业务表对
auth.users的外键约束会导致 Database 恢复失败。Storage 迁移覆盖策略:文件上传使用 upsert 模式,重复迁移会覆盖目标端同名文件;bucket 仅创建不存在的,不会覆盖已有 bucket 属性。
Auth 管道仅迁移数据,不迁移 DDL。因为目标端的 GoTrue 服务已自动初始化 auth schema,重复创建会冲突。
Edge Functions 通过 API 方式部署时需要目标端
agent-runtime服务正常运行。RDS Supabase 默认已启用该服务。RDS 实例间迁移特有注意:源端和目标端 DB 都需要开通公网端点(RDS 控制台操作),并将迁移机 IP 加入白名单。RDS 实例间迁移场景下
clean_target_before_restore建议开启,以避免残留数据冲突。
步骤一:下载源代码并配置迁移参数
先下载迁移工具源代码包获取配置文件模板,然后根据迁移场景选择对应的模板,填入源端和目标端的连接信息及各管道的开关。
下载项目源代码
下载迁移工具源代码包supabase-migration-master-v1.2.zip,并解压到运行迁移工具的机器上。源代码包中包含 Docker Compose 配置文件(docker-compose.yaml)、Dockerfile、配置文件示例(config/default.yaml.example)以及 Python 源代码等,是后续所有部署方式的基础。
配置迁移参数
Cloud 迁移至 RDS 的配置
从示例文件创建配置文件:
cp config/default.yaml.example config/default.yaml编辑 config/default.yaml,完整示例如下:
source:
project_ref: "your-project-ref"
database_url: "postgresql://postgres:YOUR_PASSWORD@db.xxx.supabase.co:5432/postgres"
service_role_key: "eyJ..."
management_api_token: "sbp_..."
api_base: "https://xxx.supabase.co"
target:
project_url: "http://your-rds-supabase/"
database_url: "postgresql://postgres:YOUR_PASSWORD@pgm-xxx.pg.rds.aliyuncs.com:5432/supabase_db"
service_role_key: "eyJ..."
api_base: "http://your-rds-supabase/"
migration:
auth:
enabled: false # Cloud 侧 Auth 数据受限,默认关闭;如需迁移请手动开启
database:
enabled: true
pg_bin_path: "/opt/homebrew/opt/postgresql@17/bin" # 本地部署时填客户端工具目录;Docker 部署可省略
clean_target_before_restore: false # 谨慎开启,会 DROP SCHEMA CASCADE
storage:
enabled: true
edge_functions:
enabled: true
deploy_method: "api" # 推荐 api,RDS Supabase 场景下更可靠RDS 实例间迁移的配置
从示例文件创建配置文件:
cp config/rds-to-rds.example.yaml config/rds-to-rds.yaml编辑 config/rds-to-rds.yaml,关键差异是 management_api_token 和 project_ref 留空,完整示例如下:
source:
project_ref: "" # RDS 留空
database_url: "postgresql://postgres:PASSWORD@source-pgm-xxx:5432/supabase_db"
service_role_key: "eyJ..."
management_api_token: "" # RDS 留空,自动识别为 RDS 模式
api_base: "http://SOURCE_IP/"
target:
database_url: "postgresql://postgres:PASSWORD@target-pgm-xxx:5432/supabase_db"
service_role_key: "eyJ..."
api_base: "http://TARGET_IP/"
migration:
database:
enabled: true
pg_bin_path: "/opt/homebrew/opt/postgresql@17/bin"
schemas: ["public"]
clean_target_before_restore: true # RDS 实例间迁移建议开启
auth:
enabled: true
storage:
enabled: true
edge_functions:
enabled: true
deploy_method: "api"源端类型自动识别:工具根据 management_api_token 是否为空自动判断源端类型。非空时识别为 Supabase Cloud 模式(使用 api.supabase.com Management API);留空时识别为 RDS 模式(使用本地 /functions/v1/manage API)。
如不希望将凭据写入磁盘文件,可通过环境变量覆盖配置项(前缀 MIGRATOR_,双下划线 __ 表示层级):
export MIGRATOR_SOURCE__DATABASE_URL="postgresql://..."
export MIGRATOR_SOURCE__SERVICE_ROLE_KEY="eyJ..."Cloud 源端凭据
参数 | 用途 | 获取方式 |
| 标识源端项目 | Supabase Dashboard URL 中的项目 ID,即 |
| 源端数据库连接串(pg_dump 直连) | Supabase Dashboard > Settings > Database > Connection string (URI)。 |
| 源端 Storage / Auth API 鉴权 | Supabase Dashboard > Settings > API > service_role key。 |
| Edge Functions 管理 | Supabase Dashboard > Account > Access Tokens,以 |
| 源端 REST API 基础地址 | 格式为 |
| 目标端首页地址 | 在 RDS Supabase 项目详情页 > 网络信息 区域获取外网连接地址。 |
| 目标端数据库连接串(pg_restore 直连) | 格式为 |
| 目标端 Storage / Auth / Functions API 鉴权 | 在 RDS Supabase 项目详情页 > API Key 中复制 ServiceKey 的值。详见附录:获取service API key。 |
| 目标端 API 网关地址 | RDS Supabase 内置 Kong 网关地址,通常与 |
RDS 源端凭据
RDS 实例间迁移场景下,源端凭据与 Cloud 源端有以下差异:
参数 | 用途 | 获取方式 |
| 不需要 | 留空。RDS 模式下不需要 project_ref。 |
| pg_dump 直连源端 | 阿里云控制台 > RDS Supabase 详情 > 连接地址(公网端点,库名为 |
| 源端所有 API 调用 | 阿里云控制台 > Supabase 详情 > API Key 中获取 serviceKey。 |
| 不需要 | 留空。留空后自动识别为 RDS 模式。 |
| 源端 API 网关地址 | 阿里云 RDS Supabase 公网 IP,如 |
目标端凭据在 Cloud 迁移至 RDS 和 RDS 实例间迁移两种场景下完全相同,均为 RDS Supabase 的连接信息,参见上表目标端部分。
步骤二:部署迁移工具
完成步骤一的配置后,选择以下任一方式部署迁移工具。推荐使用 Docker 方式部署,镜像内已包含 Python 3.12 和 PostgreSQL 18 客户端(向下兼容 PG 17/15),无需手动安装依赖。
方式一:Docker Compose 部署(推荐)
在运行迁移工具的机器上,准备
supabase-migrator工具目录并进入。从示例文件创建配置文件。
cp config/default.yaml.example config/default.yaml参考步骤一:下载源代码并配置迁移参数编辑
config/default.yaml,填入源端和目标端的连接信息等迁移参数。启动迁移工具容器。
docker compose up -d容器启动后,访问
http://<迁移工具机器IP>:8080即可打开 Web UI。
方式二:Docker run 部署
适用于无 docker-compose 环境的场景。先构建镜像,再根据是否需要将凭据落盘选择启动方式。
构建镜像。
docker build -t supabase-migrator .根据需要选择以下任一方式启动容器。
挂载配置文件
将本地编辑好的
config/default.yaml挂载到容器中,凭据以文件形式管理。docker run --rm -p 8080:8080 \ -v ./config/default.yaml:/app/config/default.yaml:ro \ supabase-migrator纯环境变量
通过环境变量代替配置文件,避免在磁盘上存储敏感凭据。环境变量使用
MIGRATOR_前缀加双下划线__表示层级,例如:docker run --rm -p 8080:8080 \ -e MIGRATOR_SOURCE__PROJECT_REF="your-project-ref" \ -e MIGRATOR_SOURCE__DATABASE_URL="postgresql://postgres:PASSWORD@db.xxx.supabase.co:5432/postgres" \ -e MIGRATOR_SOURCE__SERVICE_ROLE_KEY="eyJ..." \ -e MIGRATOR_SOURCE__MANAGEMENT_API_TOKEN="sbp_..." \ -e MIGRATOR_SOURCE__API_BASE="https://xxx.supabase.co" \ -e MIGRATOR_TARGET__DATABASE_URL="postgresql://postgres:PASSWORD@pgm-xxx.pg.rds.aliyuncs.com:5432/supabase_db" \ -e MIGRATOR_TARGET__SERVICE_ROLE_KEY="eyJ..." \ -e MIGRATOR_TARGET__API_BASE="http://your-rds-supabase/" \ supabase-migratorCLI 迁移(一次性任务)
使用 Docker 运行 CLI 模式执行迁移,适用于 CI/CD 或脚本自动化场景,无需启动 Web UI:
docker run --rm \ -v ./config/default.yaml:/app/config/default.yaml:ro \ supabase-migrator rds-supabase-migrator migrate all -c /app/config/default.yaml
方式三:本地源码部署
适用于希望调试或定制工具逻辑的场景,需自行准备 Python 和 PostgreSQL 客户端。
安装 PostgreSQL 客户端工具(版本 ≥ 17)。以 macOS 为例:
# 安装 PostgreSQL 17 客户端 brew install postgresql@17 # 验证版本 /opt/homebrew/opt/postgresql@17/bin/pg_dump --version说明无需将客户端工具加入系统 PATH,后续在配置文件中通过
pg_bin_path指定目录即可。在工具目录下创建 Python 虚拟环境并安装依赖。
cd supabase-migrator python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt将迁移工具以可编辑模式安装到虚拟环境中,注册
rds-supabase-migrator命令。pip install -e .安装完成后,可通过
--help查看命令帮助,验证是否安装成功。rds-supabase-migrator --help从示例文件创建配置文件。
cp config/default.yaml.example config/default.yaml参考步骤一:下载源代码并配置迁移参数编辑
config/default.yaml,填入源端和目标端的连接信息等迁移参数。启动 Web UI 服务,任选以下一种方式:
推荐:使用
serve子命令(需先完成上一步的pip install -e .)。source .venv/bin/activate rds-supabase-migrator serve --host 127.0.0.1 --port 8080不安装包时的备选方式:直接通过
uvicorn启动。source .venv/bin/activate PYTHONPATH=src python -m uvicorn supabase_migrator.main:app --host 127.0.0.1 --port 8080
启动成功后,浏览器访问
http://127.0.0.1:8080打开 Web UI。
步骤三:执行迁移
根据部署方式选择执行模式:
方式一:CLI模式
验证连通性。在部署目录下执行验证命令,检查迁移工具是否能正常访问源端和目标端:
rds-supabase-migrator validate -c config/default.yaml说明如验证失败,请检查:迁移工具出口 IP 是否已加入所有相关白名单、连接串中数据库名是否正确(目标端应为
supabase_db)、service_role_key 是否完整复制。执行迁移。根据需要选择迁移方式:
全量迁移:按 Auth、Database、Storage、Edge Functions 顺序执行所有已启用的管道。
rds-supabase-migrator migrate all -c config/default.yaml单管道迁移:仅执行指定管道,适用于补迁、重试或分阶段迁移。
# 仅迁移数据库 rds-supabase-migrator migrate database -c config/default.yaml # 仅迁移 Storage rds-supabase-migrator migrate storage -c config/default.yaml试运行(Dry Run):检查配置和连通性,不实际执行迁移操作。
rds-supabase-migrator migrate all -c config/default.yaml --dry-run
重要CLI模式下迁移日志直接输出到终端。如需后台运行,可结合
nohup或tee使用。中断后可重新执行,工具每次执行后自动清理临时文件。
方式二:Web UI模式
在浏览器中访问迁移工具的 Web UI 地址(本地部署为
http://127.0.0.1:8080,Docker 部署为http://<迁移工具机器IP>:8080)。在配置页面中,确认已填入步骤一的源端、目标端参数,单击测试连接,验证迁移工具是否能正常访问源端和目标端。
说明如测试失败,请检查:迁移工具出口 IP 是否已加入所有相关白名单、连接串中数据库名是否正确(目标端应为
supabase_db)、service_role_key 是否完整复制。切换到迁移页面,根据需要选择迁移方式:
开始全量迁移:按 Auth、Database、Storage、Edge Functions 顺序执行所有已启用的管道,适用于完整迁移场景。
仅迁移 XXX:仅执行单个管道,适用于补迁、重试或分阶段迁移场景。
切换到日志页面,实时查看迁移进度、当前管道执行状态以及错误信息。
重要迁移过程中请勿关闭浏览器窗口或停止迁移工具进程,否则会中断迁移。中断后可重新执行,工具使用临时目录存放中间文件,每次执行后自动清理,不会污染下一次执行。
验证迁移结果
迁移完成后,建议从以下几个维度逐一验证目标端 RDS Supabase 的数据完整性:
验证 Auth 数据:登录 RDS Supabase Dashboard,进入 Authentication > Users,对比用户总数是否与源端一致。
验证业务数据:连接目标端
supabase_db,分别在源端和目标端执行以下 SQL 对比业务表数量和关键表的行数。-- 表总数 SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'; -- 关键表行数(替换为您的实际表名) SELECT count(*) FROM public.your_table;验证 Storage 文件:在 RDS Supabase Dashboard 进入 Storage,确认 bucket 列表完整,并随机抽查若干 bucket 下的文件能正常预览或下载。
验证 Edge Functions:进入 Edge Functions 列表,确认函数已成功部署,通过
curl或 Dashboard 内的测试按钮调用函数验证返回结果是否正常。
CLI 命令参考
CLI模式下的命令结构如下:
rds-supabase-migrator <command> [pipeline] [options]
支持的命令:
validate:验证配置和连通性,不执行迁移。migrate:执行迁移,需指定管道。serve:启动 Web UI 服务。示例:rds-supabase-migrator serve --host 127.0.0.1 --port 8080。
migrate 命令支持的管道:
all:全量迁移(依次执行 Auth、Database、Storage、Edge Functions)。auth:仅迁移用户认证数据。database:仅迁移业务数据库。storage:仅迁移 Storage 文件。edge-functions:仅部署 Edge Functions。
通用参数:
参数 | 必填 | 说明 |
| 是 | 配置文件路径,如 |
| 否 | 覆盖配置文件中的源端数据库连接串( |
| 否 | 覆盖配置文件中的目标端数据库连接串( |
| 否 | 覆盖源端 |
| 否 | 覆盖目标端 |
| 否 | 试运行模式,仅检查配置和连通性,不实际执行迁移。 |
| 否 | 显示 debug 级别日志,便于排查连接、认证等问题。 |
| 否 | 仅 migrate storage 时有效。指定待迁移的 object 清单(逗号分隔),如 |
| 否 | 仅 migrate storage 时有效。从文件读取 object 清单(每行一个 |
退出码:
退出码 | 含义 |
| 迁移成功。 |
| 配置错误或连接失败。 |
| 迁移过程中部分管道失败。 |
| 迁移被用户中断(收到 SIGINT,例如按下 Ctrl+C)。 |
API 接口
Web UI 模式启动后(默认监听 http://127.0.0.1:8080),迁移工具同时对外暴露以下 HTTP 接口,可用于二次集成或自动化脚本调用:
方法 | 路径 | 说明 |
GET |
| 获取当前配置(密钥字段自动脱敏)。 |
PUT |
| 更新配置。 |
POST |
| 测试源端和目标端连通性。 |
POST |
| 全量迁移,按顺序执行所有已启用管道。 |
POST |
| 仅迁移 Auth 用户数据。 |
POST |
| 仅迁移数据库。 |
POST |
| 仅迁移 Storage 文件。 |
POST |
| 仅部署 Edge Functions。 |
POST |
| 取消正在执行的迁移任务。 |
GET |
| 查询迁移状态和进度。 |
GET |
| 通过 SSE(Server-Sent Events)推送实时日志流。 |
常见问题
Q:迁移失败后可以重试吗?
A:可以。每次迁移使用独立的临时目录(结束后自动清理),不会影响下一次执行。直接在 Web UI 重新点击开始全量迁移即可。Q:Storage 迁移时目标端已有相同文件怎么处理?
A:文件上传使用 upsert 模式,重复迁移会覆盖目标端同名文件;bucket 仅创建不存在的,不会覆盖已有 bucket 属性。Q:Database 迁移报错
pg_dump version mismatch怎么办?
A:pg_dump客户端版本必须不低于源端和目标端中的更高版本。在配置中将pg_bin_path指向更高版本的 PostgreSQL 客户端工具目录即可。Q:Edge Functions 部署失败怎么办?
A:使用 API 方式部署时,确认目标端的edge-runtime(agent-runtime)服务正常运行,并且配置项target.api_base设置正确。Q:可以只迁移其中一个管道吗?
A:可以。在 Web UI 的迁移页面点击对应的仅迁移 XXX按钮,或通过 API 调用/api/migrate/auth、/api/migrate/database等单独端点。Q:Docker 容器中如何查看日志?
A:两种方式:在 Web UI 的日志页面实时查看。
在迁移工具机器上执行
docker logs -f migrator查看容器标准输出。
Q:CLI模式下如何查看迁移日志?
A:CLI模式下日志直接输出到终端。如需保存日志文件,可使用重定向:rds-supabase-migrator migrate all -c config/default.yaml 2>&1 | tee migrate.log。Q:RDS 实例间迁移和 Cloud 迁移至 RDS 有什么区别?
A:主要区别:(1) 源端management_api_token和project_ref留空,工具自动识别为 RDS 模式;(2) 源端 DB 需开通公网端点并配置白名单;(3) 建议开启clean_target_before_restore避免残留数据冲突。