大家好,我是冯哥的缓存。上篇《文件同步与云备份——rclone 挂载网盘加密上传》里,我们用 rclone 把数据加密同步到网盘,解决了"限速 + 隐私"两个痛点。但rclone 有个天生的短板:它整份复制文件,不做去重。
想象一下:每天都要备份 100 GB 的"照片"目录,其中 99 GB 根本没变。rclone 每次要么全量重传(慢),要么靠"只传变化文件"省点事——但就算只传变化的,backup-2026-08-01、backup-2026-08-02… 几十个历史版本叠在一起,占的空间是线性增长的。存 30 天版本,就是 30 × 100 GB = 3 TB,谁顶得住?
BorgBackup(简称 Borg)就是为这个问题而生的。它把文件切成小块、只存"没出现过的内容",再用一份空间存下几十上百个历史版本,还能顺手加密压缩。一句话:rclone管"把文件送到云上",Borg 管"在本地/SSH 仓库里高效地存一堆版本"。两者正好互补。
💡两者不是"二选一"的关系。典型组合是:先 borg create在本地/SSH 仓库里存好去重加密的归档,再 rclone copy把整个仓库目录同步到网盘做异地第三份。Borg 负责"省空间地存版本",rclone 负责"把仓库送到云端"。
💡提示:本篇以 Linux 为主(服务器、NAS 最常见)。macOS 基本一致;Windows 没有官方原生 Borg 二进制,详见第 12 节,建议用 WSL2。命令在 Linux/macOS 上完全相同。
1. Borg 是什么
Borg 是一个去重(deduplication)+ 压缩(compression)+ 加密(encryption)三合一的命令行备份工具。它做对了一件事:把文件切成可变长度的内容块(chunk),相同的内容块在仓库里只存一次——跨文件、跨机器、跨年份都算。
能力 | 说明 | 带来的好处 |
去重 | 相同内容块只存一份 | 每天"全量备份"实际只多存变化量,几十个版本只占一份多空间 |
压缩 | lz4 / zstd / zlib / lzma 可选 | 文本、日志、代码进一步缩小 |
加密 | AES-256 + 认证,密钥在本地 | 仓库可以放在"不完全信任"的地方(别人只看到密文) |
挂载 | FUSE 把任意归档挂成目录 | 像翻文件夹一样浏览旧版本,直接拷出文件 |
增量 | 基于内容去重,天然增量 | 首次备份慢,之后飞快 |
⚠️核心认知: Borg 的"仓库(repository)"是一个目录(本地磁盘、移动硬盘、或 SSH 可达的远程机器上的目录)。仓库里存放若干个归档(archive),每个归档是一次备份的快照。去重发生在"仓库"层面——所有归档共享同一份内容块池。
2. 安装
Linux(发行版包,最省事)
# Debian / Ubuntu
sudo apt install borgbackup
# RHEL / Fedora / Rocky(先装 EPEL)
sudo dnf install epel-release
sudo dnf install borgbackup
# Arch
sudo pacman -S borg
发行版里的版本通常稍旧但稳定,够用。
想要最新版:pip
# 装最新稳定系列(Borg 1.4,截至撰写时 1.4.4)
pip install --user "borgbackup==1.4.4"
# 或装最新 1.4.x
pip install --user --upgrade borgbackup
💡提示:远程备份时,客户端和服务端的 Borg 版本要一致(或兼容),否则会报 incompatible API version。两边用同一种装法最稳。
macOS
brew install borgbackup
Windows:用 WSL2(推荐)
Borg 稳定版没有官方 Windows 原生二进制。最稳妥的做法是在 Windows 上开一个WSL2 的 Ubuntu,在 Linux 环境里跑 Borg,备份Windows 文件时把盘挂进 WSL(如 /mnt/c/Users/...)。
⚠️注意:通过 /mnt/c/备份 Windows 文件会经过 9P 文件系统桥,速度比直接备份 Linux 原生目录慢。如果量很大,考虑在 WSL 里专门建数据盘,或改用纯 Windows 备份工具。
💡性能提示:如果待备份数据量较大(>500 GB),可以在 Windows 磁盘管理里新建一个 VHDX 虚拟盘、挂载到 WSL2 作为独立的 ext4 数据盘,把待备份的数据放在里面,彻底避开 9P 桥的性能损耗,备份速度接近原生 Linux 目录。
国内适配:pip 镜像
pip 官方源在国内可能慢,换清华/阿里镜像:
pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple "borgbackup==1.4.4"
验证安装:
borg --version
# borg 1.4.4
3. 三个核心概念(先搞懂再看命令)
概念 | 是什么 | 类比 |
仓库 Repository | 存放所有备份的目录(一个去重池) | 一个"保险柜" |
归档 Archive | 某一次备份的快照,有名字 | 保险柜里的一格,贴了日期标签 |
密钥 Key + 密码 Passphrase | 加密/解密的钥匙 | 保险柜的锁芯 + 密码 |
💡提示:加密是在创建仓库时一次性定死的,之后既不能给现有仓库改加密模式,也不能给单个归档单独设。建仓库时选好,错了只能重建。
4. 初始化加密仓库
先建个目录,再borg init。加密模式决定"加不加密"和"密钥放哪"。
# 本地仓库(比如一块移动硬盘挂在这里)
exportBORG_REPO=/mnt/backup-hdd/borg-repo
mkdir -p "$BORG_REPO"
# 初始化,repokey 加密(推荐默认)
borg init --encryption=repokey "$BORG_REPO"
Borg 会设一个密码(passphrase),并提示导出密钥备份。
加密模式怎么选
💡一句话决策:大部分的用户直接选 repokey就够了。在考虑 keyfile或 none之前,先问自己一句:"我真的需要这个模式吗?"
模式 | 加密 | 密钥存放 | 适用场景 | 推荐度 |
repokey | AES-256 + HMAC | 仓库内(密码保护) | 大多数人的默认选择 | ⭐最常用 |
repokey-blake2 | BLAKE2b 替代 HMAC | 仓库内 | CPU 不支持 AES 指令集时更快 | ⭐备选 |
keyfile | AES-256 + HMAC | 本地 ~/.config/borg/keys/ | 仓库可能被偷,要"密钥+密码"双保险 | 高安全 |
keyfile-blake2 | BLAKE2b | 本地 | 同上且要更快 | 高安全 |
authenticated | 不加密,仅认证 | 仓库内 | 仓库本身已被磁盘加密,只想防篡改 | 特殊 |
authenticated-blake2 | 同上 BLAKE2b | 仓库内 | 同上 | 特殊 |
none | 无加密无认证 | — | 几乎不要用的兜底 | ❌ 不推荐 |
怎么选?
·拿不准就 repokey:密钥跟着仓库走,靠强密码保护,最省心。
·想要"仓库被偷也解不开":用 keyfile,密钥在本地,但密钥丢了就等于所有备份全废——所以 keyfile 模式必须离线备份密钥(见下)。
·repokey模式下也要备份密钥:虽然密钥在仓库里,但万一仓库损坏或想迁移,没有导出的密钥备份会很麻烦。
立刻导出并离线保存密钥
# 导出密钥到文件(存到完全独立的地方,如密码管理器或另一块盘)
borg key export"$BORG_REPO" ~/borg-key-backup.txt
# 想要可打印的纸质备份,加 --paper(输出适合手抄/打印的二维码+字符)
borg key export --paper "$BORG_REPO"~/borg-key-backup-paper.txt
# 权限收紧
chmod 600 ~/borg-key-backup.txt
⚠️铁律:没有"密钥 + 密码"二者,备份永久不可恢复。把密钥备份到和仓库不同的地方(密码管理器、另一块盘、纸上),别把密钥和仓库放同一个硬盘——那就等于把保险柜钥匙贴在柜门上。如果把密钥备份到同一个云盘(那个装着密文的云盘),加密同样白做了——密钥必须独立存放,呼应上篇 rclone 讲的"密钥与密文分离"原则。
5. 第一次备份
borg create创建归档。归档名支持 {hostname}、{now:%Y-%m-%d}等占位符,自动展开成带日期的名字。
export BORG_PASSPHRASE="强密码"# 自动化时用,平时可每次手输
borg create \
--stats --progress \
--compression zstd \
"$BORG_REPO"::{hostname}-{now:%Y-%m-%d_%H:%M} \
~/Documents \
~/Pictures \
~/Projects \
--exclude '*/.cache' \
--exclude '*/.git' \
--exclude '*.tmp'
参数 | 作用 |
--stats | 备份完显示原始/压缩/去重后大小对比 |
--progress | 实时进度条 |
--compression zstd | zstd 压缩(速度/体积平衡,推荐) |
--exclude | 排除匹配路径(可多次,支持 shell 通配) |
{hostname}-{now:...} | 归档名自动带主机名和日期 |
--stats的输出长这样(这是 Borg 官方示例的数字,建立直觉):
This archive:47.30 GB21.07 GB92.51 MB
All archives:892.07 GB412.86 GB29.74 GB
注意This archive那行:原始 47 GB,去重后只新增 92 MB——这就是去重的威力。第一次备份"全量"可能要传 47 GB,但之后每天的变化往往只有几十 MB。
6. 去重原理:为什么第二次这么快
Borg 用的是内容定义分块(Content-Defined Chunking, CDC):根据文件内容的边界(而非固定大小)来切分块。这样即使文件中间插入一段数据,大部分块仍保持不变、能命中已有的块——这正是去重高效的关键。
对比 | 整份复制(如 rclone 朴素 sync) | Borg 去重 |
第 1 天备份 | 存 8 个块 A~H | 存 8 个块 A~H |
第 2 天备份 | 又存一遍(或只传变的文件) | 只新增 1 个块 I,A~H 复用 |
第 3 天备份 | 再存一遍 | 只新增 1 个块 J |
三天三份"完整备份",实际只存了 10 个块,而不是 24 个。
💡提示:去重是整个仓库共享的。所以"每天做一次全量备份"在 Borg 里成本极低——尽管每次都指定整个目录,Borg 只存变化。不用纠结"全量还是增量",Borg 帮你想好了。
7. 查看 / 挂载 / 恢复
列出归档
borg list "$BORG_REPO"
# myhost-2026-08-01_23:00Mon, 2026-08-01 23:00:12
# myhost-2026-08-02_23:00Tue, 2026-08-02 23:00:09
挂载成文件夹(最直观的恢复方式)
# 需要fuse 包:sudo apt install fuse
mkdir -p /mnt/borg-restore
borg mount "$BORG_REPO"::myhost-2026-08-02_23:00 /mnt/borg-restore
# 现在/mnt/borg-restore 就是那次备份的完整目录树
# 用文件管理器/ cp 把要的文件拷出来
# 用完卸载
borg umount /mnt/borg-restore
# 个别系统用:fusermount -u /mnt/borg-restore
精准提取单个文件/目录
不想挂载整个归档,直接用extract:
# 只恢复某天的 Documents/report.docx 到当前目录
borg extract "$BORG_REPO"::myhost-2026-08-02_23:00 \
home/yourname/Documents/report.docx
# 恢复到指定目录
borg extract --destination /tmp/recover "$BORG_REPO"::myhost-2026-08-02_23:00 home/yourname/Pictures
💡提示:extract的"路径"是归档内的相对路径(去掉了开头的 /)。归档内的路径以 home/yourname/开头,而不是 /home/yourname/——Borg 在归档时去掉了前导斜杠。先用 borg list repo::archive path/to/dir看清内部结构再提取,避免路径写错。
8. 保留策略:prune(GFS)
备份越积越多,得定期清理旧归档。Borg 的prune直接支持 GFS(祖父-父亲-儿子)策略:
borg prune \
--stats \
--keep-daily7 \
--keep-weekly4 \
--keep-monthly6 \
--keep-yearly2 \
"$BORG_REPO"
含义:保留最近 7 天每天 1 份、最近4 周每周 1 份、最近 6 个月每月 1 份、最近 2 年每年1 份。
⚠️关键一步:prune之后,被删归档占的空间不会立刻释放——Borg 还要把"还有用的块"重新打包。必须再跑一次:
borg compact "$BORG_REPO"
compact才会真正腾出磁盘空间。建议把 prune和 compact写在同一个自动脚本里(下一节)。
⚠️注意:compact是相对耗时的操作(需要重写索引),建议在备份窗口之外执行,或安排在周末夜间等低峰时段运行,避免和正常备份抢 I/O。
9. 自动化:定时备份
方案 A:cron(传统,所有 Linux 都有)
写个脚本/usr/local/bin/borg-backup.sh:
#!/bin/bash
set -euo pipefail
export BORG_REPO="/mnt/backup-hdd/borg-repo"
export BORG_PASSPHRASE="强密码"# 也可用文件读取,见下方提示
# 创建备份
borg create \
--stats --compression zstd \
"$BORG_REPO"::{hostname}-{now:%Y-%m-%d_%H:%M} \
/home /etc /var/www \
--exclude '/home/*/.cache' \
--exclude '/home/*/.local/share/Trash' \
--exclude '*.tmp'
# 清理旧备份并释放空间
borg prune --stats --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --keep-yearly 2 "$BORG_REPO"
borg compact "$BORG_REPO"
echo"=== Borg 备份完成 $(date) ==="
chmod +x /usr/local/bin/borg-backup.sh
# 每天凌晨 3 点执行(crontab -e)
0 3 * * * /usr/local/bin/borg-backup.sh >> /var/log/borg-backup.log 2>&1
💡提示:把密码明文写在脚本里不安全。更稳妥:把密码存到权限 600 的文件,脚本里 export BORG_PASSPHRASE="$(cat /root/.borg-passphrase)";或配合 systemd 的 EnvironmentFile=。
方案 B:systemd timer(现代发行版推荐)
/etc/systemd/system/borg-backup.service:
[Unit]
Description=BorgBackup
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/borg-backup.sh
Environment=BORG_PASSPHRASE=强密码
/etc/systemd/system/borg-backup.timer:
[Unit]
Description=Run BorgBackup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl enable --now borg-backup.timer
10. 远程备份:把仓库放另一台机器
Borg 通过 SSH 备份到远程机器,远程永远只看到密文——密码和明文文件不经过网络明文传输。
# 初始化远程仓库(ssh 短写法)
borg init --encryption=repokey user@backup-server:/path/to/borg-repo
# 或标准 ssh:// 写法(指定端口)
borg init --encryption=repokey ssh://user@backup-server:22/path/to/borg-repo
# 备份到远程
borg create --stats --compression zstd \ user@backup-server:/path/to/borg-repo::{hostname}-{now:%Y-%m-%d} \ ~/Documents ~/Pictures
远程防篡改:append-only 模式
如果不信任远程机器(或怕备份源被黑后删光历史),创建仓库时加--append-only:
borg init --encryption=repokey --append-only user@backup-server:/path/to/borg-repo
这样远程端不能删除/修改已有归档,即使备份源被攻陷,历史版本也还在。
⚠️关键澄清: append-only不只是挡 delete,连 prune、compact也会在服务端被拒绝(它们都是"收缩仓库"的操作)。所以仓库会持续增长,直到你用另一个受信任的运维身份——一个不带 --append-only限制的 SSH 密钥(只握在管理员手里、不在被备份的机器上)——去执行 prune + compact释放空间。append-only 的价值是:即使备份源被攻陷,攻击者也只能往仓库里塞数据,删不掉你的历史。它不是"什么都不管"的万能锁,真正的防线是"删除权限只在另一台你信得过的机器上"。
专业 Borg 托管(开箱即用)
如果不想自己维护备份服务器,有几个对 Borg 友好的托管:
服务 | 特点 |
BorgBase | 专为 Borg 设计,免费额度 + 付费,内置 append-only、监控 |
Hetzner Storage Box | 德国主机商,便宜大碗,支持 Borg over SSH |
rsync.net | 老牌云存储,支持 Borg |
⚠️国内适配:这些托管多在海外,首次上传大仓库可能慢。国内机器之间互备用 SSH 最稳;跨国际备份建议先用小仓库试速度。
11. 进阶工具(不想记命令的看这里)
工具 | 是什么 | 适合谁 |
Vorta | Borg 的官方图形界面(Qt) | 桌面用户,点点鼠标就能备份/恢复 |
Borgmatic | 用 YAML 配置文件驱动 Borg(含 prune、数据库钩子、监控) | 服务器自动化、想"一份配置管所有" |
borg benchmark cpu | 测本机 CPU 加解密/哈希速度 | 纠结选 aes 还是 blake2 时 |
💡提示: Borgmatic 还能在备份前后执行钩子(hooks),比如先 pg_dump / mysqldump把数据库转储出来、临时停服务,备份完再启动。对生产环境特别有用——数据库不能只靠文件级备份,钩子能保证备份的是一致的状态。
Borgmatic 配置示例(/etc/borgmatic.d/config.yaml节选):
location:
source_directories:
-/home
-/etc
-/var/www
repositories:
-user@backup-server:/path/to/borg-repo
retention:
keep_daily:7
keep_weekly:4
keep_monthly:6
keep_yearly:2
compression:zstd
encryption_passphrase:"强密码"
然后borgmatic一条命令完成"创建 + 清理 + 压缩"。
12. 国内适配小结
场景 | 建议 |
安装 | apt/dnf直接装;要最新用 pip(配清华/阿里镜像) |
Windows 用户 | 用WSL2跑 Borg,备份文件走 /mnt/c/... |
远程备份 | 国内机器间用 SSH 互备最稳;海外托管先试速度 |
大仓库首次上传 | 去重仓库首次要传全量,建议放后台或限速避开高峰期 |
加密 | 默认 repokey + 导出密钥离线保存,够绝大多数人 |
13. 常见坑(10 条速查)
坑 | 现象 / 原因 | 对策 |
忘记备份密钥 | 仓库损坏后无法恢复 | borg key export离线存一份 |
密码忘了 | 加密仓库永久打不开 | 用密码管理器记强密码 |
prune 后空间没少 | 没跑 compact | prune 后必跑 borg compact |
远程版本不一致 | incompatible API version | 客户端服务端装同版本 |
备份 /mnt/c很慢 | WSL 9P 桥开销 | 尽量备份 WSL 内原生目录 |
exclude 不生效 | 路径写法不对 | 先用 --dry-run --list看实际包含/排除 |
归档名路径错 | extract 提示找不到 | 先 borg list repo::archive 目录看结构 |
fuse 没装 | borg mount报错 | sudo apt install fuse |
仓库满了 | 没设配额、没 prune | 加 --storage-quota或定期 prune+compact |
明文密码在脚本 | 安全隐患 | 用 600 权限密码文件或 EnvironmentFile |
14. 小结
Borg 解决了 rclone 搞不定的问题——用一份空间存几十个完整历史版本。它的三板斧是:
1.去重:相同内容只存一次,每天"全量备份"实际只多存变化;
2.压缩:zstd 平衡速度与体积;
3.加密:仓库可放"不完全信任"的地方,远程只见密文。
配合 3-2-1 原则,一个典型方案是:本地 Borg 仓库(第 1 份)+ 移动硬盘 Borg 仓库(第 2 份,另一种介质)+ 远程 SSH Borg 仓库(第 3 份,异地),三份都是去重加密的,空间占用极小。
💡提示:备份的价值在"能恢复"。"没验证过的备份等于没备份"——定期 borg mount挂出来、或 borg extract抽一个文件验证,是必须的。也可以 borg check "$BORG_REPO"校验仓库完整性。
下篇预告:《Linux 系统快照与还原——Timeshift 与 Btrfs 快照回退》,换一个思路:不备份文件,而是给"整个系统状态"拍快照,系统崩了直接回退到昨天。