服务器运行久了,总会积累越来越多的重要数据:网站代码、数据库备份、上传文件、配置文件、日志以及各种业务数据。

这些数据平时可能不会引起太多关注,但一旦遇到磁盘损坏、误删除、服务器被攻击或者系统迁移,能不能快速恢复就显得非常重要。

很多人会使用 tar 打包,再通过 scp 或 rsync 上传到另一台服务器。这种方式虽然简单,但随着数据量增加,会逐渐暴露出一些问题:

  • 每次都要处理大量文件,备份耗时较长。
  • 多次备份会产生大量重复数据,占用存储空间。
  • 缺少统一的历史版本管理。
  • 需要自己编写脚本处理备份保留和清理。
  • 备份文件缺少统一的加密和完整性检查机制。

如果希望有一套更完善的备份方案,可以了解一下 Restic。

Restic 是一款开源、跨平台的备份工具,支持增量备份、数据去重、加密存储和多种存储后端。通过它,我们可以用相对简单的命令,为 Linux 服务器建立一套自动化备份方案。

本文将从实际使用出发,介绍 Restic 的安装、配置、备份、恢复和自动化运维。

一、Restic 是什么?

Restic 是一款使用 Go 语言开发的开源备份工具,支持 Linux、macOS、Windows 等操作系统。

它的设计目标比较明确:让备份过程尽可能简单,同时保证备份数据的安全性和存储效率。

与传统的文件打包方式相比,Restic 有几个比较重要的特点。

1. 增量备份与数据去重

Restic 不会在每次备份时都重新上传所有文件。

它会分析文件内容,将数据拆分成不同的数据块,并通过内容识别和去重机制,复用仓库中已经存在的数据。

例如,服务器第一次备份了一个 10 GB 的目录,第二天只修改了其中一部分文件,那么第二次备份通常只需要保存新增或发生变化的数据块。

这样可以减少重复数据的传输和存储开销。

2. 自动加密

Restic 在保存数据之前会进行加密。

备份仓库中的文件内容、文件名等信息不会以普通明文形式直接暴露。即使备份数据存储在远程服务器或对象存储中,也不意味着存储服务提供商能够直接读取备份内容。

需要注意的是,加密密码非常重要。如果丢失了访问仓库所需的密钥或密码,又没有其他可用密钥,就可能无法恢复数据。

3. Snapshot 快照管理

Restic 使用 Snapshot(快照)记录某个时间点的文件状态。

例如:

  • 周一备份了一次。
  • 周二修改了配置文件,再备份一次。
  • 周三误删了一个目录。

即使当前服务器上的文件已经发生变化,也可以选择周一或周二的快照进行恢复。

这意味着 Restic 不只是保存一份文件副本,还能帮助我们管理历史版本。

4. 支持多种存储后端

Restic 不局限于本地磁盘,可以将备份保存到多种存储位置:

  • 本地目录
  • SFTP 服务器
  • HTTP REST Server
  • Amazon S3
  • MinIO
  • Backblaze B2
  • Microsoft Azure Blob Storage
  • Google Cloud Storage
  • 其他兼容存储或通过 rclone 接入的服务

因此,我们可以根据实际环境选择备份目标。

例如,将业务服务器的数据备份到另一台独立服务器,或者备份到 S3 兼容对象存储中。

二、安装 Restic

Restic 支持多种操作系统,这里以 Linux 服务器为例。

1. 使用系统包管理器安装

Ubuntu / Debian:

sudo apt update
sudo apt install restic

CentOS / RHEL 系列可以根据系统版本和软件源情况安装:

sudo dnf install restic

如果系统软件源中的版本较旧,也可以从 Restic 官方发布页面下载对应平台的二进制文件。

官方地址:

https://github.com/restic/restic/releases

2. 验证安装

安装完成后,执行:

restic version

如果能够正常输出版本信息,就说明安装成功。

还可以查看帮助信息:

restic --help

Restic 采用子命令的方式组织功能,例如:

restic init
restic backup
restic snapshots
restic restore
restic forget
restic prune

每个子命令都有自己的参数,可以通过以下方式查看:

restic backup --help

三、初始化备份仓库

在使用 Restic 之前,需要先创建一个 Repository(仓库)。

可以将 Repository 理解为 Restic 专门用来存储备份数据的目录或远程存储空间。

一个仓库可以保存多个时间点的快照,Restic 会负责管理其中的数据块、索引和元数据。

1. 创建本地仓库

先创建一个目录:

mkdir -p /data/restic-repo

然后初始化仓库:

restic init --repo /data/restic-repo

首次初始化时,Restic 会要求输入仓库密码。

初始化成功后,就可以向这个仓库写入备份数据了。

需要注意,本地仓库只是为了方便演示。如果备份数据和业务数据放在同一块磁盘上,那么磁盘损坏时,两份数据可能同时丢失。

生产环境更建议使用独立存储设备、远程服务器或者对象存储。

2. 创建 SFTP 远程仓库

如果有另一台 Linux 服务器,可以通过 SFTP 将备份保存到远程机器。

假设:

  • 远程服务器:192.168.1.100
  • SSH 用户:backup
  • 远程仓库目录:/srv/restic-repo

首先确保远程服务器已经安装 SSH 服务,并且备份用户拥有对应目录的读写权限。

然后配置 SSH 密钥登录,确保自动备份时不会出现交互式密码输入。

初始化远程仓库:

restic -r sftp:[email protected]:/srv/restic-repo init

Restic 会连接远程服务器,并在指定目录中创建仓库。

后续备份只需要使用相同的仓库地址即可。

3. 配置仓库环境变量

每次执行命令都指定 --repo 比较麻烦,可以通过环境变量配置仓库地址。

例如:

export RESTIC_REPOSITORY="sftp:[email protected]:/srv/restic-repo"

仓库密码也可以通过环境变量或密码文件提供。

生产环境更建议使用密码文件:

export RESTIC_PASSWORD_FILE="/etc/restic/password"

创建密码文件:

sudo mkdir -p /etc/restic
sudo sh -c 'printf "%s" "替换成你的强密码" > /etc/restic/password'
sudo chmod 600 /etc/restic/password
sudo chown root:root /etc/restic/password

这里的密码只是示例,实际使用时应该替换成随机生成的强密码。

配置完成后,执行:

restic snapshots

如果仓库还没有快照,可能会提示没有可用快照,这是正常现象。

特别提醒:Restic 仓库密码丢失可能导致备份数据无法恢复。不要只把密码保存在正在备份的服务器上。 应该将密码和必要的恢复信息安全地保存在独立位置。

四、执行第一次备份

仓库准备好之后,就可以开始备份数据了。

假设服务器上有以下目录:

/etc
/var/www
/data

我们希望备份系统配置、网站文件和业务数据。

1. 执行基础备份

执行:

restic backup /etc /var/www /data

Restic 会扫描这些目录,并将需要保存的数据写入仓库。

执行成功后,会输出类似信息:

repository ... opened successfully
using parent snapshot ...
Files:       1200 new, 0 changed, 0 unmodified
Dirs:         180 new, 0 changed, 0 unmodified
Added to the repository: 1.234 GiB
processed 1200 files, 2.345 GiB in 0:01
snapshot 12345678 saved

其中比较重要的是:

  • new:新增的文件。
  • changed:发生变化的文件。
  • unmodified:没有发生变化的文件。
  • Added to the repository:本次实际新增到仓库的数据量。
  • snapshot:本次备份生成的快照 ID。

实际输出会根据 Restic 版本和备份内容有所不同。

2. 排除不需要备份的文件

并不是所有文件都值得备份。

例如:

  • 临时文件。
  • 缓存目录。
  • 日志文件。
  • 程序运行时生成的临时数据。
  • 可以重新下载或重新生成的文件。

可以通过 --exclude 排除指定路径:

restic backup \
    /etc \
    /var/www \
    /data \
    --exclude="/var/www/*/storage/logs/**" \
    --exclude="/data/cache/**" \
    --exclude="*.tmp"

如果排除规则比较多,也可以单独维护一个文件。

例如创建:

/etc/restic/excludes.txt

内容如下:

*.tmp
*.log
**/cache/**
**/tmp/**
**/node_modules/**

然后执行:

restic backup \
    /etc \
    /var/www \
    /data \
    --exclude-file=/etc/restic/excludes.txt

需要注意,排除规则应结合业务实际情况配置。不要为了减少备份量,把上传文件、业务附件等重要数据也排除掉。

3. 给备份添加标签

当一个仓库中保存了多台服务器或多种备份任务时,可以使用 Tag 区分不同的备份。

例如:

restic backup \
    /etc \
    /var/www \
    --tag server-01 \
    --tag web

后续查看快照时,就可以根据标签进行筛选。

标签对于多服务器、多业务的备份管理很有帮助。

五、理解 Restic 的增量备份机制

第一次使用 Restic 时,很多人会关心一个问题:

如果每天都执行一次 restic backup,是不是每天都会重新上传全部文件?

答案是否定的。

Restic 会通过文件扫描、内容分块和数据去重等机制,尽可能复用仓库中已经存在的数据。

1. 什么是内容定义分块?

Restic 不只是简单地判断文件有没有修改,而是会将文件内容拆分成多个数据块。

它使用 Content Defined Chunking(内容定义分块,简称 CDC)技术,根据文件内容确定分块边界。

这样做有一个好处:当文件中间插入或删除了一部分内容时,后续数据块的边界不一定全部发生变化。

相比固定大小分块,内容定义分块通常更容易识别文件修改前后仍然相同的数据区域。

2. 什么是数据去重?

假设有两个目录:

/data/project-a
/data/project-b

它们里面有一些相同的文件。

如果使用普通压缩包分别备份,重复内容通常也会被重复保存。

而 Restic 会识别已经存在的数据块,在符合条件时直接复用,不需要再次存储相同内容。

这就是数据去重。

3. 为什么第二次备份会更快?

第一次备份时,Restic 需要读取并保存大量数据。

第二次备份时,如果大部分文件没有变化,就可以复用之前保存的数据块,只处理新增或变化的部分。

例如:

备份时间文件总量本次新增数据
第一天10 GB10 GB
第二天10 GB100 MB
第三天10 GB20 MB
第四天10 GB0 MB

以上只是用于说明机制的假设数据,实际新增量取决于文件变化情况和分块结果。

需要注意,增量备份不代表完全不读取文件。Restic 仍然可能需要扫描文件系统并读取文件内容,以判断哪些数据需要保存。

六、查看和管理备份快照

Restic 使用 Snapshot 管理每一次备份。

每次成功创建备份后,通常都会生成一个新的快照。

1. 查看所有快照

执行:

restic snapshots

输出类似:

ID        Time                 Host        Tags
-------------------------------------------------------
a1b2c3d4  2025-11-01 02:00:00  server-01   web
e5f6g7h8  2025-11-02 02:00:00  server-01   web
i9j0k1l2  2025-11-03 02:00:00  server-01   web

每个快照都有独立的 ID,可以通过它选择需要恢复的备份。

2. 查看快照中的文件

例如:

restic ls latest

可以查看最新快照中保存的文件和目录。

如果希望查看指定快照:

restic ls a1b2c3d4

3. 比较两个快照

如果想知道两次备份之间有哪些变化,可以使用 diff:

restic diff a1b2c3d4 e5f6g7h8

这对于排查文件变化、确认误操作以及检查备份内容非常有用。

4. 查看仓库统计信息

执行:

restic stats

可以查看仓库的基本统计信息。

如果想查看最新快照对应的数据量:

restic stats latest

如果想了解去重前的数据量:

restic stats --mode raw-data latest

通过对比数据量,可以大致了解去重带来的存储节省效果。

七、如何恢复备份数据?

备份的最终目的不是保存数据,而是在需要的时候恢复数据。

Restic 提供了 restore 命令,可以将指定快照中的文件恢复到目标目录。

1. 恢复整个快照

例如,将最新快照恢复到 /tmp/restore:

restic restore latest --target /tmp/restore

执行后,Restic 会将快照中的文件恢复到目标目录。

如果需要恢复某个历史快照:

restic restore a1b2c3d4 --target /tmp/restore

2. 只恢复指定目录

如果只需要恢复网站目录,可以使用 --include:

restic restore latest \
    --target /tmp/restore \
    --include /var/www

这样就不需要恢复整个快照。

3. 恢复指定文件

例如,只恢复某个配置文件:

restic restore latest \
    --target /tmp/restore \
    --include /etc/nginx/nginx.conf

恢复完成后,文件会位于:

/tmp/restore/etc/nginx/nginx.conf

建议先恢复到临时目录,检查文件内容和权限,再决定是否覆盖生产环境中的文件。

4. 挂载仓库查看历史文件

除了 restore,Restic 还支持通过 mount 将仓库挂载成一个可浏览的文件系统。

例如:

mkdir -p /mnt/restic

restic mount /mnt/restic

挂载成功后,可以在对应目录中浏览历史快照。

这种方式适合需要查找某个历史文件,但又不确定具体快照 ID 的场景。

具体使用还需要系统支持 FUSE,Windows 等平台的挂载方式有所不同。

八、配置备份保留策略

如果每天都执行一次备份,快照数量会不断增加。

虽然 Restic 会进行数据去重,但长期保留所有历史快照,仍然可能占用较多存储空间。

因此,需要制定合理的备份保留策略。

常见策略如下:

类型保留数量说明
每日备份7保留最近 7 天
每周备份4保留最近 4 周
每月备份6保留最近 6 个月
每年备份2保留最近 2 年

可以使用 forget 命令实现:

restic forget \
    --keep-daily 7 \
    --keep-weekly 4 \
    --keep-monthly 6 \
    --keep-yearly 2

执行前建议先使用 --dry-run:

restic forget \
    --keep-daily 7 \
    --keep-weekly 4 \
    --keep-monthly 6 \
    --keep-yearly 2 \
    --dry-run

它只会展示计划删除的快照,不会真正执行删除操作。

1. Forget 和 Prune 有什么区别?

这两个命令很容易混淆。

简单来说:

  • forget:删除不再需要的快照记录。
  • prune:清理仓库中已经没有快照引用的数据块,回收实际存储空间。

例如:

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

这一步主要处理快照的保留策略。

随后执行:

restic prune

清理不再被快照引用的数据。

也可以使用 --prune 将两步合并:

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

需要注意,prune 可能涉及数据包重写和远程数据传输,执行时间可能比较长,而且执行期间仓库会被锁定,影响其他备份任务。

因此,生产环境建议将清理任务安排在备份低峰期,而不是每次备份完成后都立即执行。

九、搭建 Linux 服务器自动化备份

前面介绍了 Restic 的基本操作,但实际生产环境中,不可能每天手动执行备份。

接下来通过 Shell 脚本和 Cron,搭建一个简单的自动化备份方案。

1. 准备配置文件

先创建配置文件:

sudo mkdir -p /etc/restic
sudo vim /etc/restic/backup.env

配置内容:

export RESTIC_REPOSITORY="sftp:[email protected]:/srv/restic-repo"
export RESTIC_PASSWORD_FILE="/etc/restic/password"

设置权限:

sudo chown root:root /etc/restic/backup.env
sudo chmod 600 /etc/restic/backup.env

前面已经创建了密码文件,这里不再重复配置。

2. 编写自动备份脚本

创建脚本:

sudo vim /usr/local/bin/restic-backup.sh

脚本内容:

#!/usr/bin/env bash

set -Eeuo pipefail

CONFIG_FILE="/etc/restic/backup.env"
LOG_DIR="/var/log/restic"
LOG_FILE="${LOG_DIR}/backup.log"

mkdir -p "${LOG_DIR}"

# 加载仓库配置
source "${CONFIG_FILE}"

# 备份目录
BACKUP_PATHS=(
    "/etc"
    "/var/www"
    "/data"
)

# 排除规则
EXCLUDE_FILE="/etc/restic/excludes.txt"

# 记录日志
exec >> "${LOG_FILE}" 2>&1

echo "========================================"
echo "Backup started at: $(date '+%F %T')"

# 执行备份
restic backup \
    "${BACKUP_PATHS[@]}" \
    --exclude-file="${EXCLUDE_FILE}" \
    --tag "server-01" \
    --tag "daily"

echo "Backup finished at: $(date '+%F %T')"

设置执行权限:

sudo chmod 700 /usr/local/bin/restic-backup.sh

这里使用了 Bash 数组保存备份目录,避免目录路径中存在空格时出现参数解析问题。

脚本中使用 set -Eeuo pipefail,可以让脚本在发生错误时尽早退出,避免备份失败后继续执行后续操作。

需要注意,set -e 并不能替代完整的错误监控。生产环境还应该结合退出码、日志和告警系统判断任务是否成功。

3. 配置排除规则

创建:

sudo vim /etc/restic/excludes.txt

例如:

*.tmp
*.log
**/cache/**
**/tmp/**
**/node_modules/**

根据实际业务调整排除规则。

4. 手动执行测试

先手动执行脚本:

sudo /usr/local/bin/restic-backup.sh

查看日志:

tail -f /var/log/restic/backup.log

确认备份成功后,再配置定时任务。

5. 使用 Cron 定时备份

编辑 root 用户的定时任务:

sudo crontab -e

添加:

0 2 * * * /usr/local/bin/restic-backup.sh

表示每天凌晨 2 点执行一次备份。

如果希望每周执行一次仓库清理,可以单独配置清理任务:

0 4 * * 0 /usr/bin/restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-yearly 2 --prune

不过,这里需要注意:

  1. 执行清理命令的用户必须能够读取对应的仓库配置和密码文件。
  2. 清理操作可能耗时较长,应根据仓库大小和网络情况安排时间。
  3. 应确保清理任务不会与其他备份任务冲突。
  4. 建议先使用 --dry-run 检查保留策略。

如果使用的是不同的执行用户,需要为清理任务加载相同的 RESTIC_REPOSITORY 和 RESTIC_PASSWORD_FILE 环境变量。

十、备份仓库检查与生产环境注意事项

自动备份配置完成后,并不意味着备份系统已经可靠。

一个真正可用的备份方案,还需要考虑数据完整性、恢复能力、权限隔离和异常监控。

1. 定期检查仓库

Restic 提供了 check 命令,用于检查仓库的结构和数据一致性。

执行:

restic check

如果希望进一步读取并校验备份数据,可以执行:

restic check --read-data

这会读取仓库中的数据进行更全面的检查,仓库较大时可能耗时较长。

因此,可以根据实际情况安排定期检查,而不是每次备份后都执行完整的数据读取校验。

2. 备份数据库时要保证数据一致性

如果服务器运行着 MySQL 或 PostgreSQL,不建议直接将正在写入的数据库数据目录交给 Restic 备份。

例如,直接备份 MySQL 的数据目录:

restic backup /var/lib/mysql

并不能自动保证备份时数据库处于一致状态。

更合理的方式是:

  1. 使用数据库自身的备份工具生成一致性备份。
  2. 将生成的备份文件保存到独立目录。
  3. 使用 Restic 备份这些文件。
  4. 定期验证数据库备份能否正常恢复。

例如,可以先使用 mysqldump 或其他适合业务规模的数据库备份方案生成文件,再执行 Restic 备份。

对于 PostgreSQL,可以使用 pg_dump、pg_basebackup 等工具,根据恢复目标选择合适的方式。

3. 不要让备份和业务数据处于同一个故障域

如果业务服务器和备份仓库都在同一台机器上,那么:

  • 磁盘损坏可能导致两份数据同时丢失。
  • 服务器被入侵后,攻击者可能同时删除业务数据和备份。
  • 机房故障可能导致两份数据都无法访问。

因此,建议将备份保存到独立的远程存储中。

如果条件允许,可以进一步采用异地备份策略。

4. 做好备份权限隔离

备份账号不应该拥有远程服务器的全部权限。

可以专门创建一个备份用户,只允许访问指定的仓库目录。

如果使用支持追加写入模式的存储服务,还可以考虑将备份写入权限和删除权限分离。

这样即使业务服务器被入侵,攻击者也不一定能够直接删除所有历史备份。

需要注意,追加写入模式也不是万能的。日常备份账号和执行 forget、prune 的管理账号应尽可能分离。

5. 定期进行恢复演练

这是最容易被忽略、却非常重要的一点。

不要只关注备份任务有没有执行成功,还要定期验证数据能否恢复。

可以设计一个简单的恢复演练:

  1. 创建一个测试文件。
  2. 使用 Restic 备份。
  3. 修改或删除原始文件。
  4. 从历史快照恢复。
  5. 检查恢复后的文件内容是否正确。

例如:

mkdir -p /tmp/restore-test

restic restore latest \
    --target /tmp/restore-test

生产环境中,还应该定期验证数据库恢复、应用启动和配置文件完整性。

只有经过恢复验证的备份,才真正具备灾难恢复价值。

十一、总结

Restic 是一款非常实用的开源备份工具。它通过增量备份、数据去重、加密存储和快照管理,解决了传统文件打包备份在存储效率、历史版本管理和数据安全方面的一些问题。

本文从实际使用出发,介绍了 Restic 的安装、仓库初始化、数据备份、快照管理、文件恢复、保留策略以及自动化备份。

如果只是个人使用,可以从本地仓库开始,熟悉 backup、snapshots 和 restore 等常用命令。

如果用于生产环境,建议至少做到:

  • 使用独立的远程存储保存备份。
  • 使用密码文件管理仓库密码,并做好异地保管。
  • 配置自动化备份和历史快照保留策略。
  • 定期检查仓库完整性。
  • 对数据库采用一致性备份方案。
  • 定期执行恢复演练。
  • 做好备份账号和仓库管理权限隔离。

最后,记住一个原则:

备份不是为了证明数据已经保存,而是为了在数据丢失时能够可靠地恢复。

参考资料