帮助中心

服务器、网络和账户的分步教程。

Linux 服务器

用 restic 和 rclone 实现 VPS 自动加密备份(每日异地备份并验证恢复)

用 restic 和 rclone 实现 VPS 自动加密备份(每日异地备份并验证恢复)

Linux VPS 最稳妥的备份方式是:每天用 restic 把加密快照发送到服务器之外的存储,设定清晰的保留策略,并定期测试恢复。本文在 Debian 12/13、Ubuntu 22.04/24.04 和 Rocky Linux / AlmaLinux 上完成整套配置:安装 restic、选择异地仓库(S3 兼容存储、SFTP 或 rclone)、导出数据库、用 systemd 定时器自动运行,并验证数据确实能恢复。

为什么备份必须放在 VPS 之外

放在同一台服务器上的副本不算备份:任何删除服务器的操作都会把副本一起删掉。在 JUSTG 云服务器上,以下几种正常操作都会永久删除数据:

  • 更换机房(Change location):系统会新装一台 VPS,分配新 IP,不复制任何数据。新 VPS 就绪后,旧 VPS 及其全部数据会被删除。
  • 逾期未续费:未付款的服务会在到期日自动暂停;到期 7 天后账单仍未支付,服务会被取消,数据随之删除。
  • 重装系统会清空硬盘;选择 Immediate 方式取消服务,请求处理后服务和数据会立即删除。

再加上误敲的 rm -rf、失败的升级或服务器被入侵,结论很简单:唯一可靠的备份,是你自己做、并存放在别处的备份。在更换机房、重装系统或取消服务之前,请先手动运行一次备份,并确认新快照已经生成。

restic 在 VPS 本机完成加密后才上传,存储服务商只能看到加密后的数据块。它还会去重:首次完整上传之后,每天的快照只发送有变化的部分。

步骤 1:安装 restic

Debian 12/13、Ubuntu 24.04 和 EPEL 自带的版本已经足够新:

# Debian 12/13, Ubuntu 24.04
apt update && apt install -y restic
restic version

# Rocky Linux / AlmaLinux 8, 9 (from EPEL)
dnf install -y epel-release && dnf install -y restic

Ubuntu 22.04 自带的是 restic 0.12,不支持压缩,也无法使用当前的仓库格式。在这个系统上,请安装官方二进制文件并校验 checksum:

# Official static binary (Ubuntu 22.04 or any distro with an old restic)
VER=0.18.1   # check https://github.com/restic/restic/releases for the latest version
cd /tmp
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/restic_${VER}_linux_amd64.bz2
curl -fLO https://github.com/restic/restic/releases/download/v${VER}/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS      # must print: OK
bunzip2 restic_${VER}_linux_amd64.bz2
install -m 0755 restic_${VER}_linux_amd64 /usr/local/bin/restic
restic version

步骤 2:选择异地仓库

仓库就是存放加密快照的地方。任选一种方案,保存为 /etc/restic/env(每行一个 NAME=value)。

方案 A:S3 兼容对象存储

任何提供 S3 API 的服务商都可以。创建一个存储桶和只限该存储桶的访问密钥,并在 URL 中填写服务商的 endpoint:

# /etc/restic/env  (S3-compatible object storage)
RESTIC_REPOSITORY=s3:https://s3.example.com/example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=REPLACE_WITH_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=REPLACE_WITH_SECRET_KEY
# Optional: monitoring ping URL (Step 11)
HC_PING_URL=

方案 B:通过 SFTP 备份到另一台服务器

使用你自己的另一台服务器,最好位于不同机房或不同服务商,并建立专用的 backup 用户,由它拥有 /srv/restic:

# /etc/restic/env  (SFTP to a second server)
RESTIC_REPOSITORY=sftp:[email protected]:/srv/restic/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
HC_PING_URL=

# One-time SSH key login for root on the VPS
ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519   # skip if the key exists
ssh-copy-id [email protected]
ssh [email protected] true      # accept the host key once

方案 C:rclone 后端

rclone 能让 restic 连接几十种存储服务(Backblaze B2、Google Drive、OneDrive、WebDAV 等):

# Install and configure rclone (interactive wizard, run as root)
apt install -y rclone        # Rocky/Alma: dnf install -y rclone (EPEL)
rclone config                # create a remote, for example named "offsite"

# /etc/restic/env  (any rclone backend)
RESTIC_REPOSITORY=rclone:offsite:example-backups/vps1
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
RCLONE_CONFIG=/root/.config/rclone/rclone.conf
HC_PING_URL=
/etc/restic/env 里的凭据通常也有删除备份的权限,攻击者一旦控制 VPS,就可能清空仓库。想要更强的保护,可以为存储桶开启版本控制或 object lock,或使用只能追加写入的目标,并且不要把存储账号的登录密码放在服务器上。

步骤 3:创建密码文件并初始化仓库

install -d -m 0700 /etc/restic
openssl rand -base64 32 > /etc/restic/password
chmod 600 /etc/restic/password
nano /etc/restic/env          # paste one of the examples above
chmod 600 /etc/restic/env

# Load the settings into the current shell and create the repository
set -a; . /etc/restic/env; set +a
restic init
没有密码,任何人都无法解密备份,包括你自己。请立即把 /etc/restic/password 和 /etc/restic/env 复制到密码管理器或服务器以外的安全位置:VPS 一旦不在了,恢复只需要这两个文件。

步骤 4:确定备份哪些内容、排除哪些内容

只备份配置和数据,不必备份整个操作系统:重装系统比恢复系统文件更快,快照也更小。

# /etc/restic/include  - one path per line; delete lines that do not exist
/etc
/root
/home
/srv
/var/www
/opt
/usr/local
/var/spool/cron
/var/backups/db

# /etc/restic/excludes
/root/.cache
/home/*/.cache
**/node_modules
**/*.tmp
/var/www/*/cache
  • 需要备份:/etc、用户主目录、网站根目录、应用数据、crontab 以及数据库导出目录。
  • 无需备份:/proc、/sys、/dev、/run、/tmp、swap 文件和各类缓存。它们不在列表里,restic 根本不会读取。
  • 数据库原始文件(/var/lib/mysql、/var/lib/postgresql)在数据库运行时直接复制,可能得到不一致的副本。请备份导出文件(步骤 5)。
  • Docker:不要整体备份 /var/lib/docker,应备份 compose 文件以及存放数据的卷或目录。

步骤 5:每次备份前先导出数据库

下面的脚本把压缩后的导出文件写入 /var/backups/db,该目录已在备份列表中。请按服务器实际情况设置 MYSQL 和 POSTGRES:

#!/bin/bash
# /usr/local/sbin/db-dump.sh - consistent database dumps before each backup
set -euo pipefail
umask 077
MYSQL=yes        # yes / no
POSTGRES=no      # yes / no
OUT=/var/backups/db
mkdir -p "$OUT"

if [ "$MYSQL" = yes ]; then
  DUMP=$(command -v mariadb-dump || command -v mysqldump)
  "$DUMP" --all-databases --single-transaction --quick \
          --routines --events --triggers | gzip > "$OUT/mysql-all.sql.gz.tmp"
  mv "$OUT/mysql-all.sql.gz.tmp" "$OUT/mysql-all.sql.gz"
fi

if [ "$POSTGRES" = yes ]; then
  cd /tmp
  runuser -u postgres -- pg_dumpall | gzip > "$OUT/postgres-all.sql.gz.tmp"
  mv "$OUT/postgres-all.sql.gz.tmp" "$OUT/postgres-all.sql.gz"
fi

--single-transaction 能在不锁住网站的情况下得到一致的 InnoDB 导出。在 Debian 和 Ubuntu 上,root 通过本地 socket 连接 MariaDB/MySQL,无需密码;如果你的服务器需要密码,请写入 /root/.my.cnf(权限 600),不要写在命令行里。

步骤 6:创建备份脚本

一个脚本完成数据库导出、备份、按策略清理和每周检查,并向可选的监控 URL 汇报结果(步骤 10)。任何一步失败都会让脚本报错退出,问题不会被悄悄忽略:

#!/bin/bash
# /usr/local/sbin/restic-backup.sh - dump databases, back up, apply retention
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
set -a; . /etc/restic/env; set +a

fail() {
  [ -n "${HC_PING_URL:-}" ] && curl -fsS -m 10 --retry 3 "$HC_PING_URL/fail" >/dev/null || true
}
trap fail ERR

/usr/local/sbin/db-dump.sh

restic backup \
  --files-from /etc/restic/include \
  --exclude-file /etc/restic/excludes \
  --exclude-caches \
  --tag daily

restic forget --prune \
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6

# Sundays: verify the repository and read back 5% of the data
if [ "$(date +%u)" = 7 ]; then
  restic check --read-data-subset=5%
fi

if [ -n "${HC_PING_URL:-}" ]; then
  curl -fsS -m 10 --retry 3 "$HC_PING_URL" >/dev/null
fi

为脚本加上执行权限,并手动运行第一次备份。首次运行会上传全部数据,之后只上传变化部分。

chmod 700 /usr/local/sbin/db-dump.sh /usr/local/sbin/restic-backup.sh
/usr/local/sbin/restic-backup.sh      # first run by hand, watch for errors
restic snapshots

步骤 7:用 systemd 定时器(或 cron)定时运行

推荐使用 systemd 定时器:日志会写入 journal,错过的任务会在开机后补跑(Persistent=true),还能降低任务的 CPU 和磁盘优先级,不拖慢网站。

# /etc/systemd/system/restic-backup.service
[Unit]
Description=restic backup to off-site repository
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh
Nice=10
IOSchedulingClass=idle

# /etc/systemd/system/restic-backup.timer
[Unit]
Description=Daily restic backup

[Timer]
OnCalendar=*-*-* 03:30:00
RandomizedDelaySec=30min
Persistent=true

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now restic-backup.timer
systemctl list-timers restic-backup.timer

# Test the service once and read its log
systemctl start restic-backup.service
journalctl -u restic-backup.service -n 50 --no-pager

如果你更习惯 cron,可以用下面这行代替定时器(二者只选其一):

# /etc/cron.d/restic-backup  (only if you do not use the systemd timer)
30 3 * * * root /usr/local/sbin/restic-backup.sh >> /var/log/restic-backup.log 2>&1
在夜间以低优先级运行备份,对硬盘更友好,也有助于遵守存储 I/O 的合理使用规则。

步骤 8:用 restic forget --prune 设置保留策略

restic forget 决定保留哪些快照,--prune 删除已不被任何快照引用的数据。脚本中的策略会保留:

参数保留内容
--keep-daily 7最近 7 天中每天最后一个快照
--keep-weekly 4最近 4 周每周一个快照
--keep-monthly 6最近 6 个月每月一个快照

启用新策略之前,先用 --dry-run 预览效果:

set -a; . /etc/restic/env; set +a
restic snapshots
# Preview what a policy would remove, without deleting anything
restic forget --dry-run --keep-daily 7 --keep-weekly 4 --keep-monthly 6
restic stats --mode raw-data

脚本还会在每周日运行 restic check,检查仓库结构;--read-data-subset=5% 每次下载并校验不同的 5% 数据,让损坏在你真正需要备份之前就被发现。需要更放心时,也可以随时手动运行 restic check。

步骤 9:测试恢复

从未恢复过的备份只是一种希望。每月一次,把真实数据恢复到临时目录并进行比对:

set -a; . /etc/restic/env; set +a
restic snapshots
restic ls latest /etc/nginx

# Restore one directory to a scratch location, then compare
restic restore latest --target /tmp/restore-test --include /etc/nginx
diff -r /etc/nginx /tmp/restore-test/etc/nginx && echo "restore OK"

# Check that the database dump is complete (last line: "-- Dump completed on ...")
restic dump latest /var/backups/db/mysql-all.sql.gz | zcat | tail -n 1
rm -rf /tmp/restore-test

最坏的情况也要演练一次,例如在一台备用 VPS 上:一台全新服务器,手里只有保存好的那两个文件。

# On the NEW server: install restic, then restore the two saved files
install -d -m 0700 /etc/restic
nano /etc/restic/password && nano /etc/restic/env
set -a; . /etc/restic/env; set +a

restic restore latest --target /srv/restore
rsync -a /srv/restore/var/www/ /var/www/          # copy back what you need
zcat /srv/restore/var/backups/db/mysql-all.sql.gz | mariadb     # or: mysql
不要在运行中的系统上执行 restic restore latest --target /:它会覆盖正在使用的文件,包括可能不适合新服务器的系统配置。请恢复到单独的目录,再把需要的内容复制回去。

步骤 10:备份失败时及时收到提醒

备份往往是悄无声息地失败的:密钥过期、存储桶满了、密码被改了。“dead man's switch”类服务可以解决这个问题:脚本每次成功后访问一个 URL,若没有按时收到访问,就会向你发出提醒。你可以自建(例如开源的 Healthchecks),也可以使用任何类似服务,然后把检查 URL 写入 /etc/restic/env:

HC_PING_URL=https://hc.example.com/ping/REPLACE-WITH-YOUR-CHECK-ID

脚本成功时访问该 URL,出错时访问 $HC_PING_URL/fail。把检查周期设为一天,并留出几个小时的宽限时间。如果不用这类服务,至少每周查看一次 restic snapshots 和 journalctl -u restic-backup.service。

FAQ

需要多大的存储空间?

首次快照大约等于你的数据量(压缩后通常更小),之后每天只增加少量变化数据。运行几周后执行 restic stats --mode raw-data,即可看到实际用量。

restic 提示仓库被锁定,怎么办?

说明上一次运行被中断,留下了过期的锁。先确认没有 restic 进程在运行(pgrep -a restic),再执行 restic unlock,然后重新运行备份。

在 512 MB 方案上 restic 占用内存太多,能降低吗?

可以在 /etc/restic/env 中加入 GOGC=20,让 restic 更频繁地释放内存;同时精简备份路径,并确认 VPS 已配置 swap。如果内存仍然不够,可以在服务页面升级方案。需要帮助请提交工单:JUSTG 提供 7×24 小时 AI 客服(工单),需要人工处理的问题会由工程师跟进。

这篇文章有帮助吗?
帮助中心
Linux 服务器 Linux SSH 密钥登录教程:设置 ed25519 密钥并禁用密码登录 只要服务器有公网 IPv4,上线几分钟内就会遇到 SSH 暴力破解机器人,而密码登录正是它们的首要目标。本文说明如何用较新的 ed25519 密钥完成 Linux SSH 密钥登录,再禁用 SSH 密码登录,全程避免把自己锁在门外。步骤适用于 Debian… Linux 服务器 Linux VPS 修改 SSH 端口与 root 密码教程(安全不断线) 把 SSH 从 22 端口移走虽然挡不住有心的攻击者,却能让日志里大部分自动扫描消失;而任何新服务器的第一件事,就是换一组新的 root 密码。本文说明如何在 Linux VPS 修改 SSH 端口与 root 密码且不断线:修改 sshd_config、在 Rocky… Linux 服务器 Linux 防火墙设置教程:VPS 使用 UFW 与 firewalld(含 IPv6) 新安装的 Linux 服务器,任何服务打开的端口都会直接对外响应,因此主机防火墙是最先要设置的项目之一。本文说明如何在 Debian / Ubuntu 用 UFW 设置 Linux 防火墙,以及在 CentOS、Rocky Linux、AlmaLinux 使用… Linux 服务器 Linux VPS 添加 Swap 交换空间教程(适合 512MB / 1GB 小内存套餐) 在 512 MB 或 1 GB 的云服务器上,数据库、PHP-FPM 加上一次软件包更新,很容易在同一时间用光内存。这时内核的 OOM killer 会强制终止进程,最常被牺牲的就是 MySQL 或 MariaDB。在 Linux VPS 添加 Swap… Linux 服务器 Linux 硬盘空间已满怎么办?VPS 找出并释放磁盘空间教程 “No space left on device”几乎会让服务器上所有东西出问题:数据库无法写入、网站返回错误、软件包更新失败,有时甚至无法正常登录。本文一步步说明如何排除 Linux 硬盘空间已满:先确认是数据块还是 inode 用完,再用 du 与 ncdu…
AlipayUnionPayVISAMastercardPayPalUSDTstripe