Vaultwarden 备份与恢复架构及操作指南
一、引言
Vaultwarden 作为一套常见的自托管密码管理服务,通常承载着用户账号、附件、密钥材料以及发送文件等关键数据。一旦出现误操作、容器损坏、主机迁移或数据库异常,若缺少成体系的备份与恢复方案,将直接影响业务连续性与数据安全。
本文基于一套已经落地的 Vaultwarden + PostgreSQL + Docker Compose + WebDAV 方案,给出一份完整的技术说明。文章重点覆盖以下内容:
- Vaultwarden 当前备份架构的组成与职责划分
- 备份链路中的数据范围、加密方式、调度策略与远端归档方式
- 备份任务的实施步骤与验证方法
- 恢复操作的执行路径、命令示例与注意事项
本文中的示例目录采用 /home/heaven/docker/vaultwarden,如实际部署路径不同,可按同样思路调整。
二、备份对象与系统现状
在当前部署中,Vaultwarden 运行于 Docker Compose 中,主服务数据目录通过宿主机绑定挂载到 ./data,数据库使用 PostgreSQL,而不是默认的 SQLite。
从备份视角看,一套完整的 Vaultwarden 数据至少应包含以下内容:
db.dumpPostgreSQL 数据库导出的逻辑备份文件,保存组织、用户、凭据条目、集合关系等结构化数据。rsa_key*Vaultwarden 使用的 RSA 密钥材料。attachments条目附件目录。sendsSend 功能相关的数据目录。config.json若部署使用该文件存放配置,则也应纳入备份;若当前实例完全由环境变量驱动,备份工具会在执行时跳过该文件。
因此,备份方案不能只停留在数据库导出层面,而应覆盖数据库 + 文件目录 + 密钥材料三类核心资产。
三、整体备份架构设计
1. 架构组件
当前方案包含以下关键组件:
vaultwarden主业务容器,负责对外提供密码管理服务。postgres16PostgreSQL 数据库容器,存放 Vaultwarden 核心业务数据。ttionya/vaultwarden-backup专用备份容器,用于读取 Vaultwarden 数据目录、导出 PostgreSQL、打包并上传归档。rclone负责把加密后的备份文件推送到远端 WebDAV 存储。WebDAV远端备份存储目标,用于保存最终归档文件。cron宿主机调度器,用于在每天固定时间触发一次性备份容器。
2. 数据流向
整个备份链路可以抽象为如下流程:
宿主机 cron(每天 03:00)
│
▼
docker compose run --rm backup
│
├── 读取 Vaultwarden 数据目录 /data
├── 连接 PostgreSQL 导出 db.dump
├── 打包 rsa_key / attachments / sends
├── 使用 7z + 密码进行加密压缩
├── 通过 rclone 上传到 WebDAV
└── 清理容器内临时文件,并删除远端 5 天前备份3. 设计要点
该方案有四个关键设计点:
第一,备份容器采用一次性运行模式。
backup 服务通过 docker compose run --rm 触发,每次备份结束后容器即退出,不长期驻留,运维边界更清晰。
第二,备份中间文件不在宿主机持久保留。
备份包在容器内部临时生成,上传完成后即清理,宿主机只保留日志文件。这种方式降低了本地明文归档残留风险。
第三,远端存储使用 WebDAV,归档通过 rclone 实现。
这使得备份目标可以灵活切换到支持 WebDAV 的网盘、对象存储网关或私有云盘系统。
第四,归档启用加密压缩。
备份包采用 7z 格式并配置独立压缩密码,避免远端存储侧直接暴露敏感业务数据。
四、Docker Compose 中的备份服务设计
在当前系统中,backup 服务并不常驻,而是作为一个随调随起的任务型容器存在。核心配置可整理为如下形式:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
ports:
- "8380:80"
volumes:
- ./data:/data
environment:
- DATABASE_URL=postgresql://vaultwarden:<db-password>@postgres16:5432/vaultwarden
networks:
- javdb_bridge
backup:
image: ttionya/vaultwarden-backup:latest
command: ["backup"]
restart: "no"
volumes:
- ./data:/data:ro
- /home/heaven/.config/rclone:/config/rclone:ro
- ./.backup_zip_password:/run/secrets/zip-password:ro
environment:
- TIMEZONE=Asia/Shanghai
- DATA_DIR=/data
- DB_TYPE=postgresql
- PG_HOST=postgres16
- PG_PORT=5432
- PG_DBNAME=vaultwarden
- PG_USERNAME=vaultwarden
- PG_PASSWORD=<db-password>
- RCLONE_REMOTE_NAME=clouddrive2-dav
- RCLONE_REMOTE_DIR=115/backup/vault
- ZIP_ENABLE=true
- ZIP_PASSWORD_FILE=/run/secrets/zip-password
- ZIP_TYPE=7z
- BACKUP_KEEP_DAYS=5
- BACKUP_FILE_SUFFIX=%Y%m%d-%H%M%S
- DISPLAY_NAME=vaultwarden
networks:
- javdb_bridge
networks:
javdb_bridge:
external: true上述配置中,最值得关注的参数如下:
DATA_DIR=/data指定 Vaultwarden 实际数据目录。DB_TYPE=postgresql显式切换到 PostgreSQL 备份模式。PG_HOST=postgres16使用容器网络内的数据库服务名,而不是宿主机 IP。RCLONE_REMOTE_NAME与RCLONE_REMOTE_DIR指向已经配置好的 rclone remote 和远端目录。ZIP_PASSWORD_FILE通过只读文件向容器提供压缩密码,而不是把密码直接暴露在命令行中。BACKUP_KEEP_DAYS=5表示删除 5 天之前的远端备份文件,保留最近 5 天归档。
五、备份实施步骤
1. 准备压缩密码文件
建议在 Compose 目录下为压缩密码单独准备一个只读文件,并收紧权限:
cd /home/heaven/docker/vaultwarden
umask 077
openssl rand -base64 48 > .backup_zip_password
chmod 600 .backup_zip_password该文件是后续解密恢复的关键凭据,必须进行离线保管。
2. 确认 rclone 配置可用
当前方案直接复用宿主机现有的 rclone.conf。可通过如下命令确认 remote 是否存在:
rclone config show若需要确认远端目录可访问,可执行:
rclone lsd clouddrive2-dav:115/backup/vault3. 注册每日定时任务
当前系统采用宿主机 cron 统一调度,而不是让备份容器内部自行常驻并调度。建议使用如下任务:
0 3 * * * cd /home/heaven/docker/vaultwarden && /usr/bin/docker compose run --rm -T backup >> /home/heaven/docker/vaultwarden/vaultwarden-backup.log 2>&1
这条任务表达的含义是:
- 每天凌晨 03:00 进入 Vaultwarden Compose 目录
- 启动一次
backup服务 - 备份结束后自动移除容器
- 将标准输出和错误输出统一写入
vaultwarden-backup.log
4. 手工触发一次备份
在定时任务正式投入使用前,应先人工执行一次,验证参数和链路:
cd /home/heaven/docker/vaultwarden
docker compose run --rm -T backup若执行正常,日志中通常会看到如下关键信息:
- 备份 PostgreSQL 数据库
- 打包
rsa_key、attachments、sends - 生成
backup.<timestamp>.7z - 上传到远端目录
- 删除 5 天之前的远端历史文件
5. 验证备份结果
可从两个维度进行验证。
其一,检查本地日志:
tail -n 80 /home/heaven/docker/vaultwarden/vaultwarden-backup.log重点确认是否包含:
backup vaultwarden postgresql databasepackage backup fileupload backup file to storage system
其二,检查远端文件是否生成:
rclone lsl clouddrive2-dav:115/backup/vault | tail -n 10若输出中出现类似 backup.20260407-161447.7z 的文件,说明上传已经完成。
六、恢复架构设计
备份体系的真正价值并不在于“能生成备份文件”,而在于“能可靠恢复”。从恢复链路上看,当前方案包含如下步骤:
WebDAV 远端备份包
│
▼
rclone 下载到本地 restore 目录
│
▼
停止 vaultwarden 主服务
│
▼
启动 restore 容器并挂载:
- 目标数据目录
- 待恢复备份文件目录
- 压缩密码文件
- PostgreSQL 网络
│
▼
解密 7z 归档并恢复:
- db.dump -> PostgreSQL
- rsa_key / attachments / sends -> /data
│
▼
重新启动 vaultwarden 并验证登录、条目与附件这里有两个原则必须明确:
- 恢复会覆盖现有数据。
- 恢复前必须停止 Vaultwarden 主服务,但 PostgreSQL 必须保持可连接。
七、标准恢复操作步骤
1. 从 WebDAV 下载目标备份文件
首先在本地准备一个恢复目录,并把指定时间点的备份包下载下来:
mkdir -p /home/heaven/docker/vaultwarden/restore
rclone copyto \
clouddrive2-dav:115/backup/vault/backup.20260407-161447.7z \
/home/heaven/docker/vaultwarden/restore/backup.20260407-161447.7z对于生产环境,建议先明确恢复点,再执行下载,不要在恢复时临时挑选文件。
2. 停止 Vaultwarden 服务
恢复前应先停止主业务容器,避免恢复过程中业务继续写入:
cd /home/heaven/docker/vaultwarden
docker compose stop vaultwarden3. 执行恢复命令
当前系统使用 PostgreSQL,因此恢复容器必须加入与数据库相同的 Docker 网络,并显式带上数据库连接参数:
docker run --rm -it \
--network javdb_bridge \
--mount type=bind,source=/home/heaven/docker/vaultwarden/data,target=/data \
--mount type=bind,source=/home/heaven/docker/vaultwarden/restore,target=/bitwarden/restore \
--mount type=bind,source=/home/heaven/docker/vaultwarden/.backup_zip_password,target=/run/secrets/zip-password,readonly \
-e DATA_DIR=/data \
-e DB_TYPE=postgresql \
-e PG_HOST=postgres16 \
-e PG_PORT=5432 \
-e PG_DBNAME=vaultwarden \
-e PG_USERNAME=vaultwarden \
-e PG_PASSWORD=<db-password> \
-e ZIP_PASSWORD_FILE=/run/secrets/zip-password \
ttionya/vaultwarden-backup:latest restore \
--zip-file /bitwarden/restore/backup.20260407-161447.7z若需要跳过交互确认,可以附加 --force-restore 参数,但生产环境应谨慎使用。
4. 启动服务并验证恢复结果
恢复完成后,重新拉起 Vaultwarden 服务:
cd /home/heaven/docker/vaultwarden
docker compose up -d vaultwarden随后建议执行如下验证:
- 登录后台并检查用户是否可正常认证
- 抽查若干关键条目是否存在
- 检查附件是否可访问
- 检查 Send 数据是否可读取
- 查看容器日志中是否存在数据库连接或解密异常
八、备份与恢复中的注意事项
1. 不要把压缩密码写入公开配置
压缩密码决定了远端归档的可恢复性。若直接写入 Compose 文件、Shell 历史或公开仓库,将显著放大安全风险。更稳妥的做法是使用独立只读文件或 Secret 机制。
2. BACKUP_KEEP_DAYS=5 是“按天保留”,不是“按文件数保留”
该配置的语义是删除超过 5 天的远端备份,而不是只保留最近 5 个文件。如果一天执行多次备份,远端可能会同时保留多个同日文件。
3. 恢复演练必须定期执行
只存在备份而从未恢复验证的方案,并不能视为真正可用的灾备体系。建议至少定期在测试环境执行一次全量恢复演练。
4. config.json 缺失不一定是异常
若当前实例完全通过环境变量配置,备份工具会提示 config.json 不存在并跳过,这是符合预期的,不应误判为备份失败。
5. 恢复前应额外保留当前状态快照
即便已经选定历史恢复点,在覆盖恢复之前,仍建议对当前线上状态再执行一次紧急备份,以便在恢复点选择错误时回滚。
九、结语
对于 Vaultwarden 这类承载高敏感数据的系统,备份与恢复不能仅以“数据库导出成功”作为交付标准,而应形成一套完整的工程闭环:明确备份对象、控制加密与保留策略、验证远端归档、固化恢复命令,并定期执行恢复演练。
本文所介绍的方案,以 ttionya/vaultwarden-backup 作为核心备份执行器,结合 rclone + WebDAV + cron 完成归档与调度,具备结构清晰、依赖简单、易于验证和易于迁移的特点。对于采用 Docker Compose 部署、并以 PostgreSQL 作为后端数据库的 Vaultwarden 实例,这是一套可直接复用的标准化备份恢复方案。