by wzyboy on 2017-12-17
生活在电子时代,人们每天都在产生数据。写过的文字,拍过的照片,收集过的网络内容,都是数据。对于程序员们来说,写过的代码,服务器的数据库、日志等,也都是数据。然而硬盘故障、服务器宕机等灾害却随时都有可能危害数据的安全。所以数据需要备份。正如某程序员的语录:
冗余不做,日子甭过;备份不做,十恶不赦!
本文介绍一款优秀的备份方案:BorgBackup。
BorgBackup 的主要优势(总结自官方文档):
目前 BorgBackup 是我 Linux 的笔记本及工作电脑、Windows 游戏机、以及所有 Linux 服务器的所采用的备份方案,已稳定运行数月,十分优秀。
BorgBackup 由 Python + C 写成。你可以直接从源代码编译,从 PyPI 安装,也可以从发行版仓库中安装。BorgBackup 的 1.1.x 分支相比 1.0.x 分支增加了很多有用的新功能和性能提升,建议使用 1.1.x。
最方便的安装方式是——不用安装。BorgBackup 官方提供了使用 PyInstaller 制作的单文件程序,包含了 Python 3 解释器及所有依赖,可以直接运行于各平台上,十分适合批量部署于服务器集群之中,免除编译安装各种依赖之痛苦。
推荐一款 BorgBackup 的 GUI: Borg-BackUP-GUI,适合不喜欢命令行操作的用户。
另一款 BorgBackup 的 GUI:Vorta。
BorgBackup 的备份由 repo 和 archive 的概念,类似于 Git 的 repo 和 commit 的关系。同一个 BorgBackup repo 里的各 archive 之间互相去重,同一份数据只会被备份一次:
# 初始化一个名为 my-backup-repo 的 repo $ borg init -e repokey my-backup-repo Enter new passphrase: Enter same passphrase again: Do you want your passphrase to be displayed for verification? [yN]: n # 创建一个 archive-1 的 archive,内含 Music 目录 $ du -sh ~/Music/ 2.2G /home/wzyboy/Music/ $ borg create my-backup-repo::archive-1 ~/Music Enter passphrase for key /home/wzyboy/tmp/my-backup-repo: # 可以看到整个 repo 的大小与 Music 目录一致 $ du -sh my-backup-repo 2.2G my-backup-repo # 创建一个 archive-2 的 archive,内含 Music 和 Desktop 目录 $ du -sh ~/Desktop 170M /home/wzyboy/Desktop $ borg create my-backup-repo::archive-2 ~/Music ~/Desktop Enter passphrase for key /home/wzyboy/tmp/my-backup-repo: $ borg list my-backup-repo Enter passphrase for key /home/wzyboy/tmp/my-backup-repo: archive-1 Sun, 2017-12-17 18:10:58 [af49569db9cc4899ea99e59f54581e5321fd2d800357a21ad1b6f09ec36f6f32] archive-2 Sun, 2017-12-17 18:12:27 [734a9776b60b46896b17d62fbc01dc37b256dba7afb14050226f2e9c193f43bf] # 由于 Music 目录里的数据在 archive-1 里已经有了,所以 archive-2 创建之后整个 repo 的大小只增长了 Desktop 的大小 $ du -sh my-backup-repo/ 2.4G my-backup-repo/ # 从 repo 中移除 archive。只有当所有 archive 都不再包含某数据块的内容时,该数据块才会被真正从 repo 中移除并释放磁盘空间 $ borg delete my-backup-repo::archive-1 Enter passphrase for key /home/wzyboy/tmp/my-backup-repo: $ borg list my-backup-repo Enter passphrase for key /home/wzyboy/tmp/my-backup-repo: archive-2 Sun, 2017-12-17 18:12:27 [734a9776b60b46896b17d62fbc01dc37b256dba7afb14050226f2e9c193f43bf]
更多 borg
命令的参数可通过 borg -h
查看。
以上命令中 repo 的地址为 my-backup-repo
,这是当前目录下的一个目录,如果你好奇地进去看一眼,会发现里面主要是一堆以数字命名的目录和文件,每个文件大小都差不多。这就是你备份的数据,去重、压缩、加密之后被切碎了放在那里的。
一个本地磁盘上备份目录是没有什么意义的,本地磁盘挂了,数据和备份数据就全部没有了。BorgBackup 原生支持基于 SSH 的远端 repo,其格式和 Git / rsync 有几分相似:username@hostname:/path/to/repo::archive-1
。以上命令中的所有本地 repo 都可以直接换成远端 repo 写法。这样的远端 repo 是通过 SSH 访问的,所以安全性和 SSH 是一样的。使用远端 repo 需要远端机器上已经装有 BorgBackup,正如使用 rsync 需要远端机器上已经装有 rsync 一样。
如果不方便在远端机器上安装 BorgBackup,可以使用 NFS / SSHFS / Samba 等各种网络文件系统把远端机器的磁盘映射到本地,然后用本地 repo 的方式访问,达到异地备份的效果。
BorgBackup 是没有配置文件的,所有配置项都是在运行的时候通过命令行参数或是环境变量来改变。当你在命令行里把 borg
的各种参数把玩熟悉之后,就可以把它们拼成一个自动化脚本丢给 cron 或是 systemd timer 定期执行了。
对于像我一样不想维护一个脆弱的 shell 脚本的人来说,可以使用第三方项目 Borgmatic。它通过 YAML 配置文件声明 BorgBackup 备份设置,然后拼装好 BorgBackup 命令来运行,并且它有完善的错误处理和钩子机制,方便发送备份成功的通知或备份失败的报警。
我写了一个 Ansible Playbook,可用于一条龙完成 BorgBackup + borgmatic + systemd timer + authorized_keys 的配置。这个 Ansible Playbook 会做以下事情:
/usr/local/bin/
里;/opt/borgmatic/
里;/etc/systemd/system/
里放一个 systemd timer,在每天 00:00-02:00 中随机一个时间点跑备份;-e borg_setup_pubkey=True
,则会额外把备份源机器的 SSH 公钥安装到备份目标机器上。整个 Playbook 是幂等的,安全无毒副作用。
BorgBackup 的加密有 repokey 和 keyfile 两种模式。前者是把 key 存储在 repo 目录里,用 passphrase 加密起来,而 passphrase 由你记忆,后者则是把 key 存储在 repo 外面。如果你对备份宿主的掌控力不足,可以考虑使用后者,当然,后者的风险就是这个 keyfile 本身也需要备份,产生了鸡生蛋与蛋生鸡的问题。
BorgBackup 也支持对 repo 进行压缩后存储。如果你的数据大部分都是可压缩的类型,开启一个快速的 LZ4 压缩能节省不少空间;如果你的数据都是照片、视频等不可压缩类型,压缩就没什么必要了。1.1.x 分支的 BorgBackup 提供了 -C auto,lz4
这样的选项,可以自动判断数据是否属于可压缩类型。
BorgBackup 的远端 repo 模式,因为有加密和校验,所以并不需要客户端去信任服务端,所以你不需要自己去准备服务端,完全可以买别人提供的 BorgBackup 宿主服务。著名备份方案提供商 rsync.net (是的,就是 rsync 这个软件的商业公司)就为 BorgBackup 用户提供了折扣价。25 GiB 存储空间,一年的价格仅 9 USD。你得到的是一个可以已经预装了 BorgBackup 的 SSH 账号。目前我自己的各 VPS 就是备份到 rsync.net 的。
rsync.net 的 SSH 账号是个受限账号,只能运行 borg1
, rsync
等少量命令(注:rsync.net 的服务器上 borg
是 BorgBackup 0.x,使用时注意设置 --remote-path borg1
),因此我的 Ansible Playbook 中对 rsync.net 的备份宿主做了特殊支持,用专门的方法来安装 SSH 公钥。
另一种思路是去购买「存储型 VPS」,这种机器一般是 OpenVZ 架构,CPU 和 RAM 配置都很差,但是会挂载一个巨大的磁盘,价格上比较划算。在这个 GitHub issue 里可以看到大家对这些 VPS 商家的讨论。
如前文所说,BorgBackup 的 repo 目录里是一堆切碎的数据文件,以数字命名。这个数字文件名是单调递增的,不会重复,并且 BorgBackup 在备份过程中,只会创建或删除整个文件,不会对已有的文件进行修改。这样的特性非常适合对象存储。因此除了上面两种方法,也可以考虑将 BorgBackup repo 用 rclone 同步到 Amazon S3, BackBlaze B2 等各种对象存储。
更新:将 Synology DiskStation 作为备份宿主。
更新:除 rsync.net 外,有个专门托管 BorgBackup 的网站看起来也不错:BorgBase。可以通过网页方便地管理 ACL 和 2FA。
备份和存储提供商 BackBlaze 提出过一个 3-2-1 原则,指:
在使用 BorgBackup 备份时也可以考虑这样的原则。比如我笔记本电脑上的数据会通过 BorgBackup 备份到 NAS 上,而 NAS 上的 BorgBackup repo 会用 rclone 整体备份到 BackBlaze B2 对象存储。这就满足了 3-2-1 原则。当我的笔记本电脑损坏时,我可以快速从家庭 NAS 中恢复数据到新电脑上,当因为火灾、地震、洪水等原因笔记本电脑和 NAS 一起坏了,我可以从 B2 异地恢复数据。rclone 支持把一个对象存储用 FUSE 挂载,因此从异地恢复时不需要把所有数据下载下来,只需要挂载之后用 BorgBackup 去读取 FUSE 即可按需恢复。
BorgBackup 提供了自动留存算法。通过 borg prune
命令,BorgBackup 可以按照特定的规则自动移除旧的 archive。比如对于一个每天备份的 repo 可以设置这样的 prune 规则:
这样既可以达到最大留存时间,又相对节省备份空间。这些设置自然也是可以在 Borgmatic 中配置的。
这是本周写的第三篇博客了。一年多没写博客的我,在迁移完博客之后突然就变得高产了。今天早上在观察 Nginx 日志时(想看看有没有漏迁移而坏掉的永久链接),突然有三条连续日志引起了我的注意:
223.89.xx.xx - - [17/Dec/2017:03:31:04 +0000] "GET /post/1092.html HTTP/1.1" 200 19615 "https://www.inoreader.com/" "Amazon CloudFront" 223.89.xx.xx - - [17/Dec/2017:03:31:05 +0000] "GET /static/css/style.css?h=48644d84 HTTP/1.1" 200 467 "https://wzyboy.im/post/1092.html" "Amazon CloudFront" 223.89.xx.xx - - [17/Dec/2017:03:31:06 +0000] "GET /static/css/bootstrap.min.css HTTP/1.1" 200 121200 "https://wzyboy.im/post/1092.html" "Amazon CloudFront"
天哪,一个活的订阅用户,打开了我昨天刚发布新博客文章!明明已经一年多没更新过博客了,居然还有用户在订阅着。更重要的是,居然还有用户在使用 RSS / Atom 阅读器。这让我非常感动,觉得还是应该多写博客,有什么想法要整理成文字,不能闷在大脑里消散掉或是倒进日记里沉底。
那么,欢迎大家订阅本博客的 Atom Feed: https://wzyboy.im/feed.xml
最后,祝大家常做备份,远离数据丢失。