^# VPS 自动备份方案 — rsnapshot + rclone + OneDrive

适用环境:Ubuntu 24.04 LTS / Oracle Cloud ARM VPS
备份目标:所有服务配置、账号数据、数据库、SSL 证书
远程存储:OneDrive(可通过 rclone 扩展其他网盘)


一、安装依赖

1
2
3
4
5
# 安装 rsnapshot
apt update && apt install -y rsnapshot

# 安装 rclone
curl -s https://rclone.org/install.sh | bash

二、配置 rclone(OneDrive 授权)

由于 VPS 没有浏览器,需要在有浏览器的本地电脑上获取 token。

在本地电脑上操作

1
2
# 安装 rclone 后执行(macOS: brew install rclone)
rclone authorize "onedrive"

浏览器弹出 Microsoft 登录页面,授权后会输出一段 JSON token。

在 VPS 上配置

创建配置文件 ~/.config/rclone/rclone.conf

1
2
3
4
5
[onedrive]
type = onedrive
token = {"access_token":"...","token_type":"Bearer","refresh_token":"...","expiry":"..."}
drive_id = 你的drive_id
drive_type = personal

获取 drive_id:授权后用 access_token 调用 API:

返回的 id 字段即为 drive_id。

1
2
curl -s -H "Authorization: Bearer 你的access_token" \
"https://graph.microsoft.com/v1.0/me/drive" | python3 -m json.tool

验证连接

1
rclone lsd onedrive:

能列出 OneDrive 根目录即配置成功。


三、配置 rsnapshot

3.1 主配置文件

/etc/rsnapshot.conf(注意:必须用 Tab 分隔,不能用空格)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#################################################
# rsnapshot.conf
# 注意:每行参数之间必须用 Tab 分隔
#################################################

config_version 1.2

# 备份根目录
snapshot_root /backup/
no_create_root 0

# 外部程序
cmd_cp /bin/cp
cmd_rm /bin/rm
cmd_rsync /usr/bin/rsync
cmd_logger /usr/bin/logger

# 保留策略:7天日备、4周周备、3月月备
retain daily 7
retain weekly 4
retain monthly 3

# 日志
verbose 2
loglevel 3
logfile /var/log/rsnapshot.log
lockfile /var/run/rsnapshot.pid

# 高级选项
link_dest 1
use_lazy_deletes 1

# 备份后自动压缩上传 OneDrive
cmd_postexec /bin/bash /backup/post-backup.sh

###############################
### 备份项 ###
###############################

# 1. 导出 sub2api PostgreSQL
backup_exec /bin/bash /backup/pre-backup.sh

# 2. 数据库导出文件
backup /backup/dump/ localhost/dump/

# 3. Nginx 配置
backup /etc/nginx/ localhost/nginx/

# 4. SSL 证书
backup /etc/letsencrypt/ localhost/letsencrypt/

# 5. CPA (cliproxyapi) 配置
backup /root/cliproxyapi/config.yaml localhost/cliproxyapi/
backup /root/cliproxyapi/cliproxyapi.service localhost/cliproxyapi/
backup /root/cliproxyapi/config_backup/ localhost/cliproxyapi/config_backup/
backup /root/cliproxyapi/static/ localhost/cliproxyapi/static/

# 6. CPA2 (cliproxyapi2) 配置
backup /root/cliproxyapi2/config.yaml localhost/cliproxyapi2/
backup /root/cliproxyapi2/static/ localhost/cliproxyapi2/

# 7. CPA 账号池数据 (~90 个 codex 账号)
backup /root/.cli-proxy-api/ localhost/dot-cli-proxy-api/

# 8. CPA2 账号池数据 (~90 个 codex 账号)
backup /root/.cli-proxy-api2/ localhost/dot-cli-proxy-api2/

# 9. Sub2API 配置
backup /root/sub2api/deploy/.env localhost/sub2api/
backup /root/sub2api/deploy/docker-compose.local.yml localhost/sub2api/
backup /root/sub2api/deploy/docker-compose.yml localhost/sub2api/
backup /root/sub2api/deploy/sub2api.service localhost/sub2api/
backup /root/sub2api/deploy/data/ localhost/sub2api/data/

# 10. Grok2API 配置与数据 (598 个 Grok 账号)
backup /root/grok2api/config.defaults.toml localhost/grok2api/
backup /root/grok2api/docker-compose.yml localhost/grok2api/
backup /root/grok2api/data/ localhost/grok2api/data/

# 11. 1Panel 配置
backup /opt/1panel/db/ localhost/1panel/db/
backup /opt/1panel/apps/ localhost/1panel/apps/

# 12. Systemd 服务文件
backup /etc/systemd/system/cliproxyapi.service localhost/systemd/
backup /etc/systemd/system/cliproxyapi-8318.service localhost/systemd/
backup /etc/systemd/system/sub2api.service localhost/systemd/
backup /etc/systemd/system/1panel-core.service localhost/systemd/
backup /etc/systemd/system/1panel-agent.service localhost/systemd/

# 13. SSH 密钥
backup /root/.ssh/ localhost/dot-ssh/

# 14. Docker Compose 文件
backup /opt/rsshub/compose.yml localhost/rsshub/
backup /opt/1panel/apps/chatgpt-next-web/chatgpt-next-web/docker-compose.yml localhost/chatgpt-next-web/

# 15. 服务恢复清单
backup /backup/SERVICES_RECOVERY.md localhost/

3.2 验证配置

1
2
rsnapshot configtest
# 输出 Syntax OK 即正确

四、备份脚本

4.1 备份前脚本:导出数据库

/backup/pre-backup.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
# 导出 sub2api PostgreSQL 数据库

DUMP_DIR="/backup/dump"
mkdir -p "$DUMP_DIR"

echo "[$(date)] Starting pre-backup tasks..."

# 导出为 custom 格式(可用于 pg_restore)
docker exec sub2api-postgres pg_dump -U ahao430 -d sub2api \
--format=custom -f /tmp/sub2api.dump 2>/dev/null
docker cp sub2api-postgres:/tmp/sub2api.dump "$DUMP_DIR/sub2api.dump" 2>/dev/null
docker exec sub2api-postgres rm -f /tmp/sub2api.dump 2>/dev/null

if [ -f "$DUMP_DIR/sub2api.dump" ]; then
SIZE=$(du -sh "$DUMP_DIR/sub2api.dump" | cut -f1)
echo " sub2api dump: $SIZE"
else
echo " WARNING: sub2api PostgreSQL dump failed!"
fi

# 同时导出为 SQL 明文(便于阅读和手动恢复)
docker exec sub2api-postgres pg_dump -U ahao430 -d sub2api \
--format=plain 2>/dev/null > "$DUMP_DIR/sub2api.sql"

echo "[$(date)] Pre-backup tasks completed."
1
chmod +x /backup/pre-backup.sh

4.2 备份后脚本:压缩 + 上传 OneDrive

/backup/post-backup.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/bash
# 压缩最新备份并上传到 OneDrive,清理过期远程备份

set -e

DATE=$(date +%Y%m%d)
HOSTNAME=$(hostname)
ARCHIVE_NAME="backup_${HOSTNAME}_${DATE}.tar.gz"
ARCHIVE_PATH="/tmp/${ARCHIVE_NAME}"
ONEDRIVE_PATH="onedrive:VPS-Backup"

echo "[$(date)] Post-backup: compressing /backup/daily.0 ..."

# 压缩最新日备快照
tar czf "$ARCHIVE_PATH" -C /backup daily.0 2>/dev/null

SIZE=$(du -sh "$ARCHIVE_PATH" | cut -f1)
echo "[$(date)] Post-backup: archive created ${ARCHIVE_NAME} (${SIZE})"

# 上传到 OneDrive
echo "[$(date)] Post-backup: uploading to OneDrive ..."
rclone copy "$ARCHIVE_PATH" "$ONEDRIVE_PATH/" --log-level INFO

if [ $? -eq 0 ]; then
echo "[$(date)] Post-backup: upload to OneDrive succeeded."
else
echo "[$(date)] Post-backup: WARNING - OneDrive upload failed!"
fi

# 清理 OneDrive 上超过 7 天的旧备份
echo "[$(date)] Post-backup: cleaning old remote backups (keeping 7 days) ..."
rclone delete "$ONEDRIVE_PATH/" --min-age 7d --log-level INFO 2>/dev/null || true

# 删除本地临时压缩包
rm -f "$ARCHIVE_PATH"
echo "[$(date)] Post-backup: done."
1
chmod +x /backup/post-backup.sh

五、定时任务

1
2
3
4
5
# 编辑 crontab
crontab -e

# 添加以下内容(每天凌晨 4 点执行)
0 4 * * * /usr/bin/rsnapshot daily >> /var/log/rsnapshot.log 2>&1

六、执行流程

1
2
3
4
5
6
7
8
9
10
11
12
13
rsnapshot daily(一条命令完成全部流程)

├─ 1. backup_exec → pre-backup.sh
│ pg_dump 导出 sub2api PostgreSQL

├─ 2. 旋转快照 → daily.0 → daily.1 → daily.2 → ... (保留7天)

├─ 3. rsync 同步 → 将所有备份项同步到 /backup/daily.0/

└─ 4. cmd_postexec → post-backup.sh
tar 压缩 /backup/daily.0
rclone 上传到 OneDrive:VPS-Backup/
清理 OneDrive 上 7 天前的旧文件

七、手动操作

立即执行一次完整备份

1
rsnapshot daily

查看备份日志

1
tail -50 /var/log/rsnapshot.log

查看 OneDrive 上的备份

1
rclone ls onedrive:VPS-Backup/

查看本地备份目录

1
ls -la /backup/daily.0/localhost/

验证 rsnapshot 配置

1
rsnapshot configtest

八、备份内容清单

目录 说明 大小
localhost/nginx/ Nginx 反代配置 140K
localhost/letsencrypt/ SSL 证书 124K
localhost/cliproxyapi/ CPA 配置 (端口 8317) 2.1M
localhost/cliproxyapi2/ CPA2 配置 (端口 8318) 2.1M
localhost/dot-cli-proxy-api/ CPA 账号池 (~90 个 codex 账号) 1.4M
localhost/dot-cli-proxy-api2/ CPA2 账号池 (~90 个 codex 账号) 5.9M
localhost/sub2api/ Sub2API 配置 + .env + docker-compose 48M
localhost/grok2api/ Grok2API 配置 + token.json (598 个账号) 880K
localhost/dump/ PostgreSQL 导出 (sub2api.dump + sub2api.sql) 56M
localhost/1panel/ 1Panel 数据库和 apps 配置 40M
localhost/systemd/ 所有自定义 service 文件 36K
localhost/dot-ssh/ SSH 密钥 28K
localhost/rsshub/ RSSHub compose 文件 16K
localhost/chatgpt-next-web/ ChatGPT-Next-Web compose 28K
localhost/SERVICES_RECOVERY.md 服务恢复清单 自包含

总计约 156M,压缩后约 18M。


九、恢复方法

从 OneDrive 下载并解压

1
2
3
4
5
6
7
8
9
# 下载最新备份
rclone copy onedrive:VPS-Backup/backup_主机名_日期.tar.gz /tmp/

# 解压到临时目录
mkdir -p /tmp/restore
tar xzf /tmp/backup_*.tar.gz -C /tmp/restore

# 查看内容
ls /tmp/restore/daily.0/localhost/

恢复数据库

1
2
3
4
5
6
7
# 从 custom 格式恢复
docker exec -i sub2api-postgres pg_restore -U ahao430 -d sub2api \
< /tmp/restore/daily.0/localhost/dump/sub2api.dump

# 或从 SQL 明文恢复
docker exec -i sub2api-postgres psql -U ahao430 -d sub2api \
< /tmp/restore/daily.0/localhost/dump/sub2api.sql

恢复配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Nginx
cp -r /tmp/restore/daily.0/localhost/nginx/* /etc/nginx/
nginx -t && systemctl reload nginx

# CPA 配置
cp /tmp/restore/daily.0/localhost/cliproxyapi/config.yaml /root/cliproxyapi/
systemctl restart cliproxyapi

# CPA2 配置
cp /tmp/restore/daily.0/localhost/cliproxyapi2/config.yaml /root/cliproxyapi2/
systemctl restart cliproxyapi-8318

# 账号池数据
cp -r /tmp/restore/daily.0/localhost/dot-cli-proxy-api/* /root/.cli-proxy-api/
cp -r /tmp/restore/daily.0/localhost/dot-cli-proxy-api2/* /root/.cli-proxy-api2/

# SSH 密钥
cp -r /tmp/restore/daily.0/localhost/dot-ssh/* /root/.ssh/
chmod 600 /root/.ssh/id_ed25519_1panel

# Systemd 服务
cp /tmp/restore/daily.0/localhost/systemd/* /etc/systemd/system/
systemctl daemon-reload

十、相关文件路径

文件 作用
/etc/rsnapshot.conf rsnapshot 主配置(备份源列表)
/backup/pre-backup.sh 备份前脚本:导出 PostgreSQL
/backup/post-backup.sh 备份后脚本:压缩 + 上传 OneDrive
/backup/SERVICES_RECOVERY.md 服务恢复清单
/root/.config/rclone/rclone.conf rclone 网盘认证配置
/var/log/rsnapshot.log 备份日志