跳转至

异地与恢复

重建后异地副本会等待

当第 4 步在没有旧设置的情况下重建条目时,这些域的异地复制会暂停,直到存放位置默认值被确认。参见每个项目的存放位置。

本地备份保护您免受容器丢失或错误更新之苦。异地复制和经过测试的恢复工具包保护您免受整台机器损失、勒索软件或火灾之害。本页涵盖异地复制、使该副本防篡改、证明您能够还原,以及在 BombVault 本身消失时进行恢复。

异地复制

保留快速的本地备份,再添加一个或多个异地副本。在设置,异地页面为每个域设置一个仓库。BombVault 以尽力而为的方式用 restic copy 将新快照复制到那里,因此异地出现问题绝不会导致本地备份失败。在这种形态下,本地仓库是主仓库,异地仓库是副本;但一个域的主仓库完全不必是本地的,如果想直接备份到 S3/rest-server 等而不是复制过去,参见下文的远程主仓库。

  • 每个域可有多个异地目标。 每个域(容器、虚拟机、闪存、配置、文件集和 ZFS 数据集)都可以同时复制到多个异地目标,而不仅仅是一个,因此您可以并行地保留,例如,一台朋友机器上的 rest-server 和一个 S3 存储桶。在设置,异地添加额外目标,每个目标都有各自的仓库、S3 存储类别、append-only 标志、保留和增长预算。一个现有的单一异地设置会作为第一个目标原封不动地沿用下来,而一个域的每个目标都按该域的异地计划复制。
  • 按域的异地计划(与设置,计划上的其他所有计划一起编辑):留空则在每次本地备份后复制,或设置一个周期(例如 weekly Sun 03:00)以比本地备份更不频繁地发送到异地。一个立即复制按钮涵盖按需运行。
  • 异地保留位于设置,保留,因此您可以将异地副本作为归档保留更久。将策略全部留为零则从不自动清理异地快照。
  • 带宽限制(设置,异地)限制 restic 的上传/下载速率,使复制不会占满您的 WAN。
  • 一个复制指示器在运行时显示哪个域正在复制(在其页面和仪表板上)。它是一个活动指示器,而非百分比条,因为 restic copy 不暴露机器可读的进度。

从任意位置还原

每个容器、虚拟机、文件集、闪存和应用配置,都会把它们的备份列成一条时间线,覆盖备份所在的所有位置。复制到 B2 的备份只会出现一次,标注上持有它的每个位置。还原会取用能够到达的第一个位置,从该项目写入的仓库开始,您也可以按行另选一个位置。异地位置只在您打开时才会读取。在某一处删除会先检查其他位置,并说明这是否是最后一份副本。

目标

设置、异地 以目标开头:异地副本去往的位置,为所有域一次性设置。之后,一个目标会作为按钮出现在每个域和每个项目的存放位置行中。它第一次被某个域勾选时,BombVault 会在它下面的一个文件夹里创建该域的仓库,例如 rclone:onedrive:BombVault/containers。闪存、自我备份和 ZFS 数据集没有存放位置行,因此它们的异地部分改为提供 从 目标名称 添加。

添加目标会打开一个五步向导:

  1. 备份应存放到哪里? 每个服务都带着标志列出,分为四组:提供 S3 存储桶的存储服务(Backblaze B2、Wasabi、Cloudflare R2、Hetzner Object Storage、Amazon S3 等)、您自己的 S3 服务器(Garage、SeaweedFS、RustFS、Silo、Ceph、JuiceFS、Versity S3 Gateway)、您自己的服务器和共享(rest-server、Hetzner Storage Box、SFTP、SMB、WebDAV、已挂载的路径)以及云存储(OneDrive、Google Drive、Dropbox、pCloud、Nextcloud 和 rclone 支持的其余服务)。每个服务都会说明它有多适合备份:请求很多时云盘会变慢,所以首次备份和修剪在那里要花更长时间。
  2. 登录 所选服务。需要填写的字段取决于服务:S3 用访问密钥,WebDAV 和 SMB 用用户名和密码,两步验证挡住普通密码时用应用专用密码,SFTP 和 Storage Box 用 BombVault 的公开 SSH 密钥,通过浏览器登录的服务则用令牌。对这类服务,向导会显示一条 rclone authorize 命令,供您在有浏览器的电脑上运行;它打印出的令牌填入该字段。测试连接会在保存任何内容之前检查登录。
  3. 选择文件夹。 向导会列出目标上的文件夹,新建文件夹可创建一个,服务有上报时还会显示可用空间。空文件夹最安全。
  4. 防删除保护。 向导会直说服务能做什么。append-only 模式的 rest-server 会拒绝删除,篡改测试会检查这一点。S3 存储桶可以通过版本控制和对象锁保留旧版本,BombVault 目前还无法检查这一点。云盘完全无法拒绝删除:谁进入服务器,谁就也能进入那份副本。只有在远端确实拒绝删除时才打开不可变(append-only);之后 BombVault 绝不会在那里修剪。
  5. 应对紧急情况。 恢复工具包会列出每个目标,以及其下每个域的仓库。登录信息随 BombVault 的设置备份一起恢复;在没有它的全新安装上,请在同一位置重新设置该目标。

S3 服务通过 restic 自带的 S3 后端运行,存储类别和对象锁因此可以生效。其他所有服务都通过 BombVault 自带的 rclone 运行,它的 remote 随后会出现在 设置、云访问 下的 rclone 配置中。设置导出包含这些目标;包含凭据时,也会包含它们的登录信息。

您的组中其他实例运行的接收服务器会出现在向导的来自你的组下;参见接收服务器。

由某个目标创建的域目标,会沿用该目标的名称、位置、凭据、存储类别和不可变开关。它的保留策略、压缩和增长预算仍按域设置,其位置无法移动,因为该域的仓库就在那里。每个域下的仅为此域添加目标仍然接受手动输入的仓库 URL。

手动输入的目标,如果其仓库位于某个目标的文件夹内,就可以加入该目标。目标会把这类目标列在已在此目标下之下,接管则把其中一个挂到它下面。被接管的目标保留自己的仓库、快照、保留策略和存放位置,并沿用该目标的名称、凭据、存储类别和不可变开关。BombVault 会先检查该目标的登录能否打开仓库,并拒绝把 append-only 目标放到不是 append-only 的目标之下。接管某个域的主目标,会清空该域的 off-site 字段。

每个项目的存放位置

每张容器、虚拟机和文件集卡片都有一行按钮式的存放位置:本地,以及该域每个异地目标各一个按钮,后面是该域在其下还没有目标的那些目标。亮起的按钮会获得该项目的备份。

  • 本地亮起时,项目写入存放于下所示的仓库,并复制到其他每个亮起的目标。把某个目标熄灭,它就不会再从这个项目获得任何新内容。只有本地时不复制到任何地方,适合已有第二份副本的数据,例如一个本就在 NAS 上的共享。
  • 本地熄灭时,项目直接写入第一个亮起目标的直接仓库,并从那里复制到其他亮起的目标。第一次时,会有一个对话框创建该直接仓库。
  • 点击某个目标的按钮,会在该目标下创建该域的目标,并仅为这个项目点亮它。其他每个项目起初在那里都没有副本。
  • 总有一个按钮保持亮起,因为备份需要一个去处。要把某个内容排除在备份之外,请将其排除。

位置从项目的首次备份起固定,因为 BombVault 绝不会在仓库之间搬动备份。副本则可以随时更改。不再获得某个项目的目标会保留它已有的副本,并在该域下一次异地运行时按自己的保留策略精简;卡片上的在 B2 删除会立即移除它们。当其中一些副本在别处都不存在时,确认框会按日期列出它们,并要求输入项目名称。无法从 append-only 目标中删除任何内容。

这一行下面,卡片会说明项目去向何处、实际存放在哪里:有多少个站点持有它、每个目标最后一次被看到是什么时候,以及是否满足 3-2-1。站点是指拥有原始数据的服务器、每个异地目标,以及每个标记为场外的仓库。BombVault 检查副本和站点;它不检查 3-2-1 中"两种介质"的部分。

存放位置默认值

设置、存储、存放位置默认值 为每个域提供一行,按钮与上面相同。副本会立即应用于每个没有自己选择的项目,以及 Compose 堆栈的项目文件夹。位置在新项目首次备份时生效;更改它不会移动任何备份。保存前,该行会列出每个将获得或失去项目的目标,以及这意味着多少个快照。应用于没有备份的项目 会把每个尚无备份的项目都恢复为默认值。

一个新的异地目标会接收所有未设为本地的项目。添加它的对话框会说明有多少个项目,以及在已知的情况下这意味着多少历史数据,并提供选项以排除已从其他目标中排除的项目。

直接仓库

为某个项目关闭本地,使一个没有直接仓库的目标成为它的归宿,会打开一个对话框,其中在该目标旁给出建议位置,例如 s3:https://s3.eu-central-003.backblazeb2.com/bucket/containers-direct,以及一次不会创建任何东西的连接测试。创建并使用 会创建该仓库并把项目指向它。直接仓库沿用目标的密钥、存储类别、限制、append-only 设置和保留策略,并随之变化;存储库卡片会将它显示为只读。当目标的新密钥无法打开它时,直接仓库会保留自己现有的密钥,并在保存时说明这一点。位于直接仓库上的项目会从那里复制到其他亮起的目标,绝不会复制到该仓库所属的目标。它的快照带有标签 bv:direct,其他每一次修剪都会保留它们,因此一个与目标失去关联的直接仓库绝不会按本地规则老化。B2 通过其 S3 端点访问,将密钥 ID 和应用程序密钥作为 S3 凭据输入;限定在目标自身文件夹的密钥无法到达它旁边的文件夹,因此应把密钥限定在目标上一级的文件夹。

场外

已命名的仓库可以在存储库卡片上标记为场外。远程仓库默认就是已标记的;对同一栋楼里的 rest-server 应关闭它。该标记只在卡片上计入站点数和 3-2-1,不会改变任何副本。

重建之后

复制选择保存在 BombVault 自身的设置中。在没有恢复 /config 的情况下通过 发现备份 重建之后,这些选择会消失,而全部复制又会把您原本排除在外的项目重新发送到 B2。因此每个被重建域的异地复制都会暂停。仪表板会以琥珀色显示这一点,存放位置默认值会提供确认默认值,附带下次运行将复制的内容预览,以及备份中没有对应条目的名称,您可以在那里将其排除。只有确认才能结束暂停;导入设置文件会带回规则和默认值,但不会结束暂停。

远程主仓库

域的备份路径(设置、存储)并不限于本地文件夹:直接把它指向一个 restic 远端(s3:...、rest:http://host:8000/repo、sftp:user@host:/repo、rclone:remote:bucket/path),BombVault 就会直接备份到那里,既没有另一份本地副本,也没有复制步骤。这与上面的异地复制是真正不同的形态:那里本地仓库是主,异地仓库是它的尽力而为的存档;这里远程仓库 本身就是 主,而且在你没有为该域另行配置异地复制(或第二个远端)之前,它就是唯一的一份。

六个路径字段(容器、虚拟机、闪存、自我备份、文件夹、ZFS 数据集)旁边各有一个 本地 / 远程 开关:

  • 本地 显示熟悉的文件夹浏览器。
  • 远程 把它换成一个朴素的 URL 输入框,外加一个按钮,打开异地目标所用的同一个连接测试与凭据对话框,只是配置成面向这个主仓库。从那里你能得到:
    • 一次连接测试,在你真正依赖它之前,对着实际路径跑一遍。
    • 带宽限制(上传与下载),使得定时备份到远程主仓库不会把你的 WAN 线路占满:与异地复制所用相同的 restic 参数 --limit-upload 和 --limit-download,这次作用在备份本身上。
    • 仅追加(不可变)保护,用异地目标同样的主动篡改测试(对远端发起一次真实的 DELETE 探测)来验证。开启后,BombVault 会拒绝自行修剪该仓库:既然它背后没有另一份本地副本,这台机器上的凭据就不该有能力删掉备份的唯一副本。
    • 增长预算告警,取自存储卡片本就在跟踪的那条仓库大小趋势。

这些都不是必需的:手工填入、未保存任何安全设置的远程路径,备份行为与从前一模一样(带宽不限、可修剪、无预算告警)。安全对话框是留给这种情形的:你想要异地副本所享有的同等保护,又不必为此专门建一个异地目标。

云与 REST 凭据是共用的

远程主仓库使用在 设置、云访问、共享云凭据 中配置的同一套 S3/REST 凭据进行认证,主仓库并没有单独的凭据存储。

无需主机挂载的 SMB 和 WebDAV

设置,云访问,rclone 中有一个表单,可用于 Windows 或 Samba 共享,以及 WebDAV 服务器(Nextcloud、ownCloud、SharePoint 或其他任何一种)。填入一个简短的名称、主机和共享(SMB)或 URL 和服务器类型(WebDAV)、用户名和密码,BombVault 就会替您写好 rclone 配置段。密码在保存之前由 rclone 自己做混淆处理;用一个已存在的名称添加目标时,会替换那一段,而不是再添加第二段。

表单会返回完整的位置,例如 rclone:nas:backups。把它填入备份路径或异地目标,如需要可再加一个子文件夹(rclone:nas:backups/bombvault)。共享是路径的第一段,不是名称的一部分。

这比在 Unraid 上挂载共享更好:restic 不建议把仓库放在挂载的 CIFS 共享上,而这里什么都不挂载。表单里没有 NFS,因为 restic 和 rclone 都没有 NFS 后端;对于 NFS,请在主机上挂载导出,并把备份路径指向它。

不可变(append-only)异地

将异地仓库标记为 append-only,这样勒索软件或被入侵的主机就无法删除或改写您的备份。对端(一个运行在 --append-only 模式的 restic/rest-server)强制执行它。BombVault 只会验证它,绝不会仅凭配置声明就显示绿色。

引导式异地设置向导带您从后端选择(rest-server / rclone / S3),走过一段可直接粘贴的 rest-server 部署片段、一次连接测试、不可变切换(它会立即运行篡改测试)和一套保留策略,因此无需手动编辑配置即可实现 append-only 异地。

/locks/ 下删除成功是预期行为

append-only 并不意味着什么都不能再删除。restic 必须获取并释放自己的锁,因此 /locks/ 有意保持可写和可删除。快照以及其背后的数据,也就是勒索软件真正会盯上的东西,无法被删除。如果你自己去探测远端,/locks/ 下成功的删除是正确行为,而不是防护的漏洞。

不可变仓库绝不会从此机器上清理

不可变的异地会有意从不清理旧快照。为它设置一个增长预算告警,以便在仓库大小失控之前得到告警。

篡改测试

BombVault 定期通过实际尝试对异地仓库执行删除(瞄准一个不存在的对象)来证明 append-only 保证:

  • 被拒绝意味着受保护。
  • 被接受意味着未受保护。
  • 不确定的结果(服务器不可达、认证错误)绝不会翻转已存储的判定。

一次真实的从受保护到未受保护的翻转会触发一条告警。

DR 演练

BombVault 提供两个层级的证明,证明您的备份确实可还原,而不仅仅是存在。

  • 还原验证演练(本地)。 BombVault 定期运行 restic check --read-data-subset(有界,绝不是填满磁盘的完整还原),并为每个域显示一个已验证可还原徽章。周期位于设置,计划;徽章位于设置,完整性。
  • DR 演练(异地)。 BombVault 将一个真实目标从异地仓库还原到一次性沙盒,逐文件、逐字节地验证它,然后清理。这证明您能够从异地恢复,而不仅仅是仓库能应答。

仪表板上的勒索软件防护评分卡将这些汇总为每个域的绿 / 黄 / 红态势,带有一份带时间戳的清单(异地已配置、append-only 已验证、复制为最新、还原演练通过、加密开启、清理策略已设置)。每一行红色都深链到对应的修复,而该卡片只在经过验证的事实上变绿。

配对实例

接收端、拉取来源、实例页面和 Mesh 站外备份都要和另一个 BombVault 对话。它们都是以同一个配对群组成员的身份这样做的,一个实例用十二个单词加入群组。

在第一个实例上打开设置 → 配对,在配对卡片中点击生成口令。十二个单词会出现在一个带有复制按钮的窗口中。在其他每一个实例上打开同一个位置,点击输入口令,再把这些单词粘贴或输入进去,或者在该窗口中点击粘贴。不在单词表上的单词,页面会在你输入时就指出它和它的位置,最后一个单词带有一个校验和,因此打错或调换顺序的单词会在配对完成之前就被发现。只在一个实例上生成口令:两个实例如果都生成了口令,就会形成两个各自独立的群组。如果一分钟内没有人出现,标签页会提供两种退出方式:重新显示这些单词以便在对方那边输入,或者输入对方实例的单词并一步加入它的群组。配对不设置登录密码也能用,但请设置一个:不设置的话,任何能打开这个网页界面的人都能读到这些单词,并通过这个组获得组内每个实例的 restic 密码。在设置密码之前,配对卡片会一直提示这一点。设置密码后,再次显示口令时会需要输入密码。退出组会把一个实例重新移出群组。

知道这些单词的任何人都能加入群组,所以要把它们当作密码对待。

成员如何互相联系。 每个实例会在您登录的那一刻从浏览器获知自己在网络上的地址,并显示在中继卡片上的这台实例在你的网络中;如果前面有反向代理或非常规端口,请在那里更正。在同一网络中,成员通过组播宣告这个地址并直接对话;在组播无法穿过容器网络的地方,例如 Docker 的默认桥接网络,实例会改为在自己的子网内搜索其他成员,使用只有组内成员才能应答的签名请求,因此即使没有中继,配对也仍能在几秒内完成。如果什么都没找到,配对卡片下方的找不到吗?可以手动输入一个地址,用于其他子网或非标准端口。位于不同网络中的实例会通过一个中继,该中继在同一标签页里选择:

  • 项目中继(默认):parleyport.halleluja.design,也是 KnightLoader 使用的中继。无需任何设置。
  • 自建中继:来自 Unraid Community Apps 的 ParleyPort 容器,或您已经从外部可访问、并打开了作为中继运行的某个实例。该实例随后会在自己的地址上于 /relay/connect 应答,处在它已有的反向代理和证书之后,并且只放行您的群组。请在每个应使用该中继的实例上填入它的地址。
  • 不用中继:成员会在同一网络中自动找到彼此,别处都不行。

中继能看到什么。 成员之间的每一次通话都用从这十二个单词派生出的密钥以 AES-256-GCM 封装,该密钥永远不会离开您的实例。中继只能得知一个把连接分组的哈希值、一条消息是发给哪个实例的、它有多大、以及它经过的时间。局域网内的直接通话同样以此方式封装并另加签名,因此不依赖某个实例所提供的自签名证书。

什么会经过群组。 实例页面上的评分卡、立即检查某个域的请求、Mesh 的站外存储提议,以及接收端或拉取来源所需要的东西:对方实例的仓库位置及其 restic 密码。备份数据永远不会经过;它始终直接发往 restic 后端。APP_KEY 也不会:restic 密码只能打开该实例的仓库,别的什么都打不开,无论是它保存的密钥、会话还是恢复码。

配对之前留下的条目。 用舰队令牌添加的实例,以及用对方实例的 APP_KEY 设置的接收端和拉取来源,会在更新后保留下来并标记为重新配对。接收端和拉取来源仍会照常工作:BombVault 在首次启动时会把每个已保存的 APP_KEY 替换成由它派生出的 restic 密码。把两个实例配对,然后编辑该条目并选择它的实例。一旦群组中出现同名实例,这样的实例就会立即接管它原来的那张卡片。

仍然需要手动填写 APP_KEY 的唯一地方是从另一个 BombVault 仓库还原,用于对方实例已经不在、无法在群组中应答的情况。

接收方仪表板(接收侧)

接收端以只读方式被监视,完整性检查在本机上执行。

接收端以只读方式被监视,完整性检查在本机上执行。

以上一切都是发送侧。在接收来自另一个 BombVault 的不可变异地副本的机器上,接收方仪表板为您提供对接收硬件上那些仓库的独立、只读监控,因此远端的静默失败不会无人察觉。

打开设置中的接收方开关以显示接收方标签页。它默认关闭;仅在确实接收不可变异地备份的机器上启用它。然后注册一个已接收的仓库(只读,用发送实例的 restic 密码打开,该密码通过配对群组获取),即可获得:

  • 按来源分组的快照清单,因此您可以准确看到哪些容器、虚拟机和文件集已经到达。
  • 每个来源的上次接收,因此您知道每个来源有多新。
  • 在接收硬件上运行的独立 restic check,因此完整性在数据实际所在之处得到验证,而不仅仅在发送方。
  • 一个死人开关: 当某个来源在您设定的时间窗内停止发送时发出告警。
  • 完整性告警: 当接收侧的一次检查失败时发出告警。

接收方严格只读。它绝不会写入已接收的仓库,因此绝不会破坏发送方所依赖的 append-only 保证。

接收服务器

接收端的机器也可以运行其他实例复制到的 rest-server。设置接收服务器位于接收方标签页顶部,会询问共享上的一个文件夹(用新建文件夹创建)和一个端口(除非有其他容器占用,否则为 8000)。随后 BombVault 会:

  1. 如果已存在名为 rest-server 的容器,或其他容器占用了该端口,则拒绝;
  2. 拉取 restic/rest-server,通过 Docker 套接字以 append-only 模式启动,使用私有仓库,并在该文件夹中放置登录文件;
  3. 把它的 Unraid 模板写入闪存,让该容器仍可在 Docker 标签页中编辑;如果无法访问闪存,则提供模板下载;
  4. 对它运行篡改测试,并显示它是否拒绝删除。

您的组中的各实例随后会在目标向导的来自你的组下找到该服务器,以接收端机器的名称显示。每个实例在首次选择该服务器时获得自己的登录,并且只写入其中属于自己的文件夹。卡片会列出这些登录,撤销登录信息可移除其中一个;该实例已复制的内容仍保留在文件夹中。设置还会为组外的人创建一个登录,其密码只在卡片上显示一次。

只能通过中继访问接收端机器的实例无法使用该服务器,因为中继不传输备份。请先在设置,配对中添加接收端机器的地址。如果 BombVault 运行在自己的 IP 地址上(例如 br0),请填写给伙伴使用的地址,因为服务器监听的是主机的地址。

完整示例:两台 Unraid,从头到尾

上面讲的是各个部件。这里给出一整套带真实取值的配置,因为部件只要见过一次装配好的样子,就容易装配得多。

两台机器:TOWER 运行容器并推送备份,VAULT 接收备份并强制不可变。请把名称、地址和共享路径换成你自己的。

1. 在 VAULT 上架设仅追加服务器。 在 TOWER 的 BombVault 中进入 设置 → 异地 → 设置,选择 rest-server 并生成配方。复制 Unraid 模板 (XML) 标签页,在 VAULT 上保存为 /boot/config/plugins/dockerMan/templates-user/my-rest-server.xml,然后 Docker → Add Container,从模板下拉列表中选择 rest-server。启动之前,把显示的 htpasswd 行写入 VAULT 的 /mnt/user/appdata/rest-server/.htpasswd。一次性密码只显示一次且从不保存,请现在复制。 那一行带着同一个密码,已经用 bcrypt 哈希过:明文填进 TOWER 的 REST 凭据,哈希过的那行放进 VAULT 的 .htpasswd。你不需要自己做哈希。

请保留 OPTIONS 字段中的 `--append-only`。这正是关键所在:去掉它,VAULT 就又变回普通共享了。

2. 在 TOWER 上把异地仓库指向它。 仓库 URL 遵循配方打印出的格式:

rest:http://VAULT:8000/bombvault-containers/containers

路径的第一段是 htpasswd 用户,第二段是仓库。把生成的用户名和密码填为该目标的 REST 凭据,然后运行连接测试。

3. 在 TOWER 上打开「不可变」。 篡改测试会立即运行,必须显示受保护。各结果的含义:

结果 发生了什么
受保护 VAULT 拒绝了删除。这是唯一通过的状态。
未受保护 VAULT 接受了删除。--append-only 缺失或已被移除。
无法判定 两者都不是。通常是 URL 与 restic 自己使用的不一致,或者凭据已更改。不会记录任何结果,也不会触发告警。

4. 在 VAULT 上查看收到了什么。 先给两台机器配对(配对实例),打开 设置 → 常规 → 接收端,进入接收端标签页,以 TOWER 作为发送实例,以只读方式注册该仓库。

位置是容器内部的路径,相对于主机挂载点书写

请输入 user/appdata/rest-server/bombvault-containers/containers,而不是 /mnt/user/appdata/…。BombVault 运行在容器中,主机的 /mnt 挂载在别处,主机绝对路径在容器里并不存在。若你粘贴了绝对路径,BombVault 现在会告诉你应改用的相对路径。

保存时 VAULT 会通过群组获取 TOWER 的 restic 密码;不需要任何人手动输入密钥。

5. 如果需要,可以做成双向。 把同样的五个步骤反向再做一遍:TOWER 上的 rest-server 接收 VAULT 的副本。这样每台机器都为对方强制不可变,谁也删不掉对方的备份。

引导式恢复

一个专门的恢复标签页在一处引导全新或重建的安装走完灾难场景:

  1. 先还原 BombVault 自身的设置,这样流程其余部分所需的备份路径、异地目标和凭据都会预先填好(通过 Docker 套接字上的自我重启应用,因此运行中的设置数据库绝不会在打开的句柄下被覆盖)。
  2. 检查 BombVault 能否读取您的备份(把加密密钥的陷阱放在最前面)。
  3. 让您指向您现有的仓库(本地或异地)。
  4. 发现存储在其中的容器、虚拟机、文件集和 ZFS 数据集。
  5. 一次还原容器和虚拟机(保持停止,以便您有意地启动它们),并列出文件集和 ZFS 项目供您逐个还原;ZFS 项目还原后处于关闭状态。您的恢复工具包一键即达。

计划性迁移与灾难

引导式恢复从备份还原 BombVault 自身的设置。对于计划性的迁移到新机器,您可以改用导出 / 导入设置卡片直接迁移您的配置(一个可移植的 JSON 文件)。参见配置。

从另一个 BombVault 仓库还原

恢复标签页上一张单独的卡片会在一次性的只读会话中,用那个实例的 APP_KEY 打开一个不同的 BombVault 实例的仓库(一个挂载在 /mnt 之下的共享,或一个远程 URL)。浏览存储在那里的容器、虚拟机和文件集,选择一个快照并还原它,还原后的对象会成为一个正常的本地容器、虚拟机或文件集。绝不会有任何东西被写入另一个仓库,且您自己的备份设置保持不动(会话存活于内存中并自行过期)。将一个容器从服务器 A 迁移到服务器 B 不再意味着重新指向您的仓库设置并事后还原它们。这张卡片是一次性的:它打开一个会话,还原您选择的内容,然后忘掉另一个实例。如果您想要的是一种长期安排,让这台机器按计划把另一个实例的快照取到自己的仓库中,那就是实例页面的拉取标签页。

如果容器的网络在此服务器上不存在,例如普通 Docker 主机上的 Unraid br0 网络,它的行下方会出现网络选择。BombVault 会在你选择的网络上创建它,并保留其他网络。固定 IP 地址和 MAC 地址属于旧网络,因此会被去掉,由新网络分配。

加密密钥恢复工具包

这是使灾难恢复在没有运行中的 BombVault 时也能实现的那一环。

一键下载主密钥、派生出的 restic 密码以及确切的仓库位置和命令,因此您可以在任意机器上直接用 restic CLI 还原。一条仪表板提醒会一直催促,直到您存好它。

将恢复工具包存放在服务器之外

工具包包含解密您备份的密钥。请将它存放在安全且与服务器分离的地方(一个密码管理器、一份存于保险箱的打印件)。如果您同时丢失了 BombVault 和 APP_KEY 且没有恢复工具包,您的加密备份将无法恢复。

最新的快照不一定是应该恢复的那个

从 restic 0.17 起,restic snapshots 会显示每个快照的大小。数据丢失后,最新的快照可能是被清空的那个,所以不要恢复比之前的快照小得多的快照。遭遇勒索软件后,它可能是大小如常但已被加密的那个。如果 BombVault 仍在运行,请先查看它的 异常 页面:上面会列出最后一个正常的备份。恢复不需要 BombVault 的任何异常数据,保留暂停只会保留更多快照。

密封恢复工具包

如果您为普通导出开启了 age 加密(设置),恢复工具包也会用它密封,并以 bombvault-recovery-kit.md.age 下载。它是 ASCII 装甲格式而不是二进制,所以仍然是纯文本:粘贴到密码管理器或打印出来都和以前完全一样,只是没有您的密钥就读不懂其内容。

不要把 age 密钥存放在工具包里

打开密封的工具包需要您的 age 私钥。请把它存放在不依赖工具包本身的地方,否则您要恢复的东西就从一样变成了两样。当工具包存放在您无法完全掌控的地方(共享的密码管理器、云笔记、办公室里的打印件)时,密封才有价值;放在您自己保险箱里的工具包已经有保险箱保护了。

在加密开启却没有配置可用收件人时,下载会被直接拒绝。BombVault 绝不会退回到以明文交出主密钥。

手边没有恢复包时

密码不存放在任何地方,而是从 APP_KEY 算出来的。只要有密钥和一个 shell,你就能自己复现它:

printf 'bombvault:restic-repo' \
  | openssl dgst -sha256 -mac HMAC -macopt hexkey:$APP_KEY -r \
  | cut -d' ' -f1

这是对固定字符串 bombvault:restic-repo 做 HMAC-SHA256,密钥是十六进制 APP_KEY 的原始字节,输出为 64 个小写十六进制字符。恢复包里的「派生的 restic 密码」就是同一个值;这一节是为恢复包不在你身边的那天准备的。

对于接收到的仓库,请用「发送方」实例的密钥

通过异地复制到达这里的仓库,是发送它的机器用它自己的 APP_KEY 创建的。用接收方的密钥去派生会得到一个 restic 拒绝的密码,那看起来和仓库损坏一模一样,其实并没有损坏。这正是 restic check 在接收到的仓库上反复索要密码的常见原因。

由于恢复定义存放在每个仓库内部(<repo>/def、<repo>/vm-def),被复制的仓库文件夹是完全自包含的,因此工具包加上仓库就是一次裸机还原所需的全部。

取回数据库转储

数据库转储是容器仓库中一个独立的还原点,带有标签 dbdump:<container>,里面只有一个文件 /dbdump/<container>.sql。BombVault 在 备份 里列出、下载并导入它们;下面是只用 restic 完成同样步骤的方法,为 BombVault 不在身边的那一天准备。

restic -r <repo> snapshots --tag dbdump:<container>
restic -r <repo> dump --tag dbdump:<container> latest /dbdump/<container>.sql > <container>.sql

每个转储上的 dbversion: 和 dbname: 标签说明它来自哪个服务器版本、包含哪些数据库。完整的文件以 -- PostgreSQL database cluster dump complete 或 -- Dump completed 结尾。

把它导入一个相同或更新版本(PostgreSQL)、或相同大版本(MySQL 和 MariaDB)的容器,该容器要先用空数据目录启动一次完成初始化。宿主机不需要数据库客户端,容器里就有:

docker exec -i <container> sh -c 'exec psql -X -U "${POSTGRES_USER:-postgres}" -d postgres' < <container>.sql
docker exec -i <container> sh -c 'exec mariadb -uroot -p"$MARIADB_ROOT_PASSWORD"' < <container>.sql
docker exec -i <container> sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < <container>.sql

若只想从完整转储里取一个数据库,MySQL 和 MariaDB 的客户端命令接受 --one-database <name>。PostgreSQL 的转储每个数据库一段,每段以一行 \connect <name> 开头:把那一段复制成单独的文件,先创建数据库,再用 -d <name> 导入。

以 root 取的转储会带上服务器的用户

以 root 取的 MySQL 或 MariaDB 完整转储包含系统数据库 mysql,导入它会把新服务器的账号,连同 root 的密码,替换为转储里的那些。在 PostgreSQL 上,针对容器自己创建的用户出现 role ... already exists 属于预期,无害。