用 Restic 和 SFTP 做 VPS 异地备份

用 Restic 把数据库导出、配置和附件加密存到另一台 SFTP 服务器,保留快照,再恢复到独立目录检查。

数据库导出和上传文件还在原 VPS 上,重装或丢失整机时,备份也可能一起没了。Restic 可以把文件加密存到另一处 SFTP 仓库,并保存多个时间点;之后还要试一次恢复。

备份哪些目录,数据库怎样保存

给一个 Docker 网站做备份,至少要检查应用配置、环境文件、上传目录和数据库导出。Compose 文件记录了怎么启动服务,却不包含数据卷里的内容。数据库正在写入时,不宜直接把数据目录当成普通文件打包;应先用数据库支持的方式取得一致的备份。

备份机器也要独立于原机。已有另一台服务器并有足够空间,可以先使用它;准备新增存储时,按备份数据量、历史保留和恢复下载量比较存储型 VPS 的容量与费用。不要只看首月磁盘大小:源文件、多个历史版本以及增长空间都需要预算。

购买 SFTP 仓库机器,容量先覆盖完整快照、保留版本和恢复下载空间,地区或平台与源机分开。可比较 雨云 RCS 的异地磁盘与网络,或查看 ECS 的数据盘组合;CPU 不必照业务机规格购买,但月流量与下载费用要算进成本。先上传一份真实备份,检查完整性,再从独立环境恢复,再确定长期保留策略。

先用备份账号连接 SFTP

以下示例适用于已安装 Restic、OpenSSH 客户端的 Linux。由运行定时任务的同一个系统账号配置 SSH 密钥和 backupbox 主机别名,并事先核对远端主机指纹。先执行:

sftp -b - backupbox <<'SFTP'
ls /srv/restic/site-a
quit
SFTP

远端目录需要预先创建并授予备份账号写权限。列目录成功不代表能写入,初始化仓库时还要验证写权限。命令失败时先处理密钥、路径或权限;定时任务不能依赖有人输入登录密码。

为该账号创建 /etc/restic/site-a.env,内容如下。密码文件里存仓库密码,和 SSH 私钥是两份不同的凭据。

RESTIC_REPOSITORY=sftp:backupbox:/srv/restic/site-a
RESTIC_PASSWORD_FILE=/etc/restic/site-a.password

将环境文件和密码文件的访问权限限制为执行账号可读。仓库密码还要独立保存一份;忘记它以后,拿到仓库文件也无法解密恢复。

初始化仓库,再备份文件

在 Bash 中加载环境,再初始化一个新的空仓库。已有仓库不用重复初始化。

set -a
. /etc/restic/site-a.env
set +a
restic init

确认 /srv/site-a/db-dumps 中是这次成功完成的数据库导出,而不是上次遗留的文件。下面的路径只是备份清单示例,换成实际目录后执行:

restic backup /srv/site-a/config /srv/site-a/uploads /srv/site-a/db-dumps \
  --host vps-site-a --tag site-a
restic snapshots --host vps-site-a

先手动完成一次,再放入定时任务。任务要先检查数据库导出的退出码,成功后才运行 Restic;导出失败应报警,不能继续拿旧文件生成一个看似正常的新快照。Restic 备份退出码 3 表示部分源数据无法读取,也应当作需要处理的失败。

恢复到空目录检查

从快照列表选定 ID,替换下面的 SNAPSHOT_ID。不要把恢复目标直接指向仍在运行的网站。

restic check
restic restore SNAPSHOT_ID --target /srv/restore-check/site-a

恢复后的路径保留原备份目录结构。检查配置能否读取、随机打开几张上传图片,再把数据库导出还原到独立测试库,验证登录和一条实际记录。restic check 的默认检查不能代替这一步;需要读取仓库数据本身时,可按官方文档安排 check --read-data,同时考虑下载量和耗时。

记录这次恢复使用的快照 ID、应用版本和数据库版本。等恢复流程确实走通,再决定保留周期和旧快照清理方案;仅看到快照列表,不足以证明网站可以恢复。