使用 restic 备份 Minecraft 服务器

这已经是我数不清第几次开 Minecraft 私服了…这次准备使用更加完备的流程,尽可能地保障 Minecraft 服务器的数据安全

事情的起因

作为一个拥有 Java,iOS,Google Play,Windows 四平台正版的用户,一年不玩几次是不可能的

开过无数次 Minecraft 服务器了,依稀记得那第一次开私服是朋友在淘宝上买的,一个月30¥。那时候不懂什么配置什么插件什么存档备份乱七八糟的,只知道玩,并且很高速移动很卡。1.8 时代的我还是个毛小子啥也不懂。但是现在,趁着暑假买了个 OrangePi 5 Pro ,还给他做了个 3D 打印外壳,修改了几行 pwm-fan 的驱动使我买的 pwm 调速扇能正常工作。手里拿着一个 4 大核 + 4 小核的玩意怎么能不好好压榨利用一下呢,于是乎在这上面跑 Minecraft 服务器的念头便油然而生。

2024-09-21-我的 OrangePi 5 Pro

这个单板计算机上搭载了一块性能还凑活且非常灵车的😜 NVME 硬盘:三星 PM991A,这是个只有店保的 OEM 硬盘。

65¥要什么自行车

为了磁盘读写性能,我把 Minecraft 服务器放在了这块硬盘上,而不是数据安全性可靠但是性能低下的 emmc 上。

为乘坐 高 速 灵 车 的 Minecraft 服务器提供安全保障

接下来要做的就是数据备份工作了,没有人都不想自己当了那么长时间的帕鲁撸了那么长时间的方块在一瞬间灰飞烟灭了吧。

首先明确一下本灵车服务器的定位:

  • 原版生电/建筑向服务器
  • 7*24 小时开放
  • 每一小时至少备份一次
  • 服务器开在家里,网络是普通的家庭宽带

选择备份工具

Git

作为一个用 Hexo 写 blog 的家伙,首先想到的便是 Git。不过带着“ Git 是个源码版本控制软件,它适合备份二进制的 Minecraft 存档吗?”的疑问,去网上寻找答案。已知的是 Git 可以对二进制进行版本控制的,但是其似乎无法对二进制文件进行精细的差异比较,其检测到修改的处理方式就是将新版本直接复制一份到仓库中。

这种备份的方式实在是太不优雅了,Minecraft 的存档是非常多的分散小文件,而且每当在世界中进行大量的建筑工程时,游戏对区块数据修改是极其频繁。即使我去野外砍了一棵树,撸掉一个泥土方块,那么存储那个区块的文件便会发生变化,Git 就要完整地复制好几个MB的文件到新仓库。作为一个定位为生电和建筑的服务器,制造横跨数个区块的机器是家常便饭。而且由于玩家的时间分配并不那么自由,一台机器花好几天时间造完,甚至造了一半搁置半个月再造一半都是很有可能的。

可预见地,如果我是用 Git 对服务器进行备份,那么其体积膨胀速度会非常块。根据数据备份的 3-2-1 原则,我需要有两个存储介质和至少一份异地备份,但是受限于财力不足无法严格遵守 3-2-1 原则,所以我还是只异地吧。我需要在本地再准备一个足够大的空间,异地云端也要有一个足够大的空间,并且在向云端备份时会长期占用家中的互联网上行带宽。就那 40 Mbps 小水管怎么够啊。

而且备份存档的目的是防止存档损坏丢失,版本追踪方便回档只是防止机器忘记关导致崩服,前者当然是更加重要的,对于后者,我也不需要保留如此多的版本,因为崩服很容易发现。

那么会有人说,你让 Git 删除旧 commit 不就好了? Git 删除旧 commit 的过程十分繁琐,让一个菜鸡编写那样复杂的自动化脚本还是太困难了。而且删除了旧 commit 其仓库体积也不一定会变小多少。

Git 并不适用于我现在的场景,遂排除。

restic

在排除了 Git 之后,我便开始寻找其他的备份工具,我需要的是一个轻量易用的备份工具,只需要他能够“滚动”地备份多个版本,会自动对文件进行比较,无论是二进制还是文本,都可以进行字节级差异备份,即——只添加变化的部分。

restic 是个不错的选择

根据 restic 项目网站上的介绍,restic 支持许多不同的存储类型(甚至支持 rclone ),仅传输实际更改的部分,并且其备份仓库是加密的。

看上去非常适合我的需求,就你了!

使用 restic 备份 Minecraft 服务器

注意,接下来的所有命令和操作均为演示用途,你需要将命令中的路径和各类名称修改为你当前的情况

安装

首先,需要在运行 Minecraft 服务端的系统上安装 restic,这一步很简单,官方文档的 Installation 提供了非常细致的指南。

在我部署 restic 时,其版本为 0.17.1

1
2
$ restic version
restic 0.17.1 compiled with go1.23.1 on linux/arm64

创建仓库

接下来,我先为 Minecraft 服务器新建一个本地仓库。以下命令是初始化仓库

1
2
# 使用 restic -r <仓库的路径> init 创建仓库 
restic -r mc-backup-test/ init

我这里是在当前所在目录下的一个叫 mc-backup-test 的目录中创建仓库, restic 会将各种备份数据都存在这里。你可以建多个仓库,将他们各用作不同用途。

1
2
3
4
5
6
7
8
$ restic -r mc-backup-test/ init
enter password for new repository:
enter password again:
created restic repository 3e1d6ea315 at mc-backup-test/

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.

restic 会提示你输入两次密码,一定要记住这个密码,否则后续别想对仓库进行任何操作(包括备份和恢复数据)。

备份数据

仓库创建后,备份就非常简单了:

1
2
3
# 使用 restic -r mc-backup-test/ backup ../../rokkiea/ mc-server-2024-rsync-copy/ 进行备份
# 你可以在命令结尾添加 -v 或 -vv 参数获得更详细的信息
restic -r mc-backup-test/ backup ../../rokkiea/mc-server-2024-rsync-copy/

restic 会显示当前备份的进度,文件数量,以及体积

1
2
3
4
5
6
7
8
9
10
11
12
$ restic -r mc-backup-test/ backup ../../rokkiea/mc-server-2024-rsync-copy/
enter password for repository:
repository 3e1d6ea3 opened (version 2, compression level auto)
no parent snapshot found, will read all files
[0:00] 0 index files loaded

Files: 401 new, 0 changed, 0 unmodified
Dirs: 50 new, 0 changed, 0 unmodified
Added to the repository: 595.985 MiB (372.387 MiB stored)

processed 401 files, 595.760 MiB in 0:03
snapshot 3c9c2f25 saved

提示 snapshot 3c9c2f25 saved ,这次备份就这样完成了

排除不必要的文件

不过,我的服务器中安装了 Bluemap ,这是一个可以生成类似 Google Map 那样的卫星地图的插件,其渲染产生的文件非常巨大,而且更新极其频繁。反正 Bluemap 的渲染数据也是根据当前世界存档生成的,不备份也没关系,真崩了重新再渲染一份也无妨。

所以我们就要用到 restic 强大的排除文件功能了。restic 的文件排除功能基于路径名所以,我们需要根据要排除的文件的路径来编写规则。
例如我想要排除掉路径包含为 bluemap/ 的文件,则可以新建一个文本文件,写入以下:

1
mc-server-2024/bluemap

当然,服务端目录中还有许多无用的文件,你可以自行添加,其语法类似 gitignore 的写法,更多例子请参考官方文档 Excluding Files 。我的规则最终长这样:

1
2
3
mc-server-2024/libraries
mc-server-2024/cache
mc-server-2024/bluemap

然后在备份时的命令后面加上参数 --exclude-file="<你的规则文件的路径>" 即可。
现在命令变成了这样:

1
2
# 在命令后方加入参数 --exclude-file="<你的规则文件的路径>" 来指定排除文件列表
restic -r mc-backup-test/ backup ../../rokkiea/mc-server-2024-rsync-copy/ --exclude-file="./exclude-file.txt" -vv

仔细翻阅 restic 的输出日志,你会发现列表中列出来的文件和目录都没有被加入仓库。

定时备份

当然作为一个备份程序,让他能在规定的时间自动工作是必不可少的。你那么喜欢手动运行备份我也拦不住你

restic 本身并未提供定时运行的方法,我们可以借助 cronsystemd-timer 等工具来定时运行备份
最简单的办法就是编写一个脚本,然后让以上两个工具定时帮你运行。

1
2
3
4
5
6
7
8
9
10
# 请将 /your/restic/repo/path 替换为你的 restic 仓库的路径
export RESTIC_REPOSITORY=/your/restic/repo/path
# 请将 yourpassword 替换为你的 restic 仓库密码
export RESTIC_PASSWORD=youpassword
# 请将 /your/mc/server/path 替换为你的 Minecraft 服务端所在路径
export MC_SERVER_PATH=/your/mc/server/path
# 请将 /your/restic/exclude/file/path 替换为你的 restic exclude-file 文件路径
export MC_BACKUP_RESTIC_EXCLUDE=/your/restic/exclude/file/path

restic backup "$MC_SERVER_PATH" --exclude-file="$MC_BACKUP_RESTIC_EXCLUDE"

没错,restic 支持从环境变量中读取 仓库路径,仓库密码等信息,具体可以设置哪些环境变量,请看官方文档 Environment Variables

从备份中恢复

当然了, restic 怎么可能只管备份呢。当数据发生丢失或损坏时,当务之急就是从备份中恢复数据。

首先查看仓库中的可用快照

1
restic -r mc-backup-test/ snapshots

restic 会输出一个仓库中的所有快照的列表,包含了快照的 ID ,时间,主机,标签和备份的路径

1
2
3
4
5
6
7
8
$ restic -r mc-backup-test/ snapshots
enter password for repository:
repository 3e1d6ea3 opened (version 2, compression level auto)
ID Time Host Tags Paths Size
-------------------------------------------------------------------------------------------------------------------------------
3c9c2f25 2024-09-21 14:59:04 orangepi5pro /media/nvme0/user-space/rokkiea/mc-server-2024-rsync-copy 595.760 MiB
-------------------------------------------------------------------------------------------------------------------------------
1 snapshots

我们选择恢复快照 3c9c2f25

1
restic -r mc-backup-test/ restore 3c9c2f25 --target ../../rokkiea/test/

接下来你就可以去你指定的 target 目录中享用你的备份了。
restore 命令的更多使用方法也可以去官方文档 Restoring from backup 查看。

删除旧的快照

restic 的 backup 命令只会向仓库中加入新的数据,而不会删除旧的数据。备份也是有期限的,过旧的快照应该被删除。
要在 restic 中删除一份快照一共需要两步。
例如我现在要删除快照 3c9c2f25

  1. forget
1
restic -r mc-backup-test/ forget 3c9c2f25
  1. prune
1
restic -r mc-backup-test/ prune

当然以上两步可以合为一步

1
restic -r mc-backup-test/ forget 3c9c2f25 --prune

不过手动删除也太麻烦了, restic 提供了一些内置的删除策略,我们可以直接用。
例如,我想只保留最近2160个版本,那么我就可以加上参数 --keep-last 2160

1
2
# 使用 --keep-last 来自动删除过旧的快照
restic -r mc-backup-test/ forget --keep-last 2160 --prune

还有很多其他的删除策略可用使用,以下不一一列举额,详情请看官方文档 Removing snapshots according to a policy

restic 远程备份

这里只讲了本地备份,根据上文提到的,我们还需要有一个远程备份。

restic 的文档中提到,它支持 REST Server 作为存储介质。

先挑选一个远程服务器,安装好 REST Server ,由于 REST Server 的安装不是本文的重点,故掠过。

我的方式是:在 REST Server 机器上和香橙派之间起一条 Wireguard-over-VLESS 隧道,因为隧道是加密的,我就无需为 REST Server 配置 SSL 证书了哈哈哈。这个 Minecraft 服务器真是处处充满灵车的味道啊(

由于 restic 在使用 REST Server 作为存储截至时只有仓库名字不同,其他几乎完全一致,故不再详细介绍远程备份的使用。示例可以参考官方文档 REST Server

PS: 在本文撰写结束时,我的 restic 备份已经稳定运行一周,产生了 170+ 个快照了。 restic 真香

1
2
3
4
5
6
7
8
Stats in raw-data mode:
Snapshots processed: 172
Total Blob Count: 14888
Total Uncompressed Size: 4.419 GiB
Total Size: 1.883 GiB
Compression Progress: 100.00%
Compression Ratio: 2.35x
Compression Space Saving: 57.39%

使用 restic 备份 Minecraft 服务器
https://blog.rokkiea.dev/2024/09/21/Backup-Minecraft-server-with-restic/
作者
Rokkiea
发布于
2024年9月21日
更新于
2024年9月21日
许可协议