前些时间提到,我的群晖 NAS 数据被套件误删了。由于是第三方套件造成的,即便我之前使用的是正版群晖硬件,也不可能就此向官方讨个说法。不过,我仍庆幸群晖有着强大的应用生态,能借助多种工具的协同配合完成重要数据的备份。例如,我通过 Hyper Backup 对 Docker 数据文件夹做了增量备份,又用 CloudSync 将这些备份同步到了云端。当本地数据意外丢失时,这些云端的备份全部得以幸免于难。

可换用飞牛的 fnOS 作为 NAS 系统之后,这套备份组合也随之失效。

fnOS 无论是界面、应用、生态还是移动端 APP ,都很符合我现阶段对一个 NAS 系统的基本需求。唯一美中不足的地方,就是它的备份功能。

作为 NAS 系统,其备份功能仍显不足。即便是迭代至正式版,它支持的备份方式也依旧有限。而且在实际使用过程中,备份到百度网盘的数据还会因为体积太大而经常上传失败。

我本想着,既然现在的 fnOS 备份不方便,说不定后续的更新迭代会优化这一块,要不就先放一边,等下次想起来再说。可谁曾想,飞牛于近日被爆出存在超高危的 0day 漏洞

这可把我吓了一跳。好在我一直通过 VPN 访问家庭网络,从未将 NAS 公开至公网,仔细检查后也没有发现病毒。

但要命的是,虽然该问题在系统更新后被修复(?),但是飞牛官方对此次事件采取的却是近乎冷处理的公关方式:既没有第一时间向用户发出明确的风险预警和紧急防护指引,也未做任何醒目的升级提醒,更是使用「异常访问风险」、「自身代码疏漏」这类模糊表述淡化问题本质,迟迟不肯正面承认此次漏洞产生的严重危害。

软件存在问题在所难免,承认错误及时处理便是,可飞牛对待此类安全问题却是这般敷衍的态度。我开始重新评估自己对该系统安全性的信任边界。这次的攻击者只是利用漏洞将 NAS 当作肉鸡对外攻击,更现实的担忧在于,若未来攻击直接针对数据本身,后果可能远比此次事件严重。我不希望遇上数据被病毒加密勒索的糟心事,不希望暴露 XP,更不想重新整理一遍动画片……

眼下 NAS 不在身边,我没法立刻更换系统,只能先决定即刻采取备份措施,避免后续出现任何数据安全意外。

但离了群晖的 Hyper Backup 和 Cloudsync 的助阵,有什么简单的方法,可以实现定时的增量备份,并将备份数据保存到云端呢?

这就需要请 Backrest 登场了。

关于

在介绍 Backrest 之前,有必要先引入一个几乎被所有备份方案反复提及的原则——「3-2-1 备份原则」。

所谓「3-2-1 原则」,是指在进行文件备份时,需要做到:

  • 3:至少保留 3 份完整的数据副本,防误删。例如:

    • 一份原始数据
    • 一份本地备份(同地 / 同机器)
    • 一份异地备份(云存储 / 异地 NAS)
  • 2:存储在 2 种不同的介质上,防硬盘损坏。例如:

    • 本地磁盘(机械硬盘、固态硬盘、光盘、磁带)
    • 云存储
  • 1:存储 1 份备份在异地,防勒索病毒、极端物理灾害。例如:

    • 异地 NAS
    • 云存储

在合理执行的前提下,可以最大限度降低数据丢失的风险。

可是,即便我们有意愿按「3-2-1 原则」执行备份,却需要面对另一个残酷的现实:如今机械硬盘的价格,已不是常人所能轻松负担的了。

8T机械硬盘
8T机械硬盘

我 2022 年 3 月购买的一块全新国行 8T 西数 HC320 的价格为 995 元。

但是!细心的小伙伴们应该已经注意到了,在「3-2-1 原则」的示例中,几乎每一步都可以将数据备份到「云存储」上。而云存储的价格,远比同等容量的硬盘便宜。

除了网盘,还有 COS、OSS、S3、B2 等一众云存储服务可供选择,价格都比购买实体硬盘要实惠,我们便可以考虑直接将数据备份到一个乃至多个不同的云端,以较低的成本满足「3-2-1 备份原则」的要求。

最终,我决定使用 Restic 作为我备份体系的核心。

Restic 是一款优秀的命令行备份工具,以快速、安全、高效著称。它支持:

  • 增量备份、数据去重和端到端加密,兼顾高效与安全
  • 多种主流存储后端,包括本地磁盘、网络共享目录(SMB/NFS)、远程服务器(SFTP/SSH)及各类对象存储(AWS S3、阿里云OSS、腾讯云COS等)、云存储服务(OpenStack Swift、Azure Blob Storage等)
  • 断点续传,备份中断后再次执行可从断点继续,无需重新开始
  • 任意快照点恢复(可恢复至某一次备份完整状态),也支持文件级精准恢复,恢复速度快且无需复杂配置,通过命令即可完成
  • 提供仓库校验命令,可定期检查备份数据块的完整性、修复损坏或丢失问题
  • 采用不可变仓库结构,备份过程中不修改已存储的历史数据块,避免历史备份损坏

但由于缺乏图形界面与调度管理功能,仍需配合脚本与 cron 实现自动化。对不想折腾这些东西的我来说,使用起来非常痛苦。

Backrest 正是在这一背景下登场的。作为一款专为简化 Restic 备份管理而设计的 Web UI 和编排工具,Backrest 通过直观的图形界面包装了 Restic 的命令行功能,并补齐了任务调度、状态监控与集中管理等关键功能,让复杂的 Restic 备份操作变得简单易行。

借助 Backrest,我们便能使用 Restic 实现一套可以长期稳定运行、也更容易被维护的备份方案。

准备

在正式开始之前,我们需要先思考一个很严肃的问题:

我们应该备份哪些数据?

备份并不是简单地把所有文件原封不动地复制一份。操作系统、软件包,甚至容器和镜像,本质上都属于可重建资源,只要环境还在,花一点时间就能重新部署。真正值得被长期保存的,是那些随着使用不断产生、积累,且一旦丢失就很难恢复的数据。

从实际使用场景来看,以下几类内容通常应当作为备份的重点:

  • 用户数据与业务数据
    例如文档、照片、媒体文件、项目资料,以及服务运行过程中产生的数据文件。这些内容往往具有唯一性,一旦丢失,几乎无法通过其他方式找回。
  • 服务与系统配置
    包括应用配置文件、服务参数、自定义脚本等。这些文件体积不大,却高度个性化。合理备份可以大幅降低系统重建时的时间成本。
  • 容器的持久化数据
    在使用 Docker 等容器化方案时,需要被备份的并不是容器本身,而是 Volume 或挂载目录中的数据。例如数据库文件、上传内容、状态数据等。
  • 高恢复成本数据

    例如游戏资源、音乐等。严格意义上说,这些文件并非完全不可再获取,但一旦涉及到命名规范、目录结构、封面整理和元数据获取,它们的恢复成本就不再只是「重新下载」那么简单。

相对应地,也有一些内容并不适合作为常规备份对象:

  • 操作系统本身
    系统可以重装,软件可以重新安装,将其纳入备份往往只会徒增体积和复杂度。
  • 缓存、临时文件和可再生成数据
    如构建产物、下载缓存、日志缓存等,这类数据即便丢失,恢复成本也相对较低。
  • 镜像、安装包等可从官方渠道重新获取的资源
  • 可下载的影音视频资源

通过这种取舍,将备份的重点从「尽可能多地保存数据」,转变为「只保存真正重要的那一部分」。不仅能有效控制备份体积和成本,也可以让后续的备份与恢复过程更加清晰、可控。

安装

这里以 Docker Compose 安装 Backrest 为例。

首先,需要在宿主机上创建好必要的数据文件夹,用于存放程序数据、配置、缓存和临时文件:

mkdir -p data config cache tmp rclone

随后新建 compose.yml 文件,填入以下内容:

services:
  backrest:
    image: garethgeorge/backrest:latest
    container_name: backrest
    hostname: backrest
    volumes:
    ## 程序数据文件夹
      - ./data:/data
      - ./config:/config
      - ./cache:/cache
      - ./tmp:/tmp
      - ./rclone:/root/.config/rclone # 挂载 rclone 配置(使用 rclone 远程时需要)
    ## 挂载本地备份路径
      - /vol1/1000/media:/vol1/1000/media
      - /volume2/docker:/volume2/docker:ro
    environment:
      - BACKREST_DATA=/data
      - BACKREST_CONFIG=/config/config.json
      - XDG_CACHE_HOME=/cache
      - TMPDIR=/tmp
      - TZ=Asia/Shanghai
    ports:
      - "9898:9898"
    restart: always

有几点需要注意:

  • 为避免后续误操作,建议挂载本地备份路径时直接使用宿主机原始路径
  • 对于只需备份、不需写入的目录,可适当设置只读 ro 权限(如上例 /volume2/docker)。
  • 如果使用远程存储(如 rclone 对接 S3 / COS / B2 等),记得提前在宿主机生成 rclone 配置文件,并挂载到容器内。
  • 端口 9898 用于访问 Backrest Web UI,如果通过反代访问,也可以不映射到宿主机。

设置

访问 IP:9898 启动 Backrest。Backrest 会根据浏览器语言自动切换显示语言,并弹出设置。你需要先为这台机器上启动的 Backrest 服务设置一个唯一的 实例ID,例如 my-nas ,用以区分多个 Backrest 服务。

接着,设置身份验证。如果你的 Backrest 只计划在内网中使用,那么可以不设置用户,并禁用身份验证。但如果是公开的服务,请务必设置好登录用户和高强度密码,并确保未勾选 禁用身份验证 选框,以启用身份验证功能。

鉴于公开服务可能带来的不可预测因素,建议即便是内网,也使用强密码认证身份,并在配置完毕后关闭 Backrest 服务的端口。

仓库

你应当尽可能自行阅读 backrest 官方指南 (英文) 以了解如何配置仓库,或者查看 Restic 文档 (英文) 了解更多有关仓库的信息。不过我也没看过,诶嘿

但本文演示时所使用的 Backrest 1.11.2 版本已原生支持中文界面,因此在实际配置过程中,基本可以做到无需额外查阅文档即可完成操作。

点击左侧的 「添加仓库」 按钮,新建一个 Restic 仓库。该仓库即为备份数据的最终存放位置,后续所有备份任务都可以将其作为统一的备份目的地。

仓库详情

首先,为其指定一个「仓库名称」。该名称仅用于 Backrest 内部识别不同存储库,例如区分本地仓库与云端仓库,本身并不影响实际的存储路径或数据结构。仓库名称创建后无法修改,因此建议在命名时保持清晰与可区分性。

而最关键的 「仓库 URI」,需要严格按照所选存储方式对应的 URI 格式填写。无论是本地路径、S3 对象存储,还是通过 rclone 访问的远程存储,只有格式正确,Backrest 才能成功连接并初始化仓库。

例如:

  • 本地存储库:/vol1/1000/backups/Restic
    使用本地磁盘或 NAS 上的目录作为仓库,适合作为第一层本地备份1
  • S3 / S3 兼容对象存储:s3:my-backup-bucket/Restic
    适用于 AWS S3 以及各类 S3 兼容服务(如 COS、OSS、MinIO 等)。
  • Backblaze B2:b2:my-b2-bucket/Restic
    以 B2 存储桶作为备份仓库,常见于低成本云端备份方案。
  • SFTP:sftp:user@example.com:/data/Restic-repo
    通过 SFTP 将备份数据存放到远程服务器的指定目录。
  • rclone 远程存储:rclone:remote-name:Restic
    通过 rclone 访问远程存储,其中 remote-namerclone config 中定义的远程名称,Restic 为仓库存放的子目录。

「仓库密码」 用于对 Restic 仓库中的所有数据进行加密。Restic 采用端到端加密设计,所有备份内容在写入存储库之前就已经完成加密,云端或远程存储只会保存加密后的数据本身。可以直接使用 Backrest 自动生成一段强度较高的随机密码,通常已满足安全需求。但如果有统一的密码管理策略,也可以自行指定符合习惯的密码。此外,Restic 也支持通过环境变量(如 Restic_PASSWORDRestic_PASSWORD_FILE 等)提供密码,方便在自动化或无交互环境中使用。

需要特别注意的是:该密码无法被找回或重置。一旦密码遗失,即使仓库文件仍然完整存在,也将无法再解密其中的任何数据。因此,应将仓库密码视为与数据本身同等重要,并妥善保存。建议使用密码管理器进行存储。

下方的 「自动解锁」 选项用于在执行清理(forget)和修剪(prune)操作前,自动处理仓库锁定文件。在单实例、单设备使用的情况下通常不会用到,但如果同一个仓库被多个设备或实例同时访问,开启该选项反而可能带来安全隐患,因此默认保持关闭即可。

参数变量

环境变量和命令参数(Environment & Flags)一节,本地仓库或通过 rclone 访问的常见云存储,大多数情况下可以留空。只有在使用对象存储、需要自定义认证方式,或对 Restic 行为有特殊需求时,才需要进行配置。

这里粘贴一段 AI 的见解,不一定准确。你可以在有需要时详尽地向 AI 发问、或阅读官方文档,并在正式将仓库投入使用前大量测试。

环境变量

用于向 Restic 传递环境变量,最常见的用途是:

  • 提供 对象存储的认证信息
    比如 S3、B2、Wasabi、MinIO 等
  • 设置 rclone 的运行环境变量
  • 或者传递一些 Restic 本身支持的高级参数

Backrest 会在执行 Restic 命令时,把这里填写的变量一并注入到运行环境中。常见示例包括:

  • S3 / 兼容对象存储

    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_DEFAULT_REGION
  • Backblaze B2

    • B2_ACCOUNT_ID
    • B2_ACCOUNT_KEY
  • Restic 通用

    • Restic_PASSWORD(仓库密码,不想写在仓库配置里的话)

另外一个比较实用的小细节是,这里 支持引用父进程中的环境变量,例如:

AWS_SECRET_ACCESS_KEY=${MY_AWS_KEY}

这在 Docker / systemd 环境中非常好用,可以把敏感信息只放在宿主环境里,而不是写死在 Backrest 配置中。

命令参数

对应的是 直接追加到 Restic 命令后的 flags,属于更偏高级/进阶的用法。适合以下场景:

  • 调整 Restic 的性能或行为
  • 解决网络不稳定、对象存储兼容性问题
  • 临时启用调试或特殊特性

常见例子有:

  • 限制并发、降低 IO 压力

    --limit-upload 20480
  • 指定缓存目录

    --cache-dir /data/Restic-cache
  • 某些 S3 兼容存储需要关闭 HTTP/2

    --option s3.disable-http2=true

这些参数 不会影响 Backrest 本身,只会在它调用 Restic 时生效。

定期修剪

日常执行备份时,Restic 的工作机制是:

  • backup:只往仓库里追加新数据块,从不删旧数据
  • snapshots:只是这些数据块的「索引」,方便按时间点恢复
  • forget:删除的是快照记录本身,不会立刻删除底层数据

还需配合 prune 来完成最后的空间回收工作。prune 意为修剪、精简,在 Restic 中,prune 用于删除不再使用的数据块。具体流程可以概括为:

  • 扫描整个仓库
  • 找出 不再被任何快照引用 的数据块
  • 删除这些数据块,并在必要时重新打包剩余数据以优化空间利用率

但由于 prune 需要遍历仓库索引,并对大量数据块进行读写、校验和重组,这一过程相对耗时且对存储 I/O 压力较大,尤其是在仓库规模已经不小、或使用对象存储的情况下更是如此。因此,Restic 官方文档并不建议在每次备份完成后都立刻执行 prune,而是推荐将其作为一项低频的维护任务,定期运行即可——例如每周一次,或每月执行一次清理。既能有效回收空间,又不会对日常备份造成额外负担。

Backrest 自然是将 prune 也做成了一个可视化的定时任务。

你只需要在初始化仓库时,完成三件事:

  1. 设置最大未使用比

    对应 Restic 的 --max-unused 参数,单位是百分比。

    顾名思义,这个数字代表允许仓库中未使用内容所占的最大百分比:

    • 数字越小:仓库残余无用数据块越少,但检索过程会更费时间、IO 占用也更高
    • 数字越大:清理动作更温和、更快,但仓库里会保留更多暂时用不到的数据块

    对个人 NAS 来说,保持默认的 10 一般已经足够。

  2. 选择 Schedule Type(何时执行)

    这决定 prune 自动运行的方式,有以下几种:

    • Disabled:禁用自动执行,只在手动点击「运行」时才会清理
    • Interval (Hours):每隔 N 小时跑一次
    • Interval (Days):每隔 N 天跑一次
    • Cron:使用标准 cron 表达式自定义时间点

    对个人 NAS 来说,更推荐选择 Interval (Days),每 7 天运行一次;或选择 Cron,设置每周/每月指定时间段(比如无人使用 NAS 的凌晨)运行。

  3. Cron Expression 与 Reference Clock

    当选择 Cron 时,会出现:

    • Cron Expression(Cron 表达式):

      • 界面里常见的 0 0 1 * *:表示「每月 1 日 0 点 0 分」
      • 想要「每周日凌晨 3 点」可以写 0 3 * * 0

      表达式可以直接询问 AI 获取。

    • Reference Clock(参考时间):

      • Local:按服务器本地时区
      • UTC:按 UTC
      • Last Run Time:多用于「间隔」调度,基于上一次实际运行的时间继续往后算

综合起来,一个相对通用、比较稳妥的配置是:

  • 最大未使用比:10(默认)
  • Schedule Type:Cron
  • Cron Expression:0 3 * * 0(每周日凌晨 3 点自动清理)
  • Reference Clock:Local

这样,Restic 就会在通常不怎么用机器的时候自动执行 prune,对仓库进行「垃圾回收 + 瘦身」。既不影响日常使用,又能长期把磁盘空间控制在一个相对合理的范围内。

数据验证

这一项对应的是 Restic 的 check 操作,用于验证仓库中数据的完整性

  • 验证数据占比
    这里填写的是一个百分比,用来控制每次检查时抽查多少数据

    • 100%:每次检查都会完整扫描并校验整个仓库,最安全,但耗时和带宽开销最大
    • 较小的数值(如 5%10%):只随机抽查一部分数据块,能在较低成本下发现大多数潜在问题

    对于已经稳定运行的仓库,一般不需要每次都全量校验,定期抽查即可;而在刚迁移仓库、存储后端不太可靠(比如部分对象存储)时,可以适当调高比例。

  • 调度方式(Schedule Type)
    可根据需求设置为 Interval 或 Cron。
  • Reference Clock
    用于指定调度时间的参考基准,也同上一环节的使用方法一致,一般保持默认。

高级设置

在大多数使用场景下,这一部分完全可以保持默认。Backrest 已经为常见环境选择了相对保守、稳定的配置,除非你对系统资源调度或自动化流程有明确需求,否则无需在这里折腾。

这里同样粘贴一段 AI 的见解,仅供参考。

高级设置可以为备份任务指定运行时的 IO 与 CPU 优先级,用于控制 Restic 在系统中的「存在感」。

硬件优先级

  • IO 优先级
    决定备份任务在磁盘读写层面的优先程度。
    默认的 IO_DEFAULT 表示不做额外干预,由操作系统自行调度。
  • CPU 优先级
    决定备份任务在 CPU 调度中的权重。
    CPU_DEFAULT 同样表示使用系统默认策略。

在以下场景中,这些选项才可能派上用场:

  • 备份任务与数据库、转码、下载等高 IO 负载服务共存
  • 希望备份「慢一点跑」,但不影响前台服务响应
  • 服务器性能有限,需要人为限制备份任务的资源占用

否则,保持默认,Restic 本身已经足够克制。

钩子

Hooks 用于在备份生命周期的特定阶段执行自定义脚本,例如:

  • 备份开始前 / 结束后执行脚本
  • 备份成功或失败时发送通知
  • 备份前暂停服务,结束后再恢复服务

典型使用场景包括:

  • 备份数据库前执行 dump
  • 备份完成后通过 Telegram / 邮件推送结果
  • prunecheck 前后执行清理或校验操作

对于只想安稳备份数据的用户来说,这一功能并非必需;但如果你有自动化流程需求,Hooks 提供了非常大的扩展空间。

配置示例

以创建一个本地仓库为例。

  • 仓库详情

    • 仓库名称:local
    • 仓库 URL:/vol1/1000/backup/mikusa
    • 密码:********(自动生成强密码)
    • 自动解锁:关闭(不选中选框)
  • Environment & Flags(参数变量)

    • 默认
  • Prune(定期修剪)

    • 最大未使用比:10(默认)
    • Schedule Type:Cron
    • Cron Expression:0 3 * * 0(每周日凌晨 3 点自动清理)
    • Reference Clock:Local
  • Check(数据校验)

    • 验证数据占比:10(视数据重要程度和体积而定)
    • Schedule Type:Cron
    • Cron Expression:0 2 1 * *(每月 1 日凌晨 2 点校验)
    • Reference Clock:Local
  • Advanced(高级设置)

    • 默认

计划

点击左侧的 「添加调度计划」 按钮,新建一个 Restic 计划。必须先配置好仓库,才能新建调度计划。

计划详情

这里需要注意的事项与创建 Restic 仓库时基本一致。例如,计划名称必须唯一,且创建后无法修改,主要用于区分不同的备份任务。此外,虽然可以直接选择已创建的仓库作为备份目标,但单个计划只能指定一个仓库;若需要同时备份至多个目标,则需分别创建多个计划。

不过,一个仓库是可以供多个备份计划使用的。在 Restic 中,多个备份计划共用一个仓库时,去重是以「数据内容」为单位进行的,而不是以「计划」或「路径」为单位。即使多个计划备份了相同的文件,这些文件的数据块在仓库中也只会存储一份。因此,即使不同计划备份了大量重叠数据,仓库体积也不会线性增长。

我一开始忽视了「数据去重」的含义,于是在同一存储库里按路径创建了很多仓库……

备份范围

你可以参考 Restic 文档 (英文) 了解更多信息。

  • 路径

    至少添加一个要备份的路径,可以是目录,也可以是文件。Restic 会把这些路径当作备份入口,在快照里保留原本的目录结构。路径也可以在界面中直接选择,避免手动输入错误。

  • 排除规则

    用来排除不需要备份的路径或文件模式,语法与 Restic 的 --exclude 相同。可以使用排除规则把缓存、临时文件、日志等剔出去,减小仓库体积、提升备份速度。

    例如:

    • *.tmp :排除所有临时文件
    • /home/*/.cache :排除用户缓存目录
    • /var/log :排除大量滚动日志

    这一栏是区分大小写的,在类 Unix 系统中需要特别注意这类问题。

  • 排除规则(不区分大小写)

    与上面类似,但匹配时不区分大小写,对 Windows 等环境更友好。比如填写 *.log 时,会同时匹配 .log, .LOG 等。

备份调度

视数据的重要程度,可手动、按每时/每天、或 Cron 设置备份频率,基本上与创建仓库 prune 时的原理一致,就不再赘述了。

如果没有特别复杂的需求,比较常见的配置是:

  • Schedule Type:Cron
  • Cron Expression:0 2 * * *(每天凌晨 2 点)
  • Reference Clock:Local
但这块的 UI 是不是有点问题?强迫症受不了。

保留策略

保留策略(Retention Policy)对应的是 Restic 的 forget 规则,用于控制旧快照的保留。

可选项有:

  • By Count:按数量保留,比如只保留最近 N 个快照。

  • By Time Period:按时间维度保留,是最常用、也最直观的一种。

    该模式下每个字段的意思是:

    • Hourly:每小时最多保留多少个快照
    • Daily:每天最多保留多少个快照
    • Weekly:每周最多保留多少个快照
    • Monthly:每月最多保留多少个快照
    • Yearly:每年最多保留多少个快照
    • Latest (Count):无论时间如何,始终至少保留最近 N 个快照

    因此,截图中示例的配置意为:

    • 小时级:最近 24 小时内,每个小时保留 1 个快照
    • 天级:最近 7 天内,每天至少保留 1 个快照
    • 周级:最近 4 周内,每周至少保留 1 个快照
    • 月级:最近 3 个月内,每月至少保留 1 个快照
    • 年级:不额外保留按年的快照
    • 最近:不额外强制保留「最近 N 个快照」,完全按上面的时间分组来决定
  • None:不做自动清理,所有快照都保留。适合短期测试,不推荐长期使用。

应该根据数据重要程度、存储空间和恢复需求调整保留策略,例如保留 7 天的日快照 + 6 个月的月快照就已足够日常使用。如果数据本就不是频繁备份,那么也就没必要设置太精细的策略。

高级设置

计划的「高级设置」也同仓库处一样,没有特殊需求的话可以保持默认

备份参数对应 Restic backup 命令的额外参数,用于调整备份行为或性能,例如:

  • --one-file-system:只备份当前文件系统,避免跨挂载点
  • --exclude-larger-than 500M:跳过超大文件
  • --compression max(Restic 0.16+):提高压缩等级,换取更小体积

脚本(Hooks)则可以在备份生命周期的不同阶段执行自定义脚本或通知,支持多种 hook 触发点(如 before-backup, after-backup, on-error 等),具体用法可以参考官方 hook 文档。例如:

  • 备份前暂停某个服务、锁库
  • 备份后重启服务
  • 发送任务状态通知

现版本的 Backrest 已原生支持 TG 通知,不用自行编写脚本。只需在 Hooks 处选择 Telegram、确定需要通知的环节,填入 Bot Token 和 Chat ID,再参考官方模板设置一下通知文本,就能知道备份有没有正常执行了。

我的模板如下:

📦 备份任务通知

任务名称:  .Task }}
执行时间(  .FormatTime .CurTime )
事件类型(  .EventName .Event )
仓库 ID(  .Repo.Id )
计划 ID(  .Plan.Id )

 if .Error -}}
❌ 任务执行失败

错误信息(
{{ .Error )

 else -}}
✅ 任务执行成功

{{ if .SnapshotStats -}}
📊 备份统计

• 新增数据( {{ .FormatSizeBytes .SnapshotStats.DataAdded )
• 处理文件数(  .SnapshotStats.TotalFilesProcessed )
• 处理数据量(  .FormatSizeBytes .SnapshotStats.TotalBytesProcessed )
• 执行耗时( {{ printf "%.1f" .SnapshotStats.TotalDuration ) 秒

{{ end -}}
{{ end }}

From Backrest 自动通知

效果大概是这样:

📦 备份任务通知

任务名称: backup for plan "book"
执行时间: 2026-02-18T23:40:39+08:00
事件类型: snapshot end
仓库 ID: baidupan
计划 ID: book

✅ 任务执行成功

📊 备份统计

• 新增数据: 0.000 B
• 处理文件数: 4865
• 处理数据量: 533.452 GB
• 执行耗时: 13.3 秒

From Backrest 自动通知

栗子

让我再举个更实际的例子:使用 openlist 挂载百度网盘,并用 rclone 连接 openlist 提供的 webdav 服务。

先获取个人用户 UID/GID:

# mikusa @ truenas in ~ [11:45:35]
$ id
uid=1000(mikusa) gid=3000(mikusa)

准备 .env 环境变量文件,置于 compose.yml 同级路径,填入基础的公共变量:

PUID=1000
PGID=3000
TZ=Asia/Shanghai

安装 openlist:

services:

  openlist:
    image: openlistteam/openlist:latest
    container_name: openlist
    user: ${PUID}:${PGID}
    ports:
      - 5244:5244
    volumes:
      - ./openlist:/opt/openlist/data
    environment:
      - UMASK=022
      - TZ=${TZ}
    restart: always

启动后,打开 openlist 添加百度网盘存储,设置挂载路径,如 /baidupan ,并填写刷新令牌。

刷新令牌需在官方的 OpenList Token 获取工具 获取,找到「百度网盘 (OAuth2) 验证登录」并勾选「使用 OpenList 提供的参数」,点击「获取 Token」,将底下的刷新令牌粘贴至 openlist 对应位置即可。

确认当前用户具备 Webdav 相应权限。

在终端中连接 NAS,进入 Backrest 容器内部命令环境:

docker exec -it backrest /bin/sh

使用 rclone config 新建 rclone 配置, 添加 WebDav 存储,所需的信息有:

  • name 名称: openlist
  • url 地址:http://openlist:5244/dav
  • vendor 提供商:other
  • 用户名 user:mikusa
  • password 密码:mikusa

具体流程这里不做演示。

创建完成后,rclone 对应映射文件夹内的 rclone.conf 文件应当有如下内容:

[openlist]
type = webdav
url = http://openlist:5244/dav
vendor = other
user = mikusa
pass = mikusamikusamikusamikusamikusamikusa
密码部分是自动加密的,因此会与真实密码看起来不太一样。

使用 rclone ls openlist:// 测试配置是否有误,如有输出即表示正常。例如:

/ # rclone ls openlist://baidupan/mikusa
8753641238 零售机_游戏性能大横评_2026.mp4
842538736 琉璃的宝石/AICL-4796~7.rar
829036840 琉璃的宝石/VVCL-2788~9.rar

接着,打开 backrest 创建 Restic 仓库。

假设网盘挂载路径为/baidupan,计划备份到 mikusa/Backup/truenas 内,那就在仓库 URI 一栏填入:

rclone:openlist://baidupan/mikusa/Backup/truenas

如果是多个计划使用同一个仓库,可以考虑勾选自动解锁,否则修剪任务可能会失败。

保存仓库、测试连接成功后,即可新建计划任务使用这个仓库。

你可以先备份一些小文件进行测试,并尝试恢复云端备份文件到本地。待确定一切正常后,再执行大批量备份。

由于上传的都是些经过加密的文件块,体积不大。实测备份约 2T 数据,暂未遇到上传限制问题(具体情况可能因账户与网络环境而异)。唯一可能需要担心的,便是宽带运营商是否会因持续大量的上传而限速了。

最后

以上便是我关于 Backrest 的全部心得了。不同于 Restic 只是一个纯粹的命令行工具,Backrest 本质上是一个常驻运行的 Web 服务,拥有完整的 HTTP 端口监听、用户认证与任务调度能力。为了读取所有需要备份的目录,它在 Docker 中往往需要较高权限,甚至直接挂载宿主机的大量路径。这意味着,一旦 Backrest 本身存在安全漏洞——无论是认证绕过、未授权访问,还是远程代码执行——攻击者能够触及的范围,便远不止备份数据本身。

当然,这并不意味着 Backrest 不值得使用。对于大多数家庭 NAS 场景而言,只要运行在内网环境中,做好基本的隔离与访问控制,风险通常是可以接受的。若你对安全边界有更严格的要求,那么直接使用 Restic + cron 的纯命令行方案,会是更简洁、也更克制的选择。

参考

本文在摸索时期参考了少数派对「3-2-1 原则」的《不想被勒索软件毁掉数据,就按照「3-2-1 原则」来备份文件》,刘一树的《服务器备份 - backrest + rclone + oss》,试验成功、再加上官方推出了中文界面后,便大量依赖 ChatGPT、Gemini、Doubao 等一系列人工智能的解释了。

因而本文 AI 含量较高,如有顾虑,酌情阅读。


  1. 第一层备份,是「多层备份架构」中的术语。指的是将数据备份到本地或同一网络中的存储设备,作为最基础的备份层级。这一层的核心特点是:备份速度最快、恢复时间最短、成本最低。它通常是备份计划中最频繁执行的一部分,主要应对日常误操作、硬盘故障、系统崩溃等常见风险。尽管第一层备份提供了较高的恢复速度,但并不具备防范物理灾害、勒索病毒或盗窃的能力,因此需要配合其他层级的备份(如异地备份)来确保数据的长期安全。