教程 · 安全加固
用 restic 做自动异地备份(顺便说清楚快照不是备份)
难度
高级
预计时长
35 分钟
步骤
8 步
最近修订
基准系统
Debian 12
要点
用 restic 做自动异地备份(顺便说清楚快照不是备份)
restic 提供去重、加密、增量的备份仓库,配合 systemd timer 可以每天自动备份并按策略清理旧快照。控制台快照与备份是两回事:快照通常与源机器在同一机房、同一账号之下,机房级故障或账号问题会连同快照一起失去 —— 只有落在另一台机器、另一个机房的副本才算备份。
前置条件
开始之前,先确认这些都具备
- 一台待备份的服务器,以及一个存放备份的目标(另一台 VPS、存储型机器或对象存储)
- 两台机器之间已配置 SSH 密钥登录
- 想清楚要备份哪些目录 —— 这一步不想清楚,后面全是白做
操作步骤
共 8 步
步骤 01 / 08
先列清单:什么必须备份,什么不必 #
备份整块磁盘既慢又贵,而且恢复时你会发现真正需要的只有几个目录。典型清单是:配置(/etc)、网站文件(/var/www)、用户数据(/home)、数据库导出文件。系统本身不用备 —— 重装一遍比恢复更快。把这份清单写进文档,它比脚本更重要。
Shell # 先看看各目录到底多大,再决定备份范围 sudo du -sh /etc /home /var/www /var/lib/docker 2>/dev/null | sort -h步骤 02 / 08
安装 restic 并初始化仓库 #
仓库密码一旦丢失,备份数据就永久打不开了 —— restic 是端到端加密的,没有找回机制。密码存进密码管理器,同时抄一份放在离线的地方。
Shell sudo apt update && sudo apt install -y restic restic version sudo mkdir -p /etc/restic # 生成一个强随机密码(务必另存一份到密码管理器) sudo sh -c 'openssl rand -base64 32 > /etc/restic/password' sudo chmod 600 /etc/restic/password export RESTIC_REPOSITORY="sftp:[email protected]:/srv/restic/web01" export RESTIC_PASSWORD_FILE=/etc/restic/password restic init步骤 03 / 08
先跑一次手动备份 #
自动化之前先手动跑通。第一次是全量,之后 restic 只传输变化的数据块,相同的文件在多台机器之间也只存一份。--exclude-caches 会跳过带 CACHEDIR.TAG 标记的缓存目录。
Shell restic backup /etc /var/www /home \ --exclude-caches \ --exclude '/home/*/.cache' \ --exclude '*.log' restic snapshots restic stats步骤 04 / 08
数据库要先导出,不能直接拷文件 #
直接备份运行中的数据库数据目录,拿到的很可能是一份无法启动的残缺副本。正确做法是先用官方工具导出一致性快照,再让 restic 备份导出文件。
Shell # PostgreSQL sudo -u postgres pg_dump -Fc appdb > /var/backups/appdb.dump # MySQL / MariaDB sudo mysqldump --single-transaction --routines --events appdb > /var/backups/appdb.sql restic backup /var/backups步骤 05 / 08
用 systemd timer 每天自动跑 #
timer 比 cron 更适合这件事:失败会进 journald、Persistent=true 保证关机期间错过的任务开机后补跑、RandomizedDelaySec 避免整个机队在同一秒钟一起压向备份服务器。
systemd 单元 # /etc/systemd/system/restic-backup.service [Unit] Description=restic backup After=network-online.target Wants=network-online.target [Service] Type=oneshot Environment=RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/web01 Environment=RESTIC_PASSWORD_FILE=/etc/restic/password ExecStart=/usr/bin/restic backup /etc /var/www /home /var/backups --exclude-caches ExecStart=/usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune # /etc/systemd/system/restic-backup.timer [Unit] Description=Daily restic backup [Timer] OnCalendar=*-*-* 03:30:00 RandomizedDelaySec=900 Persistent=true [Install] WantedBy=timers.target步骤 06 / 08
启用并确认它真的在跑 #
「配好了」和「在跑」之间隔着一次 enable。list-timers 会告诉你下一次触发时间;几天后再回来看一眼快照数量有没有增加。
Shell sudo systemctl daemon-reload sudo systemctl enable --now restic-backup.timer systemctl list-timers 'restic*' sudo systemctl start restic-backup.service journalctl -u restic-backup.service -n 50 --no-pager步骤 07 / 08
每季度做一次真实恢复演练 #
没有验证过的备份不是备份,只是一个让人安心的错觉。恢复到临时目录,打开几个文件确认内容完整 —— 这件事花十分钟,换来的是真正的睡眠质量。
Shell restic snapshots restic restore latest --target /tmp/restore-test --include /etc/nginx ls -R /tmp/restore-test/etc/nginx | head restic check --read-data-subset=5% rm -rf /tmp/restore-test步骤 08 / 08
快照的定位:回滚工具,不是备份 #
控制台快照适合的场景是「升级前留一个还原点,十分钟内出问题就回滚」。它不适合当备份,因为它通常与源机器在同一机房、同一账号之下:机房级故障、账号异常、误删机器,快照会跟着一起消失。真正的备份必须落在另一台机器、另一个机房 —— 大容量存储型机器(例如 巨舱 1 / JC-1,1 TB)常被用作这种异地副本的落点。
Shell # 3-2-1 原则的最小可用版本: # 3 份数据(生产 + 本地 + 异地) # 2 种位置或介质 # 1 份在另一个机房,并且验证过能恢复
常见错误
这一步最容易踩的坑
下面每一条都对应一个真实会发生的故障。先读完再动手,比出问题之后再回来查要省时间。
- 备份和源数据放在同一台机器上。磁盘坏了、机器被误删、账号出问题,两份一起没。
- 从没做过恢复演练。绝大多数「备份失效」都是在真正需要恢复的那一天才被发现的。
- 直接 rsync 或 restic 运行中的数据库数据目录。拿到的文件很可能无法启动,必须先用 pg_dump / mysqldump 导出。
- 丢失 restic 仓库密码。restic 没有密码找回机制,密码丢了,备份就是一堆随机字节。
- 只备份不清理。没有 forget --prune,仓库会持续膨胀直到写满目标磁盘,然后备份开始失败,而通常没人在看那个日志。
- 把控制台快照当备份用。快照回答的是「十分钟前的状态」,不是「机房没了怎么办」。
- 备份里含明文密钥与 .env 文件,而备份目标机器的防护远不如生产机。备份仓库本身也要按生产标准加固。
这篇教程的边界
- 命令以 Debian 12 为准。Ubuntu 与 Rocky Linux 的差异只在正文明确标注之处,未标注的部分请以你所用发行版的官方文档为准。
- 示例中的 IP 来自文档保留段 203.0.113.0/24,域名为 example.com,端口为示意值。复制后必须替换成自己的值, 原样执行不会有任何效果。
- 教程不能替代备份。任何会改动数据或线上流量的步骤,执行前先确认有一份验证过能恢复的备份。
- 本站不提供任何用于绕过网络审查的配置或说明,这篇也不例外。
发现命令过时或有误,请发邮件到 [email protected]。 指出错误的邮件比沉默的旧文档有价值得多。