Sub2API 从脚本安装迁移到 Docker Compose 部署流程
Sub2API 从脚本安装迁移到 Docker Compose 部署流程
这篇文章记录了一次实打实的 Sub2API 迁移过程,从旧服务器的脚本安装环境,完整搬迁到新服务器的 Docker Compose 部署方式。整个流程走下来,核心思路其实很清晰:把配置和数据打包带走,在新的容器环境里重新组装。
旧服务器是用官方脚本装的,配置文件和程序都老老实实待在 /opt/sub2api。新服务器这边,则用官方提供的 docker-compose.local.yml 来部署,数据库从 PostgreSQL 备份里恢复。整个过程不复杂,但细节需要格外留意。

适用场景
在开始之前,先确认一下这套方案适用的环境:
- 旧服务器用的是官方安装脚本,主配置文件在
/opt/sub2api/config.yaml。 - 新服务器准备用 Docker Compose 来部署。
- 备份方式比较标准——Sub2API 后台的“数据备份”功能已经将 PostgreSQL 备份上传到 S3/R2,文件命名格式类似
sub2api_20260528_152845.sql.gz。 - Redis 这边,只作为缓存和锁使用,通常不需要迁移旧数据。
一、旧服务器打包
在旧服务器上,需要先把手头的东西收一收:
cd /opt/sub2api
# 备份主配置文件
cp config.yaml /root/sub2api-config.yaml
# 备份应用本地数据目录
tar czf /root/sub2api-data.tar.gz data
接下来,确认旧配置里的数据库、Redis、JWT 这些关键信息:
grep -nA 20 '^database:' /opt/sub2api/config.yaml
grep -nA 20 '^redis:' /opt/sub2api/config.yaml
grep -nE 'secret|password|client_secret|encryption_key' /opt/sub2api/config.yaml
需要带到新服务器的文件清单:
/root/sub2api-config.yaml
/root/sub2api-data.tar.gz
R2/S3 下载下来的 sub2api_YYYYMMDD_HHMMSS.sql.gz
如果不用 R2/S3 备份,也可以选择在旧服务器手动导出 PostgreSQL:
PGPASSWORD='<旧库密码>' pg_dump -h localhost -p 5432 -U sub2api -d sub2api --no-owner --no-acl -f /root/sub2api.sql
gzip -f /root/sub2api.sql
二、把文件放到新服务器 /opt
把准备好的文件上传到新服务器的 /opt 目录下:
/opt/sub2api-config.yaml
/opt/sub2api-data.tar.gz
/opt/sub2api_YYYYMMDD_HHMMSS.sql.gz
可以这样操作:
scp /root/sub2api-config.yaml root@<新服务器IP>:/opt/sub2api-config.yaml
scp /root/sub2api-data.tar.gz root@<新服务器IP>:/opt/sub2api-data.tar.gz
scp sub2api_YYYYMMDD_HHMMSS.sql.gz root@<新服务器IP>:/opt/
三、新服务器准备 Docker Compose
在新服务器上开始搭建:
cd /opt
git clone https://github.com/Wei-Shaw/sub2api.git
cd /opt/sub2api/deploy
cp .env.example .env
mkdir -p data postgres_data redis_data
解压旧服务器的本地数据目录:
tar xzf /opt/sub2api-data.tar.gz -C /opt/sub2api/deploy
然后把旧的配置文件放进去:
cp /opt/sub2api-config.yaml /opt/sub2api/deploy/config.yaml
四、修改 config.yaml
这一步比较关键,需要编辑新服务器上的配置:
vi /opt/sub2api/deploy/config.yaml
核心改动是:把旧服务器上的本地地址,改成 Docker Compose 环境里的内部服务名:
database:
host: postgres
port: 5432
user: sub2api
password: "<旧数据库密码>"
dbname: sub2api
sslmode: disable
redis:
host: redis
port: 6379
password: "
如果旧配置里没有设置固定的 totp.encryption_key,强烈建议现在补上,否则每次重启都会生成一个随机密钥:
openssl rand -hex 32
把生成的密钥填入 config.yaml,与 jwt: 同级:
totp:
encryption_key: "<64位hex密钥>"
这里有一个很容易踩的坑:如果旧实例之前没有固定的 totp.encryption_key,那么数据库里已经加密保存的部分敏感信息,在新实例里是无法自动解密的。具体受影响的内容包括:
- 系统设置里的 S3/R2
Secret Access Key - Channel Monitor 里的 API Key
- 已开启 2FA 的用户,需要重新绑定或由管理员关闭后再启用
五、修改 docker-compose.local.yml
编辑这个文件:
vi /opt/sub2api/deploy/docker-compose.local.yml
需要确保 sub2api 服务的 volumes 部分包含这两行挂载:
volumes:
- ./data:/app/data
- ./config.yaml:/app/data/config.yaml
六、修改 .env
编辑环境变量文件:
vi /opt/sub2api/deploy/.env
至少确保以下值与 config.yaml 保持一致:
POSTGRES_USER=sub2api
POSTGRES_PASSWORD=<旧数据库密码>
POSTGRES_DB=sub2api
REDIS_PASSWORD='
一个小技巧:如果 Redis 密码里包含 >、^、! 这类特殊字符,建议在 .env 里用单引号包起来,避免解析出错。
七、启动 PostgreSQL 和 Redis
先只启动数据库和 Redis,确认基础组件没问题:
cd /opt/sub2api/deploy
docker compose -f docker-compose.local.yml up -d postgres redis
docker compose -f docker-compose.local.yml ps
等待几秒钟,确认 sub2api-postgres 和 sub2api-redis 的状态都显示为 Healthy,再往下走。
八、导入 PostgreSQL 备份
现在,把之前下载或导出的备份文件恢复到数据库里:
gunzip -c /opt/sub2api_YYYYMMDD_HHMMSS.sql.gz | docker compose -f /opt/sub2api/deploy/docker-compose.local.yml exec -T postgres psql -U sub2api -d sub2api
如果 .env 文件里配置的数据库用户名或库名不是 sub2api,记得把命令里的 -U 和 -d 参数同步换成实际的值。
九、启动 Sub2API
数据库恢复完成后,就可以启动主服务了:
docker compose -f /opt/sub2api/deploy/docker-compose.local.yml up -d sub2api
docker compose -f /opt/sub2api/deploy/docker-compose.local.yml logs -f sub2api
正常情况下,日志里应该能看到类似这样的信息:
[Backup] 定时备份已启用: 0 2 * * *
如果日志里出现了下面这条:
TOTP encryption key auto-generated
这说明你配置的固定 totp.encryption_key 没有被正确加载。这个时候需要逐一排查:
/opt/sub2api/deploy/config.yaml是否正确挂载到了容器内的/app/data/config.yamlconfig.yaml文件中是否确实有totp.encryption_key这个字段.env文件里是否也填了对应的TOTP_ENCRYPTION_KEY
十、迁移后检查
服务启动后,别急着关终端,先做一轮基本检查:
docker compose -f /opt/sub2api/deploy/docker-compose.local.yml ps
docker compose -f /opt/sub2api/deploy/docker-compose.local.yml logs --tail=200 sub2api
然后进后台确认几件事:
- 管理员账号能否正常登录
- 用户、渠道、账号、订阅这些数据是否都在
- 系统设置是否恢复到了迁移前的状态
- 数据备份的配置有没有恢复
- R2/S3 备份是否能测试连接成功
- Channel Monitor 的日志里有没有解密失败的错误
- 如果之前用了 2FA,确认一下用户能不能正常登录
如果遇到 R2/S3 连接测试失败的情况,大概率是因为旧数据库里保存的 Secret Access Key 因为旧加密密钥缺失而无法解密。解决方案很简单:进入后台「系统设置 -> 数据备份」,重新填一遍 Secret Access Key,保存后再次测试连接即可。
十一、常见问题
1. pg_dump version 报错
这个其实是个小乌龙。正确的查看版本命令是 pg_dump --version,pg_dump version 会被 PostgreSQL 当作数据库名处理,进而触发连接错误。
2. 迁移后日志提示 channel_monitor: decrypt api key failed
这说明旧库中保存的 Channel Monitor API Key 无法用当前密钥解密。进入后台,重新填写对应监控项的 API Key 就行。
3. 迁移后日志提示 payment encryption/signing key is not explicitly configured
配置好固定的 totp.encryption_key,然后重启服务即可解决。
4. Redis 数据要不要迁移
通常不需要。Sub2API 的核心业务数据都在 PostgreSQL 里,Redis 只是用来做缓存、锁和临时状态存储。新服务器直接用新 Redis,干净利落。
5. R2 桶里有文件但后台看不到
这是一个常见误区。Sub2API 的备份列表并不是去扫描 R2/S3 桶里的文件,而是读取 PostgreSQL 数据库里 settings.key = 'backup_records' 这条记录。只要导入的是完整的 PostgreSQL 备份,备份记录就能正常恢复。