背景
为了防止重要数据丢失,必须进行备份,备份最保险的措施就是异地备份。即使本地组成最安全的磁盘阵列,依然可能被一锅端。文章将介绍如何通过 OpenList + 阿里云盘异地备份重要数据。
环境
- 操作系统:debian12
安装 openlist
最简单最安全的方式是使用 docker 安装 openlist。docker-compose.yaml 文件内容如下:
services:
openlist:
image: 'openlistteam/openlist:latest'
container_name: openlist
user: '1001:1001' # Please replace `0:0` with the actual user ID and group ID you want to use to run OpenList.
volumes:
- './data:/opt/openlist/data'
ports:
- '5244:5244'
environment:
- UMASK=022
- TZ=Asia/Shanghai
- OPENLIST_ADMIN_PASSWORD=password
restart: unless-stopped
执行如下命令启动 OpenList:
# 启动之前先修改 data 目录的权限
chown -R 1001:1001 ./data
docker compose up -d
在 OpenList 中挂载阿里云盘
根据官方文档进行操作即可。假设
设置 OpenList 的 WabDav 权限
根据官方文档 操作即可。
上传文件到 OpenList
假设服务器的地址是: docker.local.com:5244,阿里云盘映射到 OpenList 的名称是:aliyun-drive。有两种方式上传文件:
- curl
- rclone
curl 上传文件
使用 curl 上传:
curl -T size_60MB.txt -u <username>:<password> http://docker.local.com:5244/dav/aliyun-drive/
使用 curl 命令测试的时候,URL 最后面的 / 不能够少,表示上传文件到 aliyun-drive 文件夹。如果不加最后的 / ,表示上传文件到 openlist 的根目录,并将 size_60MB.txt 重命名为 aliyun-drive。
rclone 上传文件
安装 rclone 命令:
apt install -y rclone
安装成功之后,可以通过 rclone config 交互式命令配置 rclone,也可以在 ~/.config/rclone/rclone.conf 文件中直接写入配置
# openlist 是名称,随意命名
[openlist]
type = webdav
url = http://docker.local.com:5244/dav
vendor = other
user = admin
pass = 2SkGONIcZ4HcPItSBDN8O26ThYY4AV_C
配置文件中的密码是加密后的密码,可以通过如下命令对密码进行加密:
rclone obscure 'mypassword'
将加密后的密码放入到 ~/.config/rclone/rclone.conf 文件的 pass 中
使用 rclone 上传文件:
rclone copy size_60MB.txt openlist:aliyun-drive --progress
对文件进行加密
加密方式有两种: 对称加密和非对称加密。
- 对称加密速度快,适合加密大文件
- 非对称加密更安全,但是不适合加密大文件
备份文件的大小通常都比较大,应当使用对称加密。如果每次备份文件使用的对称加密的密钥都相同,某个文件被破解,其他使用相同密钥加密的文件也被破解了,因此每次加密文件使用的对称加密的密钥应当不同。
每次加密的密钥都不相同,如何管理这些密钥呢?答案是:使用非对称加密的公钥对对称加密的密钥进行加密,并将加密后的密钥与备份文件放在一个压缩包中,这就是对称加密和非对称加密的混合加密方式。
使用混和加密时,一定一定要保管好非对称加密的私钥,私钥丢了,那就一点办法都没有了,以目前计算机的算力是无法破解的。私钥可以保存到自己的计算机或者是 U 盘上。
混和加密的步骤如下:
1. 生成 RSA 密钥对
生成私钥
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
genpkey: 表示生成私钥-algorithm RSA: 表示使用 RSA 非对称加密算法-out private.pem: 输出的私钥保存到private.pem文件中-pkeyopt rsa_keygen_bits:2048: 表示生成的 RSA 密钥的大小为 2048 位。密钥长度越长,安全性越高,但生成和加解密运算时消耗的资源也越多。2048 位是目前推荐的最低安全密钥长度。
导出公钥
openssl rsa -in private.pem -pubout -out public.pem
rsa: 执行 rsa 非对长加密算法的相关操作-pubout: 执行输出公钥的操作-out public.pem: 输出的公钥保存到public.pem文件中-in private.pem: 从private.pem文件中提取公钥
2. 生成随机 AES 密钥
openssl rand -out aes.key 32
rand: 表示生成随机字节-out aes.key: 表示将生成的随机字节写入到aes.key文件中- 32 表示 32 个字节,即 256 位,$2^{256}$,这是 AES 加密支持的最大长度
3. 使用 AES 密钥加密文件
openssl enc -aes-256-cbc -pbkdf2 \
-in plain.txt \
-out data.enc \
-pass file:./aes.key
enc: 表示执行加密操作-aes-256-cbc: 指定加密算法:AES,使用 256 位密钥长度,工作模式为 CBC(Cipher Block Chaining,密码块链模式)-pbkdf2: 指定使用 PBKDF2(Password-Based Key Derivation Function 2)作为密钥派生函数。这使得基于密码的加密更安全,增加了抗暴力破解能力。默认情况下,openssl enc以前不使用PBKDF2,而是用较弱的EVP_BytesToKey,现代实践推荐加上此选项。-out data.enc: 表示密文写入到data.enc文件中-in plain.txt: 表示待加密的文件-pass file:./aes.key: 表示从aes.key文件中读取密码。pass选项有三种传递密码的方式:- 直接传递密码:
pass:<password> - 文件读取密码:
file:/path/to/file - 读取环境变量:
evn:<Variable>
- 直接传递密码:
4. 使用公钥加密 AES 密钥
openssl pkeyutl -encrypt -pubin -inkey public.pem -in aes.key -out aes.key.encrypted
pkeyutl: 表示执行非对称加解密相关操作-encrypt:加密操作-pubin:表示使用公钥加密-inkey public.pem:公钥文件-in aes.key:需要机密的数据。-out aes.key.encrypted:将加密后的数据写入aes.key.encrypted文件中。
5.将加密后的文件和加密后的密钥一起打包
mkdir backup-2026-01-08
mv data.enc aes.key.encrypted backup-2026-01-08
tar -czvf backup-2026-01-08.tar.gz backup-2026-01-08
对文件进行解密
1. 解压文件
tar -xvf backup-2026-01-08.tar.gz
2. 使用私钥解密 AES 密钥
cd backup-2026-01-08
openssl pkeyutl -decrypt \
-inkey private.pem \
-in aes.key.encrypted \
-out aes.key
pkeyutl: 非对称加解密相关工具-decrypt: 执行解密操作-inkey private.pem: 密钥文件路径-in aes.key.encrypted: 加密文件路径-out aes.key: 解密后的数据写入到aes.key文件中
3. 使用 AES 密钥解密文件
openssl enc -d -aes-256-cbc -pbkdf2 \
-in data.enc \
-out plain.txt \
-pass file:./aes.key
enc -d: 执行解密操作-aes-256-cbc: 指定加密算法:AES,使用 256 位密钥长度,工作模式为 CBC(Cipher Block Chaining,密码块链模式)-pbkdf2: 指定使用 PBKDF2(Password-Based Key Derivation Function 2)作为密钥派生函数。这使得基于密码的加密更安全,增加了抗暴力破解能力。默认情况下,openssl enc以前不使用PBKDF2,而是用较弱的EVP_BytesToKey,现代实践推荐加上此选项。-in data.enc: 加密文件-out plain.txt: 解密后的内容输出到plain.txt文件中-pass file:./aes.key: 从aes.key文件中读取密钥。pass选项有三种传递密码的方式:- 直接传递密码:
pass:<password> - 文件读取密码:
file:/path/to/file - 读取环境变量:
evn:<Variable>
- 直接传递密码:
4. 检查文件是否成功解密
cat plain.txt
备份文件
工具都准备好后,就可以备份重要文件了,备份步骤:
- 打包重要文件
- 对重要文件进行加密
- 上传加密后的文件到阿里云盘
- 删除阿里云盘中过期的备份文件
假设我需要备份服务器上的 ~/docker/minio 文件夹
# -C 参数表示先进入 ~/docker 文件夹,再进行打包
# 这样解压 minio.tar.gz 文件时,解药出来的就是 minio 而不是 docker/minio
tar -czvf minio.tar.gz -C ~/docker minio
# 生成 AES 密钥
openssl rand -out aes.key 32
# 使用 AES 密钥对 minio.tar.gz 文件加密
openssl enc -aes-256-cbc -pbkdf2 \
-in minio.tar.gz \
-out minio.tar.gz.enc \
-pass file:./aes.key
# 从私钥中导出公钥
openssl rsa -in private.pem -pubout -out public.pem
# 使用公钥对 AES 密钥加密
openssl pkeyutl -encrypt -pubin -inkey public.pem -in aes.key -out aes.key.enc
# 将备份文件以及密钥放入到一个压缩包中
mkdir backup-2026-01-08
mv minio.tar.gz.enc aes.key.enc backup-2026-01-08
tar -czvf backup-2026-01-08.tar.gz backup-2026-01-08
# 将备份文件通过 openlist 上传到阿里云盘
rclone copy backup-2026-01-08.tar.gz openlist:aliyun-drive --progress
# 删除阿里云盘中七天以前的备份
rclone delete "openlist:aliyun-drive/" --min-age 7d --include "backup-*.tar.gz" -v
# 清理本地不必要的文件
rm -rf aes.key backup-2026-01-08 backup-2026-01-08.tar.gz minio.tar.gz public.pem
恢复备份文件
# 解压备份文件
tar -xvf backup-2026-01-08.tar.gz
# 使用私钥解密加密的 AES 密钥
openssl pkeyutl -decrypt \
-inkey private.pem \
-in backup-2026-01-08/aes.key.enc \
-out aes.key
# 使用 AES 密钥解密备份文件
openssl enc -d -aes-256-cbc -pbkdf2 \
-in backup-2026-01-08/minio.tar.gz.enc \
-out minio.tar.gz \
-pass file:./aes.key
# 解压备份文件
tar -xvf minio.tar.gz