技术指南

Restic 异地备份:从首次快照到恢复演练

用 Restic 建立加密异地快照,从仓库初始化、R2 凭据隔离到完整检查与恢复演练。

Restic 能把文件加密、去重后保存为可追溯快照,但“命令返回成功”不等于数据已经可恢复。先定义允许丢失多少数据、恢复必须多快完成,再用一次本地仓库走通初始化、备份、检查和隔离恢复;确认流程后,才把同一方法接到 Cloudflare R2 等异地对象存储。

先写清恢复目标

对象一致性方法需要记录的结果
静态文件与配置直接纳入快照;排除可重建缓存快照 ID、文件数、校验抽查
MySQL / PostgreSQL先用数据库官方工具生成逻辑或物理备份导出退出码、版本、隔离导入结果
正在写入的应用目录应用快照、维护窗口或官方备份接口写入暂停点、恢复顺序、验收查询
密钥与仓库密码与仓库分开保管的受控副本保管人、轮换日、取回演练

3-2-1 可以用来检查故障域,但不是完成证明:生产数据、本机仓库和同一账号下的对象存储可能仍被一组凭据同时删除。VPScope 的判断是,恢复时间、删除权限和凭据隔离比机械地数副本更重要。

安装后先确认版本

优先使用发行版受支持的软件包。若业务需要上游新版本,应从 Restic 官方发布页下载与架构匹配的文件,并按同一发布提供的校验清单核对;不要使用未固定版本、未校验的“latest”下载链接。当前官方稳定文档为 0.19.1,实际执行仍以 `restic version` 的输出为准。

记录客户端版本;仓库格式和可用参数取决于实际安装版本
sudo apt update
sudo apt install restic
restic version

先用本地仓库走通闭环

下面把测试输入、仓库位置和秘密文件分开。`/srv/backup-input` 只放已经达到应用一致性的输入,例如数据库导出和静态文件;不要把正在写入的数据库数据目录直接当成一致备份。生成密码后,先将其保存到独立的密码管理或受控密钥库,再初始化仓库。

初始化前先独立保管仓库密码;init 只执行一次
sudo install -d -m 0750 /srv/backup-input /srv/restic-repo
sudo install -d -m 0700 /etc/restic
sudo sh -c 'umask 077; openssl rand -base64 32 > /etc/restic/repository-password'
printf '%s\n' /srv/restic-repo | sudo tee /etc/restic/repository >/dev/null
sudo chmod 0600 /etc/restic/repository /etc/restic/repository-password

sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password init
首次手动快照;检查退出码、路径、标签和快照 ID
sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password \
  backup /srv/backup-input --tag manual --exclude='*.tmp'

sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password snapshots

再切换到 R2 异地仓库

Cloudflare 官方文档给出的 S3 端点是 `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`。新建私有 bucket,并创建只限该 bucket 的 Object Read & Write 令牌;Secret Access Key 只显示一次。Restic 的维护和 prune 需要读写及删除对象,因此不能把令牌缩成只读。若删除权限与生产主机放在一起,异地并不等于防删除。

/etc/restic/r2.env;用受控编辑器填写,权限设为 0600
AWS_ACCESS_KEY_ID=REPLACE_WITH_BUCKET_SCOPED_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET
/etc/restic/repository-r2;替换账户与 bucket 名,不要添加公开域名
s3:https://ACCOUNT_ID.r2.cloudflarestorage.com/BUCKET/vps-restic

在受控的 root 会话中读取 `r2.env`,再用 `--repository-file /etc/restic/repository-r2` 和同一 password file 执行一次 `init`、备份与恢复。不要把密钥直接写成 `export AWS_SECRET_ACCESS_KEY=...` 留在 shell 历史。自动化时让 systemd 通过仅 root 可读的 `EnvironmentFile` 注入这两个变量,并检查失败退出码。

把恢复演练当成发布门

每次策略变更后,先恢复到空的隔离目录。Restic 会在目标目录下重建快照中的路径;不要直接覆盖生产。核对文件、权限、应用版本和数据库导入,再记录快照 ID、耗时与验收结果。`check` 验证仓库结构,`--read-data` 会读取全部 pack,适合按容量安排周期性深度检查。

只恢复到隔离目录;随后执行应用级验收,不直接覆盖生产
sudo install -d -m 0750 /srv/restore-drill
sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password check --read-data

sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password \
  restore latest --target /srv/restore-drill

find /srv/restore-drill -type f -print | head -50

先预演保留,再允许删除

保留周期必须覆盖误删被发现的时间,并匹配 RPO、容量和合规要求。下面只是示例。Restic 官方说明 `forget` 先移除快照,`--prune` 才回收不再引用的数据;prune 会锁定仓库且可能耗时。先用 `--dry-run` 审阅 keep/remove 清单,完成最新恢复演练,并确认没有并发备份后再执行。

第二条命令会删除快照并回收数据;不要未经预演直接自动化
sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password \
  forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --dry-run

# 审阅清单并完成恢复演练后,才在维护窗口执行:
sudo restic --repository-file /etc/restic/repository \
  --password-file /etc/restic/repository-password \
  forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

可交付的验收记录

  • 备份任务非零退出时能告警,日志不包含密码、Access Key 或 Secret。
  • 最新与至少一个旧快照都能恢复到隔离目录,并通过应用级只读检查。
  • 仓库密码可从独立保管位置取回;R2 令牌能轮换且只作用于指定 bucket。
  • 定期执行仓库检查,容量允许时安排 `check --read-data`;失败会阻止后续 prune。
  • 保留 dry run、恢复耗时、快照 ID、客户端版本和验收人,下一次演练可以复现。

返回知识库