推荐一款史上最强跨平台、多端加密同步神器 Restic

Posted by Mike on 2020-05-11

什么是 Restic

Restic 是一款 GO 语言开发的开源免费且快速、高效和安全的跨平台备份工具。Restic 使用加密技术来保证你的数据安全性和完整性,可以将本地数据加密后传输到指定的存储。

Restic 同样支持增量备份,可随时备份和恢复备份。Restic 支持大多数主流操作系统,比如:LinuxmacOSWindows 以及一些较小众的操作系统 FreeBSDOpenBSD 等。

项目地址:https://github.com/restic/restic

Restic 支持的存储类型

Restic 支持的存储种类比较多,大致有如下这些类型:

  • 本地存储

  • SFTP

  • REST Server

  • Amazon S3

  • Minio Server

  • OpenStack Swift

  • Backblaze B2

  • Microsoft Azure Blob Storage

  • Google Cloud Storage

  • 通过 Rclone 挂载的存储 (比如:Google Drive、OneDrive 等)

Restic 与 Rclone 的区别

ResticRclone 都是开源的命令行文件备份(同步)工具,但却有着很本质的区别。

  1. 两者的相同点
  • 两者都是基于命令行的开源文件同步和备份工具。

  • 两者都支持将文件备份到本地、远程服务器或对象存储。

  1. 两者不同点
  • Rclone 面向的是文件同步,即保证两端文件的一致,也可以增量备份。

  • Restic 面向的是文件备份和加密,文件先加密再传输备份,而且是增量备份,即每次只备份变化的部分。

  • Rclone 仓库配置保存在本地,备份的文件会保持原样的同步于存储仓库中。

  • Restic 配置信息直接写在仓库,只要有仓库密码,在任何安装了 Restic 的计算机上都可以操作仓库。

  • Rclone 不记录文件版本,无法根据某一次备份找回特定时间点上的文件。

  • Restic 每次备份都会生成一个快照,记录当前时间点的文件结构,可以找回特定时间点的文件。

  • Rclone 可以在配置的多个存储端之间传输文件。

总的来说,RcloneRestic 各有所长,要根据不同的业务需求选择使用。比如:网站数据的增量备份,用 Resitc 就比较合适。而常规文件的远程备份归档,用 Rclone 就很合适。

安装 Restic

Restic 可以通过系统软件包安装,也可以直接下载最新的二进制包方式进行安装。

  1. 通过软件包安装
  • Debian & Ubuntu
1
$ apt-get install restic
  • RHEL & CentOS
1
2
3
$ yum install yum-plugin-copr
$ yum copr enable copart/restic
$ yum install restic
  • Fedora
1
$ dnf install restic
  • Arch Linux
1
$ pacman -S restic
  • macOS
1
$ brew install restic

更多平台的软件包安装方法可参见官方文档:https://restic.readthedocs.io/en/stable/020_installation.html

  1. 通过二进制版本安装

通过预编译好的二进制版本进行安装,非常的简单。只要根据自己所需的平台选择对应的版本下载即可,这里以 Linux 系统为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 下载指定版本的安装包
$ wget https://github.com/restic/restic/releases/download/v0.9.5/restic_0.9.5_linux_amd64.bz2

# 解压并删除压缩包
$ bzip2 -d restic*.bz2 && rm -rf restic*.bz2

# 增加执行权限
$ chmod +x restic*

# 移动二进制文件到指定目录
$ mv restic* /usr/local/bin/restic

# 验证所安装的版本
$ restic version

如果以后需要更新到最新版本,只需运行以下命令就可完成。

1
2
# 直接升级二进制文件到最新版本
$ restic self-update
  1. Restic 常用语法命令

Restic 支持的命令和参数比较多,你可以使用 --help 参数来查看它们的基本用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$ restic --help
restic is a backup program which allows saving multiple revisions of files and
directories in an encrypted repository stored on different backends.

Usage:
restic [command]

Available Commands:
backup Create a new backup of files and/or directories
cache Operate on local cache directories
cat Print internal objects to stdout
check Check the repository for errors
diff Show differences between two snapshots
dump Print a backed-up file to stdout
find Find a file or directory
forget Remove snapshots from the repository
generate Generate manual pages and auto-completion files (bash, zsh)
help Help about any command
init Initialize a new repository
key Manage keys (passwords)
list List objects in the repository
ls List files in a snapshot
migrate Apply migrations
mount Mount the repository
prune Remove unneeded data from the repository
rebuild-index Build a new index file
restore Extract the data from a snapshot
snapshots List all snapshots
stats Count up sizes and show information about repository data
tag Modify tags on snapshots
unlock Remove locks other processes created
version Print version information

Flags:
--cacert file file to load root certificates from (default: use system certificates)
--cache-dir string set the cache directory. (default: use system default cache directory)
--cleanup-cache auto remove old cache directories
-h, --help help for restic
--json set output mode to JSON for commands that support it
--key-hint string key ID of key to try decrypting first (default: $RESTIC_KEY_HINT)
--limit-download int limits downloads to a maximum rate in KiB/s. (default: unlimited)
--limit-upload int limits uploads to a maximum rate in KiB/s. (default: unlimited)
--no-cache do not use a local cache
--no-lock do not lock the repo, this allows some operations on read-only repos
-o, --option key=value set extended option (key=value, can be specified multiple times)
-p, --password-file string read the repository password from a file (default: $RESTIC_PASSWORD_FILE)
-q, --quiet do not output comprehensive progress report
-r, --repo string repository to backup to or restore from (default: $RESTIC_REPOSITORY)
--tls-client-cert string path to a file containing PEM encoded TLS client certificate and private key
-v, --verbose n[=-1] be verbose (specify --verbose multiple times or level n)

Use "restic [command] --help" for more information about a command.

Git 等程序类似 Restic 有许多子命令,每个子命令都有自己的命令行选项。如果你要列出每个子命令的帮助选项,可以使用类似下面的命令语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 以备份子命令为例
$ restic backup --help
The "backup" command creates a new snapshot and saves the files and directories
given as the arguments.

Usage:
restic backup [flags] FILE/DIR [FILE/DIR] ...

Flags:
-e, --exclude pattern exclude a pattern (can be specified multiple times)
--exclude-caches excludes cache directories that are marked with a CACHEDIR.TAG file. See http://bford.info/cachedir/spec.html for the Cache Directory Tagging Standard
--exclude-file file read exclude patterns from a file (can be specified multiple times)
--exclude-if-present stringArray takes filename[:header], exclude contents of directories containing filename (except filename itself) if header of that file is as provided (can be specified multiple times)
--files-from string read the files to backup from file (can be combined with file args/can be specified multiple times)
-f, --force force re-reading the target files/directories (overrides the "parent" flag)
-h, --help help for backup
--hostname hostname set the hostname for the snapshot manually. To prevent an expensive rescan use the "parent" flag
-x, --one-file-system exclude other file systems
--parent string use this parent snapshot (default: last snapshot in the repo that has the same target files/directories)
--stdin read backup from stdin
--stdin-filename string file name to use when reading from stdin (default "stdin")
--tag tag add a tag for the new snapshot (can be specified multiple times)
--time string time of the backup (ex. '2012-11-01 22:08:41') (default: now)
--with-atime store the atime for all files and directories

Global Flags:
--cacert file file to load root certificates from (default: use system certificates)
--cache-dir string set the cache directory. (default: use system default cache directory)
--cleanup-cache auto remove old cache directories
--json set output mode to JSON for commands that support it
--key-hint string key ID of key to try decrypting first (default: $RESTIC_KEY_HINT)
--limit-download int limits downloads to a maximum rate in KiB/s. (default: unlimited)
--limit-upload int limits uploads to a maximum rate in KiB/s. (default: unlimited)
--no-cache do not use a local cache
--no-lock do not lock the repo, this allows some operations on read-only repos
-o, --option key=value set extended option (key=value, can be specified multiple times)
-p, --password-file string read the repository password from a file (default: $RESTIC_PASSWORD_FILE)
-q, --quiet do not output comprehensive progress report
-r, --repo string repository to backup to or restore from (default: $RESTIC_REPOSITORY)
--tls-client-cert string path to a file containing PEM encoded TLS client certificate and private key
-v, --verbose n[=-1] be verbose (specify --verbose multiple times or level n)

配置 Restic 支持的存储方式

安装好 Restic 后,我们需要配置下存储方式。也就是你想备份数据到本地,还是其它远程服务上。

本文将主要讲讲最常用的本地、SFTP 两种备份方式,其它远程库配置方法可参考官方文档:https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html

  1. 配置本地存储仓库
1
2
# 备份到本地 /home/mike/backup 文件夹
$ restic init --repo /home/mike/backup
  1. 配置 SFTP 方式的存储仓库

该方法适合将文件备份到另一台服务器上。首先,我们需要在两台服务器间配置免密码登录。

注意:以下将需要备份的服务器称为 A,备份服务器称为 B。

2.1 配置 SSH 免密码登录

这部分内容比较基础,就不在这里展开了。如果你不会配置可以参考以下两篇文章:

2.2 在服务器 A 上进行数据备份

1
2
# root 为服务器 B 的用户名,192.168.1.100 为 B 服务器 IP,端口默认为 22,/home/mike/backup 为服务器 B 上的目录,如果不存在则会自动创建。
$ restic -r sftp:root@192.168.1.100:/home/mike/backup init

如果服务器 B 的 SSH 默认端口不是 22,你就需要简单调整下 A 服务器上的 SSH 配置文件。

1
2
3
4
5
6
# 在服务器 A 中 ~/.ssh 目录创建一个 config 文件,并新增如下内容。
# 分别是 B 服务器的 IP、用户名和 SSH 的端口。
$ vim ~/.ssh/config
Host 192.168.1.100
User root
Port 2000

由于上面配置了默认的 B 服务器的用户名和密码,现在就可以直接只写 B 服务器的 IP 就可以了。

1
$ restic -r sftp:192.168.1.100:/home/mike/backup init

注意:以上配置过程中都会要求你输入密码,切记不要遗忘。

使用 Restic 备份数据

经过上面的步骤,我们已经完成了备份存储的初始化。现在我就来看几个 Restic 备份的例子。

以下我们所有演示的例子均是将 A 服务器上 /var/www/ 目录下的文件备份到 B 服务器上的 /home/mike/backup 目录下。

创建备份快照

以下命令是备份的 /var/www 整个目录,如果只需备份目录中单个文件,比如:/var/www/mike.zip,那备份内容就可以改成 /var/www/mike.zip

1
2
3
4
5
# 本地备份
$ restic -r /home/mike/backup --verbose backup /var/www

# SFTP 备份
$ restic -r sftp:192.168.1.100:/home/mike/backup --verbose backup /var/www

如果你不想备份目录下全部的内容,你还可以用以下参数排除或包含指定的备份目录或者文件。

1
2
3
4
5
--include 指定一次或多次以包含一个或者多个目录或文件
--exclude 指定一次或多次以排除一个或多个目录或文件
--exclude-caches 指定一次以排除包含特殊文件的目录
--exclude-file 指定一次或多次以排除给定文件中列出的项目
--exclude-if-present 如果目录内容包含给定文件,则指定一次或多次排除目录的内容

具体用法可以参考官方文档: https://restic.readthedocs.io/en/stable/040_backup.html#including-and-excluding-files

Restic 还支持直接将命令的输出进行重定向,比如:将备份好的数据库文件直接通过 SFTP 方式备份到另一台服务器。

1
2
# 将 Wordpress 数据库备份到另一台服务器,并命名为 Wordpress_Backup.sql
$ mysqldump -uroot -ppasswd 000000 --databases Wordpress | restic -r sftp:192.168.1.100:/home/mike/backup backup --stdin --stdin-filename Wordpress_Backup.sql

列出备份快照

备份完成后,可以使用以下命令查看备份的快照信息。您可以看到我们在第一次备份期间的快照 ID,拍摄快照的时间戳,主机名,标签以及备份的目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 查看所有备份快照

$ restic -r sftp:192.168.1.100:/home/mike/backup snapshots
ID Time Host Tags Paths
---------------------------------------------------------------------
ef5ff5fe 2019-08-25 17:03:57 Mike-Dev01 /home/mike/backup
9f0bc19e 2019-08-26 17:18:57 Mike-Dev02 /home/devops/backup
---------------------------------------------------------------------

# 只查看 /home/mike/backup 目录的备份快照
$ restic -r sftp:192.168.1.100:/home/mike/backup snapshots --path="/home/mike/backup"
ID Time Host Tags Paths
---------------------------------------------------------------------
ef5ff5fe 2019-08-25 17:03:57 Mike-Dev01 /home/mike/backup
---------------------------------------------------------------------

# 只查看主机名为 Mike-Dev01 的备份快照
$ restic -r sftp:192.168.1.100:/home/mike/backup snapshots --host Mike-Dev01
ID Time Host Tags Paths
---------------------------------------------------------------------
ef5ff5fe 2019-08-25 17:03:57 Mike-Dev01 /home/mike/backup
---------------------------------------------------------------------

# 列出某个快照中所包含的文件
$ restic ls ef5ff5fe
snapshot ef5ff5fe of [/home/mike/backup] at 2019-08-25 20:35:39.450146467 +0800 CST):
/backup
/backup/2019-04-19_2004334933.jpg
/backup/2019-04-13_15-00-15.png
/backup/2019-04-16_15-19-39.png
/backup/2019-04-16_15-20-22.png
/backup/2019-04-18_17-11-52.png

从上面的结果,我们可以看到 Tags 列是空的。这是因为备份时没有使用 --tag 参数,下面我们演示下 --tag 参数的使用。

1
2
# 给备份文件指定标签
$ restic -r sftp:192.168.1.100:/home/mike/backup --verbose backup /var/www --tag site

如果你想加入更多标签来更详细的区分备份,那就在后面多加几个 --tag 参数。

恢复备份快照

这里以 SFTP 存储仓库为例,我们将远程存储目录 /home/mike/backup 的备份文件恢复到本地 /var/wwww 文件夹。

1
2
3
4
5
# restore 后面指定为要恢复备份的 ID
$ restic -r sftp:root@192.168.1.100:/home/mike/backup restore ef5ff5fe --target /var/wwww

# 你也可以直接使用 latest 来恢复最后一次的备份文件
$ restic -r sftp:root@192.168.1.100:/home/mike/backup restore latest --target /var/wwww

删除备份快照

如果你不在再要一些备份快照,你可以直接使用下面的命令删除指定的备份快照。

1
2
# ef5ff5fe 为要删除文件的 ID
$ restic -r sftp:root@192.168.1.100:/home/mike/backup forget ef5ff5fe

不过上面的命令只是将快照记录清除了,但快照中包含的文件数据仍存储在存储库中。如果要彻底清除未引用的数据,你必须运行 prune 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ restic -r sftp:root@192.168.1.100:/home/mike/backup prune
enter password for repository:

counting files in repo
building new index for repo
[0:00] 100.00% 22 / 22 files
repository contains 22 packs (8512 blobs) with 100.092 MiB bytes
processed 8512 blobs: 0 duplicate blobs, 0B duplicate
load all snapshots
find data that is still in use for 1 snapshots
[0:00] 100.00% 1 / 1 snapshots
found 8433 of 8512 data blobs still in use
will rewrite 3 packs
creating new index
[0:00] 86.36% 19 / 22 files
saved new index as 544a5084
done

清理完成后,存储库的空间就会释放出来。当然你也可以直接使用 --prune 参数来将上面两步合成为一步:

1
2
# ef5ff5fe 为要删除文件的 ID
$ restic -r sftp:root@192.168.1.100:/home/mike/backup forget ef5ff5fe --prune

使用 Restic 进行自动备份

  1. 免密码操作存储仓库

上面的备份中我们都手工输入了密码,如果需要定期备份当然是通过一个脚本来实现是最方便,但是在使用脚本备份时如果要显示输入访问存储仓库的密码肯定不适用的。这里我们就需要使用 --password-file 参数来达到自动读取密码的目的。

1
2
3
4
5
# 将密码保存在 /home/mike/resticpasswd 文本中
$ echo '000000' > /home/mike/resticpasswd

# 在备份命令中使用 --password-file 参数来读取文本中的密码
$ restic -r sftp:root@192.168.1.100:/home/mike/backup --verbose backup /var/www --password-file /home/mike/resticpasswd

除了使用 --password-file 参数指定密码外,你也可以使用环境变量来指定一些 Restic 所需的参数。例如,使用腾讯云的对象存储就可以使用下面这些环境变量。

1
2
3
4
export TencentCloud_ACCESS_KEY_ID="your-access-key"
export TencentCloud_SECRET_ACCESS_KEY="your-secret-key"
export RESTIC_REPOSITORY="s3:server-url/bucket-name"
export RESTIC_PASSWORD="a-strong-password"
  1. 结合 Cron 完成自动备份

Restic 中的 forget 命令可以帮助你来维护快照的运行存档。你可以使用 restic forget --prune 来设置每小时、每日、每周等保留的备份数量,任何不符合策略的备份都将从存储库中清除。

这里我们将使用 Cron 系统服务每 30 分钟运行一次备份任务。

1
2
$ crontab -e
30 * * * * /usr/local/bin/restic -r sftp:root@192.168.1.100:/home/mike/backup backup --password-file /home/mike/resticpasswd -q /var/www; /usr/local/bin/restic forget -q --prune --keep-hourly 24 --keep-daily 7

上面的计划任务里,其中 30 * * * * 定义了 Cron 中任务运行的时间,这里定义为每隔 30 分钟运行。--keep-hourly 24 --keep-daily 7 定义了根据指定的保留标志并删除不再需要的旧快照,在这里我们是将 24 小时内的快照保留 7 天。

更多策略可参考官方文档:https://restic.readthedocs.io/en/latest/060_forget.html#removing-snapshots-according-to-a-policy

参考文档

  1. https://www.google.com

  2. https://restic.readthedocs.io/en/latest/

  3. https://www.moerats.com/archives/897/

  4. https://cloud.tencent.com/developer/article/1160729

  5. https://it.ismy.fun/2018/04/22/restic-backup-to-aliyun-oss/

  6. https://zhuanlan.zhihu.com/p/66324926

  7. https://www.elasticfeed.com/e8590b1297e81b6e7ab19c66be4f037d/

  8. https://www.vmvps.com/restic-a-new-opensource-backup-free-tool-to-backup-your-vps-files.html