Vaultwarden 运维手册
Vaultwarden 运维手册:数据目录结构详解、SQLite 在线热备与恢复演练、升级流程、日常巡检与常见故障排查(收不到邮件、附件失败、管理台无法登录),全部基于 Ubuntu 22.04 实测。
Vaultwarden 运维手册
> 目标:读完本文后,你可以独立承担一台 Vaultwarden 1.37.4 的日常运维:看懂数据目录每个文件的职责、做一致性备份并完成恢复演练、按正确流程升级、执行例行巡检,并快速定位四类常见故障。
一、环境信息
本手册全部操作基于下表环境实测执行,数据层命令(sqlite3、tar、sha256sum)与验证命令(curl)的回显均为真实输出。
| 项目 | 实测值 |
|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS(内核 6.8.0-138-generic) |
| Vaultwarden 版本 | 1.37.4(Web Vault 2026.7.0) |
| 数据库引擎 | SQLite 3.53.2(诊断页实测);命令行工具 sqlite3 3.37.2(Ubuntu 22.04 软件源) |
| 数据目录 | /opt/data/vaultwarden |
| 数据库文件实测大小 | db.sqlite3 = 290816 字节(约 284 KiB,含 1 用户/12 条目/3 附件) |
| 日志模式 | WAL(PRAGMA journal_mode 实测返回 wal) |
| 服务端口 | 监听 80,对外 8222 |
运维工具准备(均为 Ubuntu 22.04 软件源版本):
# apt-get install -y sqlite3
# sqlite3 --version
3.37.2 2022-01-06 13:25:41 872ba256cbf61d9290b571c0e6d82a20c224ca3ad82971edc46b29818d5dalt1
二、数据目录结构说明
2.1 目录总览
实测 ls -la /opt/data/vaultwarden(数据目录为部署时挂载的持久化目录,服务升级、重启、迁移都不触碰这里的内容):
total 340
drwxr-xr-x 4 root root 4096 10月 17 16:20 .
drwxr-xr-x 15 root root 4096 10月 17 16:05 ..
drwxr-xr-x 3 root root 4096 10月 17 16:10 attachments
-rw-r--r-- 1 root root 500 10月 17 16:20 compose.yml
-rw-r--r-- 1 root root 290816 10月 17 16:11 db.sqlite3
-rw-r--r-- 1 root root 32768 10月 17 16:20 db.sqlite3-shm
-rw-r--r-- 1 root root 0 10月 17 16:20 db.sqlite3-wal
-rw-r--r-- 1 root root 1675 10月 17 15:58 rsa_key.pem
drwxr-xr-x 2 root root 4096 10月 17 16:10 tmp
各文件职责与运维要点:
| 路径 | 职责 | 运维要点 |
|---|---|---|
| db.sqlite3 | 主数据库:用户、条目元数据、组织、Sends 等全部结构化数据(内容为密文) | 备份核心对象;WAL 模式下运行中直接拷贝有撕裂风险(见第三章) |
| db.sqlite3-wal / db.sqlite3-shm | WAL 预写日志与共享内存伴生文件 | 服务停止后自动合并/清空;恢复数据文件时必须一并处理(见第三章 3.4 节) |
| attachments/ | 附件密文存储,按条目 UUID 分目录 | 随数据库一起备份;删除条目时对应目录被清理 |
| rsa_key.pem | JWT 签名私钥(实测 1675 字节,首次启动自动生成) | 权限应最小化;泄露等同于所有会话可被伪造,必须随备份妥善保管 |
| tmp/ | 上传等操作的临时文件区 | 重启后可安全清理残留 |
| icon_cache/ | 网站图标缓存(首次触发图标抓取后出现) | 可整体删除重建,不影响业务数据 |
| sends/ | Sends 分享的文件存储(启用并使用后出现) | 备份策略与 attachments 相同 |
| backup/ | 管理台内置「备份数据库」按钮的输出目录 | 生成数据库快照副本,仍需外移异地 |
| config.json | 管理台保存的运行时配置(使用管理台修改后才出现) | 与环境变量的优先级关系见《Vaultwarden 1.37.4 配置参数详解》第二章 |
2.2 数据库表结构速查
实测表清单(sqlite3 db.sqlite3 ".tables",节选):
__diesel_schema_migrations groups_users
archives invitations
attachments org_policies
auth_requests organization_api_key
ciphers organizations
ciphers_collections sends
collections sso_auth
collections_groups sso_users
巡检常用统计(实测当前实例:1 个用户、12 条条目、3 个附件记录):
# sqlite3 /opt/data/vaultwarden/db.sqlite3 "SELECT COUNT(*) FROM users; SELECT COUNT(*) FROM ciphers; SELECT COUNT(*) FROM attachments;"
1
12
3
注意边界:users/ciphers 记录的都是加密元数据与密文指针,直接查询无法(也不应)还原任何明文内容;统计数仅用于容量与规模巡检。
三、备份与恢复
3.1 备份对象清单
最小完整备份集 = db.sqlite3(数据库)+ attachments/(附件密文)+ rsa_key.pem(会话签名密钥)。若使用管理台修改过配置,再叠加 config.json;启用了 Sends 则加 sends/。数据库备份必须考虑 WAL 模式的运行中一致性,见下节。
3.2 运行中一致性备份(sqlite3 在线备份)
推荐方案:用 sqlite3 自带的在线备份接口,它通过 SQLite API 保证快照的原子性(即使服务正在写入)。实测全过程:
# sqlite3 /opt/data/vaultwarden/db.sqlite3 ".backup '/tmp/db_full_backup.db'"
# sqlite3 /tmp/db_full_backup.db "PRAGMA integrity_check;"
ok
# stat -c '%s %n' /tmp/db_full_backup.db
290816 /tmp/db_full_backup.db
三步含义:.backup 生成一致快照;PRAGMA integrity_check 返回 ok 证明备份文件结构完整;字节数与源库一致。把这一串写入 cron 即为定时热备(示例:每日 02:30):
30 2 * * * sqlite3 /opt/data/vaultwarden/db.sqlite3 ".backup '/var/backups/vaultwarden/db-$(date +\%F).db'" && sqlite3 /var/backups/vaultwarden/db-$(date +\%F).db "PRAGMA integrity_check;"
备份文件的加密与异地保存见《Vaultwarden 安全加固指南》第六章(openssl 加密方案已实测往返无损)。
3.3 其他备份形态对比
| 方案 | 一致性 | 适用 | 风险 |
|---|---|---|---|
| sqlite3 .backup(本节) | 原子快照 | 全场景首选 | 无 |
| 管理台「备份」按钮 | 服务自身保证 | 临时手工操作 | 文件留在本机 backup/ 目录,需外移 |
| 直接 cp db.sqlite3 | 不保证 | 仅服务完全停止后 | 运行中拷贝会撞上 WAL:拷出的文件可能缺最近事务,且缺 -wal 伴生无法补齐 |
| 文件系统快照(LVM 等) | 取决于快照实现 | 大库/高频备份 | 同样需要理解 WAL 伴生文件 |
3.4 恢复演练(全流程实测)
只备份不演练等于没有备份。以下是一次完整的恢复演练记录(在测试实例上执行,生产同构):
# 1) 停止服务(编排部署的完整生命周期回显见部署指南第六章)
Container vaultwarden-1.37.4-server Stopping
Container vaultwarden-1.37.4-server Stopped
# 2) 覆盖数据文件,并清理 WAL 伴生文件(关键:旧 -wal/-shm 必须删除,否则新库文件会被旧日志污染)
# rm -f db.sqlite3-wal db.sqlite3-shm && cp /tmp/db_full_backup.db db.sqlite3
RESTORE-COPIED
# stat -c '%s %n' /opt/data/vaultwarden/db.sqlite3
290816 /opt/data/vaultwarden/db.sqlite3
# 3) 启动服务
Container vaultwarden-1.37.4-server Started
# 4) 恢复后验证
# curl -s http://127.0.0.1:8222/alive
"2026-10-17T08:43:27.817791Z"
# sqlite3 /opt/data/vaultwarden/db.sqlite3 "PRAGMA integrity_check; SELECT COUNT(*) FROM users; SELECT COUNT(*) FROM ciphers; SELECT COUNT(*) FROM attachments;"
ok
1
12
3
验证要点:/alive 返回 200、integrity_check 为 ok、用户/条目/附件计数与备份时一致(本例 1/12/3),再用客户端登录一次核对数据可见性。恢复演练建议每季度一次。
3.5 附件与密钥的恢复
- 附件目录恢复:整目录覆盖
attachments/即可;实测单个附件落盘路径形如attachments/f8afa06c-7aab-444f-92a2-573cc9fcf22b/d01e9799f624569e784d(条目 UUID 目录 + 附件文件 ID),数据库中的 attachments 表与磁盘目录一一对应; - rsa_key.pem 恢复后无需重新生成;若源文件已丢失,服务重启会自动生成新密钥,代价是所有已登录客户端会话失效(需要重新登录),数据本身不受影响;
- 恢复后务必把目录属主与权限恢复为服务运行用户可读写。
四、升级流程
4.1 升级前置
升级前完成三件事:一是按 3.2 节做一次热备并确认 integrity_check 为 ok;二是记录当前版本(启动日志横幅 Version 1.37.4 或诊断页 Server version);三是阅读目标版本 Release Notes 确认无破坏性变更。
4.2 编排部署的升级
改版本标签 → pull → 重建,完整命令与回显见部署指南第七章(实测输出形态一致)。数据目录不动,服务启动时自动完成数据库结构迁移(__diesel_schema_migrations 表记录迁移历史,可查询确认)。
4.3 二进制部署的升级
- 停服务(systemd 形态:
systemctl stop vaultwarden); - 从 GitHub Releases 下载目标版本对应平台的压缩包,校验校验和后替换二进制;
- 启动(
systemctl start vaultwarden),查看日志横幅确认新版本号; - 验证:
curl /alive返回 200、客户端登录、诊断页数据库检查无报错。
4.4 回退
标签/二进制换回旧版本重启即可。唯一红线:一旦新版本启动过(数据库已迁移),禁止用旧版本直接指向同一数据目录——必须先还原升级前的备份,再以旧版本启动。这也是 4.1 节要求「先备份再升级」的根本原因。
五、日常巡检
5.1 每日/每周巡检项
| 巡检项 | 命令 | 判定 |
|---|---|---|
| 存活与健康 | curl -s http://127.0.0.1:8222/alive | 返回时间字符串即健康 |
| 数据库完整性 | sqlite3 db.sqlite3 "PRAGMA integrity_check;" | ok(巡检读取建议在业务低峰) |
| 数据增长 | stat -c '%s' db.sqlite3(对比上期) | 平稳增长;暴涨需查异常注册/附件 |
| 附件目录体积 | du -sh attachments/ | 与 USER_ATTACHMENT_LIMIT 配额对照 |
| 日志错误 | `journalctl -u vaultwarden --since -24h | grep -i error`(或对应日志文件) |
| 备份任务 | 检查备份目录最新文件时间与 integrity_check | 昨日备份存在且校验通过 |
5.2 版本与安全跟进
订阅 GitHub Releases;安全版本发布后按第四章流程升级并复跑《Vaultwarden 安全加固指南》第八章清单。Web Vault 版本随服务版本一起更换,无需单独运维。
六、常见故障排查
6.1 收不到验证邮件 / 邀请邮件
现象:邀请或邮箱验证没有邮件到达。
排查路径:
- 确认 SMTP 配置完整:
SMTP_HOST/SMTP_FROM/SMTP_USERNAME/SMTP_PASSWORD任一缺失即邮件功能整体停用(默认全为空,见《Vaultwarden 1.37.4 配置参数详解》第七章);/admin/diagnostics与管理台配置页可核对当前生效值; - 管理台「发送测试邮件」按钮直接触发一次发信,是最快的端到端验证;
- 查日志:
journalctl -u vaultwarden | grep -i smtp(或对应日志文件 grep SMTP),常见错误是认证失败(检查 SMTP_AUTH_MECHANISM)与证书校验失败(检查 SMTP_ACCEPT_INVALID_CERTS,生产应保持 false 并修证书); - 收件方垃圾箱与反垃圾策略:自建邮件域没有 SPF/DKIM/DMARC 记录时极易进垃圾箱,配置 DNS 记录后重试;
- DOMAIN 配置错误会让邮件里的链接指向错误地址(实测 DOMAIN 默认 http://localhost,见[《Vaultwarden 1.37.4 配置参数详解》](https://www.quzuo.net/document/pRvgVuQaeSQu)第三章对照),表现为「收到邮件但链接打不开」。
6.2 附件上传失败
现象:客户端上传附件报错或卡住。
排查路径:
- 反向代理体积限制:nginx
client_max_body_size小于文件体积时被代理层拦截(部署指南第五章取官方建议 525M); - 磁盘空间:
df -h /opt/data/vaultwarden,附件与数据库同盘时空间耗尽会同时影响上传与元数据写入; - 目录权限:
attachments/必须对服务运行用户可写(实测属主 root、服务内以运行用户映射的部署需核对挂载权限); - DOMAIN 不匹配:上传接口 v2 返回的直传地址与
DOMAIN相关(实测 DOMAIN 未设置时下载令牌签发方为http://localhost|file_download),反代后必须把 DOMAIN 设为对外 https 地址,否则客户端拿到的地址不可达; - 配额已满:USER_ATTACHMENT_LIMIT/ORG_ATTACHMENT_LIMIT 超限时服务端拒绝,客户端会收到明确报错。
定位技巧:上传失败时盯服务日志中 POST /api/ciphers/<id>/attachment/v2 的响应码——请求本身 200 而后续直传失败多为代理/网络问题;v2 就报错多为配额或权限问题。
6.3 管理台无法登录
现象与实测对照:
| 现象 | 实测回显 | 处置 |
|---|---|---|
| 口令错误 | HTTP 401,页面文案 Invalid admin token, please try again. | 核对口令;argon2 形态登录用明文口令而非哈希串 |
| 连续失败被限流 | HTTP 429,Too many requests, try again later.(实测第 3 次起) | 等 300 秒窗口或重启服务;再核对口令 |
| 哈希被转义污染 | 登录始终 401 且配置值中 $ 异常 | 编排文件中 $ 必须写成 $$(实测转义后服务内为单 $ PHC 串) |
| 令牌生成失败 | /vaultwarden hash 无终端执行 panic(完整回显见部署指南 2.2 节) | 改用 argon2 命令行生成(实测回显见 3.1 节) |
| 会话过期 | 20 分钟无操作后要求重新输入口令 | 正常行为(ADMIN_SESSION_LIFETIME 默认 1200 秒) |
6.4 注册被拒(排障时先确认不是加固生效)
现象:注册页或客户端提示 Registration not allowed。
实测回显(SIGNUPS_ALLOWED=false 时):
{"message":"Registration not allowed or user already exists","validationErrors":{"":["Registration not allowed or user already exists"]},...}
HTTP 400
[2026-10-17 08:14:27.652][vaultwarden::api::identity][ERROR] Registration not allowed or user already exists
[2026-10-17 08:14:27.652][response][INFO] (register_verification_email) POST /identity/accounts/register/send-verification-email => 400 Bad Request
处置:这是关闭注册后的预期行为(见《Vaultwarden 安全加固指南》第五章)。若确需新注册:临时在管理台放开注册(保存 config.json 立即生效)或走管理员邀请;完成后立即改回。另注意 PBKDF2 轮数下限(实测低于 100000 轮的注册被拒,报 Password iteration minimum is 100000),旧客户端需升级后才能注册。
6.5 服务无响应 / 启动失败
排查路径:
/alive无响应时先看服务日志:启动失败常见于数据库损坏(日志出现 SQLite IO 错误)与数据目录权限错误;- 数据库损坏时用最近一次热备按 3.4 节恢复(这也是热备任务必须配 integrity_check 的原因);
- 端口冲突:日志出现绑定 80 失败时检查端口占用;
- 升级后启动失败优先看 Release Notes 是否有必须人工介入的变更,必要时按 4.4 节回退。
七、参考链接
- Vaultwarden 官方 Wiki(备份说明):https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault
- 官方 Wiki(升级与更新):https://github.com/dani-garcia/vaultwarden/wiki/Updating-your-vaultwarden
- 官方 Releases(版本下载与变更日志):https://github.com/dani-garcia/vaultwarden/releases
- SQLite 在线备份接口(.backup 命令):https://www.sqlite.org/backup.html
- SQLite WAL 模式说明:https://www.sqlite.org/wal.html
- SQLite PRAGMA integrity_check:https://www.sqlite.org/pragma.html#pragma_integrity_check
- 本专栏相关:《Vaultwarden 介绍与选型指南》、部署指南、《Vaultwarden 1.37.4 配置参数详解》《Vaultwarden 安全加固指南》
- 相关文档:《Keycloak Admin API 使用详解》《OpenBao 2.7.1 常用 CLI 命令与工具详解》