Skip to content

使用 systemd+GPG+rclone 实现数据定时备份

Published: at 02:21

最近越来越重视数据的安全问题了,存放在 VPS 上的数据并不是那么可靠,有些关键的东西还是备份一下比较稳妥。正好最近用上了 bitwarden_rs,这里就以备份 bitwarden_rs 的数据目录为例了。

rclone

Rclone 是一个可以以命令行形式与各大网盘进行交互的程序,在整个流程中,我们用它来实现最后一公里的上传任务。

具体的配置方式这里不再详述,值得注意的是,如果你的 VPS 操作用户不是 root,那在这一步,你需要记下配置文件所在路径(通常为 ~/.config/rclone/rclone.conf)。

GPG

GPG 是一个开源的 PGP 实现,在整个流程中,我们用它来实现加密。由于网盘并非一定值得信任,因此加密的步骤可以让你的文件保险很多。

本机:导出公钥

生成密钥对的过程这里跳过不讲。在本地生成完密钥对之后,你首先需要这样东西:密钥的 ID(即完整 ID 的末 16 位)。使用如下命令以导出公钥:

Terminal window
gpg --output encrypt_pub.gpg --armor --export <密钥 ID>

服务器:导入公钥

接下来就是服务器上的操作了。在进行这一步时,切记:要使用 root 进行操作

导入密钥的过程分为两步,一为导入(import),二为信任(trust)。先看导入,导入的步骤首先要求你将之前导出的公钥上传到服务器,然后使用如下命令:

Terminal window
# 记得以 root 运行
# 或 sudo -u
gpg --import /path/to/encrypt_pub.gpg

接下来是信任(trust),使用如下命令:

Terminal window
# 要求同上
gpg --edit-key <密钥 ID>

你会看到类似如下的提示:

gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
pub rsa4096/E7AAA31E332F889C
created: 2019-07-28 expires: never usage: SC
trust: ultimate validity: unknown
sub rsa4096/A55F6F610BB28FA0
created: 2019-07-28 expires: never usage: E
[ultimate] (1). Yesterday17 (某昨P) <[email protected]>
gpg>

这里你会发现 validityunknown,我们要修改的就是这个。输入 trust

gpg> trust
pub rsa4096/E7AAA31E332F889C
created: 2019-07-28 expires: never usage: SC
trust: ultimate validity: unknown
sub rsa4096/A55F6F610BB28FA0
created: 2019-07-28 expires: never usage: E
[ultimate] (1). Yesterday17 (某昨P) <[email protected]>
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5

正如我这里输入的一样,输入 5。因为这是你自己的证书,所以肯定是可以信任的。完成后 Ctrl+C 退出即可。想要检查的话可以使用:

Terminal window
gpg --list-keys

备份脚本

这里直接给出我之前摸的脚本好了:

#!/bin/bash
if [[ $(id -u) -ne 0 ]]; then
echo "You must run it as root." >&2
exit 1
fi
TMP="/var/tmp"
FILE="$FILE_PREFIX$(date +%s).tar.gz"
cd "$TMP"
tar -czvf "$FILE" "$FOLDER"
gpg -r "$RECEIVER" -e "$FILE"
rm "$FILE"
rclone copyto "$FILE.gpg" "$DEST/$FILE.gpg" --config /home/yesterday17/.config/rclone/rclone.conf
rm "$FILE.gpg"

整个过程很简单,先判断 root 权限。在拥有 root 权限时,将 $FOLDER 打包成,并存放到 /var/tmp 下;再调用 gpg 对文件进行加密,这里用到了 $RECEIVER,实际上是之前生成密钥对时候的邮箱;最后将文件通过 rclone 上传到指定位置,并删除本地的备份文件。

Systemd

Systemd 在这里扮演了两个作用:一是 service 执行,二是 timer 定时。其 timerservice 深度绑定,且语法简单。我们直接来看:

backup.service

[Unit]
Description=Backup script for bitwarden_rs
After=network.target
[Service]
Type=oneshot
Environment=FILE_PREFIX="bitwarden_rs_"
Environment=FOLDER="/var/lib/bitwarden_rs"
Environment=RECEIVER="[email protected]"
Environment=DEST="gd:/bitwarden_rs"
ExecStart=+/usr/local/bin/bitwarden_backup
[Install]
WantedBy=multi-user.target

这里也很好理解,首先是四个环境变量,我们选择在这里设置;然后是脚本的位置。这个服务类型是 oneshot,其只执行一项任务,并且在执行之后立即退出。

在这之后,你就可以 start 了。只要配置正确,你应该就可以在网盘上看到对应的文件了。当然了,daemon-reload 是免不了的。

backup.timer

回到开头的需求:定时备份。我们的确可以使用 cron,但 systemdtimer 也挺香,尤其是配合 service 使用的时候,整个过程非常流畅。同样的,我们直接来看配置文件:

[Unit]
Description=Backup bitwarden daily
[Timer]
OnActiveSec=1s
OnUnitActiveSec=12h
[Install]
WantedBy=timers.target

这里我用到了 OnActiveSec,这个选项是指当前 timer 开始(start)后的多长时间后执行对应 service;而 OnUnitActiveSec 则是当该 Timer 开始多久之后执行对应 service,相当于 interval

配置完之后,我们只需要:

Terminal window
# 假设当前用户为 root
# 非 root 需要 sudo
systemctl enable backup.timer
systemctl start backup.timer

至此,整个系统就构建完成了。当然了,我们可以用这个命令查看所有 Timer 的状态:

Terminal window
systemctl list-timers

结语

这个备份脚本被我命名为 bitwarden_backup,但其实它可以满足任何需要打包加密备份的需求。也是借着这次机会,我某种意义上稍微了解了一下 systemdTimer。平日里和 systemd 接触这么频繁,但却缺失了那么多知识,惭愧(

嘛,就是这样(


Previous Post
vue-cli 出现 Vue packages version mismatch 的解决方案
Next Post
kara-templater 源码分析