Sub2API 从脚本安装迁移到 Docker Compose 部署流程

本文档记录一次实际走通的 Sub2API 迁移流程:旧服务器使用官方脚本安装,配置和程序位于 /opt/sub2api;新服务器使用官方 docker-compose.local.yml 部署,并从 PostgreSQL 备份恢复业务数据。

适用场景

  • 旧服务器:官方安装脚本部署,主配置文件在 /opt/sub2api/config.yaml
  • 新服务器:使用 Docker Compose 部署。
  • 备份方式:Sub2API 后台“数据备份”已将 PostgreSQL 备份上传到 S3/R2,文件形如 sub2api_20260528_152845.sql.gz
  • Redis:只作为缓存和锁使用,通常不迁移旧 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: "<Redis密码>"
    db: 9
    enable_tls: false

如果旧配置里没有固定的 totp.encryption_key,建议现在补上,避免每次重启生成随机密钥:

openssl rand -hex 32

把输出填入 config.yaml,与 jwt: 同级:

totp:
    encryption_key: "<64位hex密钥>"

注意:如果旧实例之前没有固定 totp.encryption_key,数据库里已经加密保存的部分 secret 无法在新实例自动解密,需要迁移完成后重新录入。例如:

  • 系统设置里的 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密码>'
REDIS_DB=9

JWT_SECRET=<旧配置里的 jwt.secret>
TOTP_ENCRYPTION_KEY=<config.yaml 里的 totp.encryption_key>

如果 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-postgressub2api-redis 都是 Healthy

八、导入 PostgreSQL 备份

用 R2/S3 下载下来的备份文件恢复数据库:

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.yaml
  • config.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,保存并测试连接即可。

这里分享一下个人搭建的中转站 https://hahacode.com

十一、常见问题

1. pg_dump version 报错

看版本应使用:

pg_dump --version

pg_dump version 会被当成数据库名,可能触发连接错误。

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 备份,备份记录就会恢复。

这里分享一下个人搭建的中转站https://hahacode.com

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐