最后更新于

使用 restic 备份 vaultwarden 数据


在甲骨文机器上用 docker 运行着一个 vaultwarden 服务,用来管理自己的所有密码。

Vaultwarden 介绍

Vaultwarden 是 Bitwarden 的开源后端替代品,前身为 bitwarden_rs。通过自行部署 Vaultwarden,你可以拥有一个完全自主的密码管理服务。由于 Vaultwarden 兼容 Bitwarden 的 API 接口,且 Bitwarden 客户端支持自定义后端,你可以使用熟悉的 Bitwarden 客户端连接到自己的 Vaultwarden 服务。这种方式既能享受 Bitwarden 客户端的便捷功能,又能完全掌控自己的密码数据,实现了便利性和数据安全的完美结合。

因为甲骨文提供的是免费的 vps,为了避免机器被忽然回收导致数据丢失,所以需要定期备份 vaultwarden 的数据库。

首先 vaultwarden 使用了 docker compose 部署,默认使用 sqlite 存储数据。部署文件如下:

docker-compose.yaml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
environment:
SIGNUPS_ALLOWED: false # Deactivate this with "false" after you have created your account so that no strangers can register
volumes:
- ./vw-data:/data # the path before the : can be changed
ports:
- 11001:80 # you can replace the 11001 with your preferred port

因此在 vw-data 下面,保存着所有密码数据,只要备份这个目录,就可以还原

在选择备份方案时,我没有采用较为热门的 vaultwarden-backup,而是选择了 restic 工具,主要基于以下两个原因:

  1. 备份需求的全面性:vaultwarden-backup 基于 rclone,而 rclone 主要专注于文件同步。然而,一个完整的备份方案还需要考虑其他方面,如数据版本管理。使用支持版本控制的备份工具可以在某个版本出现问题时轻松切换到其他版本。

  2. 学习一个新工具:选择 restic 也是为了学习一个新的备份工具。在研究 Kubernetes pod 备份时,我发现 volsync 被广泛使用,而 volsync 的备份就是基于 restic 的。因此,熟悉 restic 不仅可以解决当前的备份需求,还能为将来在 Kubernetes 环境中使用 volsync 打下基础。

下面步骤主要是设置好备份地址,然后定期执行的操作细节:

前置条件

在开始之前,请确保已经有一个 S3 兼容的服务,例如 MinIO、Amazon S3 或其他支持 S3 协议的存储服务。您需要获取到以下信息:

  • S3 服务的访问地址(例如 https://<minio-host>:<minio-port>
  • 存储桶名称(例如 <bucket-name>
  • 访问密钥(AWS_ACCESS_KEY_ID
  • 秘密密钥(AWS_SECRET_ACCESS_KEY) 确保这些信息在后续步骤中可以使用。

一: 首先安装 restic

Terminal window
sudo apt update
sudo apt install restic

二: 初始化 restic 仓库

先设置好环境变量:

Terminal window
export RESTIC_REPOSITORY=s3:https://<minio-host>:<minio-port>/<bucket-name>/<subpath>
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-key>
export RESTIC_PASSWORD=<your-password>

然后执行:

Terminal window
restic init

执行成功后,会在远程 S3 目录 https://<minio-host>:<minio-port>/<bucket-name>/<subpath> 看到一些初始化 meta 数据。

三: 创建备份并清理旧数据的脚本 backup_and_prune.sh,内容如下:

backup_and_prune.sh
#!/bin/bash
# 设置环境变量
export RESTIC_REPOSITORY=s3:https://<minio-host>:<minio-port>/<bucket-name>/<subpath>
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-key>
export RESTIC_PASSWORD=<your-password>
# 备份目录
BACKUP_SOURCE="/home/ubuntu/vaultwarden/vwdata"
# 日志文件
LOG_FILE="/home/ubuntu/back.log"
# 执行备份并记录日志
restic backup $BACKUP_SOURCE >> $LOG_FILE 2>&1
# 删除超过7天的旧备份并记录日志
restic forget --keep-daily 7 --prune >> $LOG_FILE 2>&1
# 记录快照信息
restic snapshots >> $LOG_FILE 2>&1

请自行将里面的变量和路径替换为实际值。

四: 设置定期执行:

使用 cron 来设置每天定期执行备份任务。

Terminal window
crontab -e

添加以下行来设置每天凌晨 2 点执行备份脚本:

Terminal window
0 2 * * * /home/ubuntu/backup_and_prune.sh

确保你的脚本有执行权限:

Terminal window
chmod +x /home/ubuntu/backup_and_prune.sh

这样你的备份脚本就会每天凌晨 2 点执行一次了。

五: 验证备份

验证数据是否正常的最好办法是让 vaultwarden 加载备份的数据,然后在网页查看数据是否是最新的。因此接下来的操作是将远程的备份下载到本地,然后在本地执行的具体操作。

首先设置环境变量

Terminal window
export RESTIC_REPOSITORY=s3:https://<minio-host>:<minio-port>/<bucket-name>/<subpath>
export AWS_ACCESS_KEY_ID=<your-access-key>
export AWS_SECRET_ACCESS_KEY=<your-secret-key>
export RESTIC_PASSWORD=<your-password>

列出所有快照:

Terminal window
restic snapshots

恢复某个快照到指定目录:

restic restore <snapshot-id> --target ~/Downloads/

根据本文的例子,最终的文件还原到了 ~/Downloads/vw-data 下面。

本地临时运行一个 docker compose 文件:

dock-compose.yaml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
environment:
SIGNUPS_ALLOWED: false # Deactivate this with "false" after you have created your account so that no strangers can register
volumes:
- ~/Downloads/vw-data:/data # the path before the : can be changed
ports:
- 11001:80 # you can replace the 11001 with your preferred port

docker compose up 启动后,访问 localhost:11001 查看数据正常就表示备份没有问题了。

至此,我们已经完成了一个基本的自动化备份方案。这是一个通用型方案,理论上可以用于备份各种类型的数据。然而,任何系统都有改进的空间,这个方案也不例外。以下是两个可以考虑的优化点:

  1. 启用 append-only 模式:如果有足够的备份空间,可以考虑启用此模式。这样可以防止在服务器被入侵的情况下,攻击者删除所有备份数据。

  2. 使用支持快照的文件系统:这可以解决备份过程中数据变化导致的不一致问题。通过在备份开始时创建快照,我们可以确保备份的是某一时刻的一致性数据。

这两点优化可以进一步提高我们备份系统的安全性和数据一致性。