Vaultwarden自动备份方案

Bitwarden是比较流行的开源密码管理软件。Vaultwarden是轻量级非官方服务端版本,通常自建服务器都采用这个版本。优势是比官方轻量很多,同时无需付费就可以使用TOTP功能。

自建Vaultwarden后马上面临如何备份问题。虽然Bitwarden密码都是本地保存,只要经常同步即使服务器端失效也不会导致所有密码丢失。但是如果长期使用,考虑到任何服务器和数据都有损毁风险,需要有一个恢复手段。

我采用的是rclone本地挂接onedrive网盘,然后配置自动备份脚本备份到网盘。具体方案如下。

1. 挂载网盘

通过rclone config命令配置onedrive并进行本地挂载。

rclone mount onedrive:/backup/ /mnt/onedrive --allow-non-empty --vfs-cache-mode full --daemon

配置自启动挂载

创建桌面文件

nano ~/.config/autostart/rclone-onedrive.desktop

编辑内容

[Desktop Entry]
Type=Application
Name=Mount OneDrive with rclone
Exec=rclone mount onedrive:/backup/ /mnt/onedrive --allow-non-empty --vfs-cache-mode full --daemon writes &
Terminal=false
Hidden=false

2. 编写自动备份脚本

我最开始是用专业的restic进行备份。但发现会自动创建上百个子目录,很影响网盘性能,而且备份文件查看也不直观。于是改回用最简单的tar打包备份。考虑到备份到公网网盘,虽然数据库文件有主密码加密,依然有被暴力破解风险,于是增加了打包加密,采用GPG加密。

Vaultwarden的核心是sqlite数据库,为了保证数据一致性,我采用sqlite3先热备数据库,然后打包。另外需要备份用于加解密的rsa_key.pem,因为不常变化,采用手工备份,不纳入自动备份计划。密码附件文件保存在/vw-data/attachments目录,如果用到也需要纳入备份计划。

备份计划每天一个日备份,保存在daily目录,保留30份,循环覆写。每个月一个月备份,保存在monthly目录,保留12份,循环覆写。

脚本文件如下:

#!/bin/bash

# 定义路径
DATA_DIR="/vw-data"
BACKUP_DIR="/mnt/onedrive"
DAILY_BACKUP_DIR="${BACKUP_DIR}/daily"
MONTHLY_BACKUP_DIR="${BACKUP_DIR}/monthly"
WORK_DIR="${BACKUP_DIR}/work"
DATE=$(date +%Y%m%d)
DAILY_BACKUP_RETENTION=30
MONTHLY_BACKUP_RETENTION=12

# 定义加密密码
GPG_PASSPHRASE="your_secret_passphrase_here"  # 你的加密密码

# 确保目标目录存在
mkdir -p "$DAILY_BACKUP_DIR" "$MONTHLY_BACKUP_DIR" "$WORK_DIR"

# Step 1: 执行SQLite3热备份
sqlite3 "${DATA_DIR}/db.sqlite3" ".backup '${WORK_DIR}/db_${DATE}.sqlite3'"

# Step 2: 打包备份文件
tar -czf "${WORK_DIR}/backup_${DATE}.tar.gz" -C "${WORK_DIR}" "db_${DATE}.sqlite3"

# Step 3: 加密备份文件
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --symmetric --cipher-algo AES256 --output "${DAILY_BACKUP_DIR}/backup_${DATE}.tar.gz.gpg" "${WORK_DIR}/backup_${DATE}.tar.gz"

# Step 4: 删除临时文件
rm "${WORK_DIR}/db_${DATE}.sqlite3" "${WORK_DIR}/backup_${DATE}.tar.gz"

# Step 5: 每月备份逻辑(每月第一天执行)
if [ "$(date +%d)" -eq 1 ]; then
  cp "${DAILY_BACKUP_DIR}/backup_${DATE}.tar.gz.gpg" "${MONTHLY_BACKUP_DIR}/"
fi

# Step 6: 保留最近的30份每日备份
cd "${DAILY_BACKUP_DIR}"
ls -tp | grep -v '/$' | tail -n +$((${DAILY_BACKUP_RETENTION}+1)) | xargs -I {} rm -- {}

# Step 7: 保留最近12个月的备份
cd "${MONTHLY_BACKUP_DIR}"
ls -tp | grep -v '/$' | tail -n +$((${MONTHLY_BACKUP_RETENTION}+1)) | xargs -I {} rm -- {}

修改备份脚本权限。因为包含加密密钥,需要取消其他用户及组任何权限,同时保证当前用户有执行权限。

chmod 700 /path/to/backup.sh

创建定时任务每天凌晨2点自动备份。

0 2 * * * /path/to/backup.sh

可以手动运行一次,去onedrive目录看备份文件是否如预期生成。如果服务器重启注意看一下rclone是否正常挂载网盘。

18 个赞

感谢大佬的分享!

1 个赞

注意隔一段时间用备份还原一下测试下,我就是之前忘记测试了,真数据丢了要还原时候发现附件没备份上 :tieba_087:

感谢大佬分享!

确实需要测试。按我多年的经验,一般来说备份90%的概率用不上,当需要使用备份时90%概率没有备份,当侥幸故障发生又有备份的情况下90%概率备份恢复会有这样那样的问题。

1 个赞

感谢大佬分享

感谢大佬分享

我是用 duplicacy 每天定时备份到阿里云OSS,备份使用 RSA 加密,每个备份保存30天。同时阿里云OSS的bucket每天也进行一次备份,防止accesskey泄露导致OSS上的文件被恶意删除。

感谢分享,用的这个docker暂时还没出啥问题

2 个赞

牛逼,感谢大佬分享。

重要的docker我跑群晖里,直接每天备份到另一台群晖上,这样丢失也就一天的数据。

1 个赞

restic还是很好用的,已经自带了备份加密,还能保存多版本,它也有mount功能供恢复。

又学习到好工具的用法了, 佬友们真是太优秀了

如果懒得跑 rsync 可以考虑用外部 SQL 服务 备份压力会小的多 只有 send(文件共享) 和登录 session没有真正的备份

  • 所有设置都可以用环境变量 不需要备份设置文件
  • 所有密码都在数据库里 数据是加密的 单独考虑备份即可
  • 文件共享没有备份 这个无解
  • 每次重启登录都会掉 重新登录即可

感谢分享,我赶紧配了一个