在法国用二手 NAS 跑 Vaultwarden,别把 SQLite 放机械盘

家里那台 DS218j 是 2017 年在 Leboncoin 上 60 欧收的,两盘位,ARM 双核,内存 512MB,系统还停在 DSM 7.1。之前它只干两件事:Hyper Backup 和一台旧打印机的扫描目录。上个月想把密码库从 Bitwarden 官方云搬回来,就顺手在 Docker 里起了 Vaultwarden,镜像版本 1.30.5。数据量很小,两个人用,密码条目加起来不到 400 条,数据库文件 20MB 左右。

问题出在第一次做完整备份的时候。Vaultwarden 默认用 SQLite,我把 data 目录直接挂到存储池的机械盘上,没有放 SSD。备份脚本是停容器后直接 cp 那个 db 文件,看着没问题。但恢复测试时解出来的库是坏的,sqlite3 db.sqlite3 "PRAGMA integrity_check" 报 malformed。后来才发现,Vaultwarden 在运行时并不会一直持锁写,但我在 cp 之前只停了容器,没确认 WAL 已经合并回去。

现在的做法是这样,先用 sqlite3 自带的备份命令,不要 cp:

docker stop vaultwarden
sqlite3 /volume1/docker/vaultwarden/data/db.sqlite3 \
  ".backup '/volume1/backup/vw/db-$(date +%F).sqlite3'"
docker start vaultwarden

如果不想停容器,可以走 Vaultwarden 自带的 admin 接口触发备份,但那个接口要开 ADMIN_TOKEN,我嫌多一个暴露面,就还是停容器,反正只有两个人用,停十几秒没人察觉。另外把 DATABASE_URL 显式写成文件路径,而不是让它默认,避免以后换目录时找错库。

为什么这样能行:.backup 走的是 SQLite 的在线备份 API,会把 WAL 里的内容一并落到目标文件,不需要你手工 checkpoint。cp 的问题是它只复制主库文件,WAL 和 shm 没跟上,恢复出来的库自然缺页。代价是备份期间写入被阻塞,不过这个量级无所谓。

失效的地方也得说清楚。第一,.backup 在机械盘上遇到大库会慢,我试过拿一个 200MB 的测试库,DS218j 上跑了将近 40 秒,期间容器是停的,如果库再大会很难受。第二,这个方案只适合单机 SQLite,哪天你迁到 PostgreSQL,这套脚本全部作废。第三,我踩过的坑是备份目录和 data 目录在同一块盘上,有次盘掉线两个一起没,现在备份落到 USB 外挂盘,每周手动拔一次。

你们在法国这边跑 Vaultwarden 的,备份是停容器还是走 admin 接口?有没有人试过在 ARM 机器上把 SQLite 换成 libSQL,值不值得折腾?

0
赞同度 100% · 0 条评论 · 1 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。