摘要

密码管理器的选型只有一条标准:数据必须在自己手里。这篇记录 vaultwarden(Bitwarden 的轻量 Rust 实现)在 CT700 上的完整落地:Docker 部署、nps 隧道 + nginx 公网化(pwd.028000.xyz)、SIGNUPS_ALLOWED=false 关注册、登录接口限流 + fail2ban 防爆破、每日 03:30 自动备份到 NAS(保留 14 天)。重点写了为什么选 vaultwarden 而不是官方 Bitwarden、WebSocket 和附件大小的 nginx 细节,以及"备份一定要恢复演练"的教训。

目录

一、为什么是 vaultwarden

密码管理器存的是一家人的数字身家,选型标准只有一条:数据必须在自己手里。用第三方密码服务,等于把最敏感的数据托付给别人的服务器和别人的安全团队。自建是唯一选项。

方案 结论
Bitwarden 官方服务端 功能全,但重(微软系技术栈、吃资源),个人用不上那么多
vaultwarden Bitwarden 的轻量 Rust 实现,API 兼容官方客户端,一个 Docker 容器搞定,资源占用小
1Password 等商业服务 数据不在自己手里,直接排除

vaultwarden 的最大优势是客户端兼容:手机、电脑、浏览器扩展全部用 Bitwarden 官方客户端,登录时把服务器地址填成自己的 pwd.028000.xyz 就行。服务端轻量,客户端成熟,两头都占了。

二、部署:CT700 上的 Docker

vaultwarden 跑在 CT700 这个 LXC 容器里(和 OpenList 的 CT701、docker-lab 的 CT702 是邻居)。部署方式 Docker Compose,一把梭:

# docker-compose.yml(关键片段,结构示意)
services:
  vaultwarden:
    image: vaultwarden/server:latest
    volumes:
      - /opt/vaultwarden/data:/data
    environment:
      # 关闭公开注册,铁律
      - SIGNUPS_ALLOWED=false

数据卷 /opt/vaultwarden/data 落在宿主,里面是 SQLite 数据库和附件。容器重建不丢数据,这是底线。

三、公网化:nps 隧道 + nginx

密码库要随时可用(手机上查密码是高频场景),所以必须公网化。链路:

手机/电脑 → https://pwd.028000.xyz
  → VPS 443(nginx:LE 证书,2026-12-30 到期,certbot 自动续期)
  → nps 隧道(VPS 28443 → 192.168.0.120:443,CT700)
  → vaultwarden

注意隧道目标是 CT700 的 443 端口(容器内 vaultwarden 配了 HTTPS),不是 80。这个细节别搞错。

nginx 反代有几个 vaultwarden 特有的配置点:

# 关键片段
server {
    listen 443 ssl http2;
    server_name pwd.028000.xyz;

    # WebSocket 支持(vaultwarden 的实时同步用)
    location /notifications/hub {
        proxy_pass http://127.0.0.1:28443;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # 附件上传大小
    client_max_body_size 500m;

    location / {
        proxy_pass http://127.0.0.1:28443;
    }
}

WebSocket:vaultwarden 的 /notifications/hub 是实时同步通道,nginx 必须配 Upgrade 转发,否则多端同步会有延迟或异常。附件大小:client_max_body_size 500m,密码库里经常存些证书、密钥文件附件,默认的 1m 肯定不够。HTTP 301 跳 HTTPS:全站强制,密码流量不允许明文。

四、安全加固:关注册、限流、fail2ban

密码库是全家最敏感的服务,加固按最高标准:

措施 配置 说明
关闭公开注册 SIGNUPS_ALLOWED=false 公网任何人都不能自助注册,见下节
登录接口限流 5 次/分钟 防密码爆破
全站 API 限流 60 次/分钟 防刷
fail2ban vaultwarden-limit jail,10 分钟 8 次 429 封 1 小时 第二道防线
TLS 仅 1.2/1.3,HSTS 传输安全

fail2ban 的 jail 是照着成熟模式配的:nginx 限流先挡,超限回 429,fail2ban 盯 429 日志,10 分钟内 8 次就封 IP 1 小时。这套模式在 vaultwarden 上首创,后来被复制到 OpenList、Halo、图床,全家统一。

五、SIGNUPS_ALLOWED=false 的含义与用户注册流程

SIGNUPS_ALLOWED=false 是 vaultwarden 最重要的安全开关,值得单独讲透。它的含义是:关闭公开注册接口,公网上的任何人都不能自助创建账号。注意它关的是"自助注册",不是"添加用户"——管理员还是可以邀请/创建用户的。

当时的真实操作流程是这样的:

  1. 部署时先保持 SIGNUPS_ALLOWED=true(或临时打开),完成初始化;
  2. 走官方注册页创建第一个用户账号(当时给用户新建的账号);
  3. 确认第一个账号能正常登录、客户端同步正常;
  4. 把 SIGNUPS_ALLOWED 改成 false,重启容器;
  5. 从公网访问注册页,确认已无法自助注册。

这个顺序不能反:如果一上来就设 false,第一个管理员账号都建不出来。以后需要给家人开账号,走管理员邀请流程,不开公开注册。账号密码用户自设,不记录明文。

六、自动备份:每日 03:30 到 NAS

密码库的备份是"丢了就全家抓瞎"级别的数据,备份策略按最高标准:

  • 频率:每日 03:30,systemd timer 触发;
  • 目标:NAS(CT700 内挂载 NAS 目录,备份直接写过去);
  • 保留:14 天滚动;
  • 内容:/opt/vaultwarden/data 整个目录(SQLite 数据库 + 附件)。
# systemd timer 示意:每天 03:30 执行备份脚本
# 备份脚本核心就是打包 + 按日期命名 + 清理 14 天前的
tar -czf /mnt/nas/backup/vaultwarden/vaultwarden-$(date +%F).tar.gz /opt/vaultwarden/data
find /mnt/nas/backup/vaultwarden/ -name "vaultwarden-*.tar.gz" -mtime +14 -delete

2026-10-01 部署当天就做了一次备份并校验通过。备份的铁律:没做过恢复演练的备份等于没备份。SQLite 文件的恢复就是停容器、解压覆盖、起容器,三步,演练一遍心里才有底。这个演练记在待办里,定期做一次。

另外注意备份时间 03:30 的选择:和 PVE 整机备份(02:00/03:00)、Google Drive 异地备份(04:00)错开,避免同一时间多个大 IO 任务打架。家里这套备份体系的时间表是统一规划过的。

七、验收清单

测试项 结果
公网 HTTPS 访问 正常,TLS 1.3
HTTP 301 跳 HTTPS 通过
注册页(关闭后) 无法自助注册
用户登录 正常
客户端同步 正常
限流(登录接口超限) 429
fail2ban 封禁正常
附件上传 正常(500m 以内)
每日备份 03:30 正常执行,NAS 上有文件

端到端验收全部通过后,才算交付。密码库这种服务,"差不多能用"是不够的,必须逐项确认。

八、踩坑记录

坑 1:隧道目标端口是 443 不是 80

CT700 内的 vaultwarden 配了 HTTPS,nps 隧道要打到 192.168.0.120:443。如果按惯性打到 80,隧道通了但握手失败,表象是"隧道是好的,服务连不上"。新增隧道时先确认目标服务到底在监听哪个端口。

坑 2:WebSocket 不配,同步异常

vaultwarden 的实时同步走 /notifications/hub 的 WebSocket,nginx 不配 Upgrade 转发,表现是"能登录、能看,但多端同步延迟或不同步"。这种"半正常"的状态最难排查,因为第一反应是客户端问题。记住:vaultwarden 的 nginx 配置里,WebSocket 那一段是必备的。

坑 3:附件默认 1m 不够用

nginx 默认 client_max_body_size 1m,密码库里存个证书、密钥文件经常超。配成 500m,一步到位。所有带文件上传的服务,部署时都要检查这一项。

客户端使用指南:手机、电脑、浏览器扩展

vaultwarden 的服务端只是"仓库",日常用的是客户端。全家统一用 Bitwarden 官方客户端,登录时服务器地址填 https://pwd.028000.xyz:

客户端 说明
手机 App Bitwarden 官方 App,iOS/Android,自填/指纹解锁
电脑桌面端 官方桌面应用,剪贴板自动清除记得开
浏览器扩展 最常用,自动填充、右键生成密码

三个习惯要养成:主密码足够强(它是唯一钥匙,丢了谁也找不回来)、开两步验证(TOTP,存在手机验证器里)、定期导出备份(加密 JSON,存 NAS 私密配置)。密码管理器本身的安全,靠的是主密码 + 2FA,服务端加固只是外层。

组织与分享:家庭密码管理

密码多了要分类,vaultwarden 支持文件夹和组织(Organization):

  • 按"个人/家庭/工作"建文件夹,条目多了不迷路;
  • 家庭共用的账号(宽带、NAS、视频会员),建组织共享给家人,不用微信发密码;
  • 每个条目写清用途和备注,半年后自己还看得懂。

组织分享的权限分"可看/可改",默认给可看。家人离席(比如孩子长大分家),组织里移除就行,不用一个个改密码。

密码学的常识:主密码与零知识

vaultwarden 的安全,建立在两个密码学常识上,值得每个用户理解。

主密码是唯一的钥匙。 vaultwarden(和 Bitwarden)是"零知识"架构:你的主密码在本地派生出加密密钥,密码库在本地加密后,才上传到服务器。服务器存的是密文,没有你的主密码,服务器自己也解不开。这意味着:主密码丢了,谁也找不回来——包括你自己,没有"找回密码"。主密码的强度,就是整个密码库的强度。建议:四个随机单词的组合(比如"正确-马-电池-订书钉"那类),好记又够强。别用生日、别用重复密码。

两步验证是第二把锁。 主密码再强,也怕键盘记录、钓鱼。TOTP 两步验证(手机验证器 6 位数)堵的是"密码泄露":攻击者拿到你的主密码,没有你的手机,还是进不去。开 2FA 的代价是每次登录多输 6 位数,收益是"密码泄露也不丢库"。这笔账,划算。注意:2FA 的恢复码要抄下来存好(NAS 私密配置),手机丢了靠它救命。

零知识的边界:零知识保护的是"服务器看不到你的密码",不保护"你的设备被黑"。手机中了木马,键盘记录把主密码偷了,零知识也救不了。所以设备安全(系统更新、不装来路 App)和主密码安全是一体的。密码管理器解决的是"密码太多记不住"的问题,不是"设备被黑"的问题。分清边界,才能正确使用。

家庭密码管理的分工:谁管什么

密码库搭好了,家庭密码管理还要分工。不然密码库变成"你一个人的",家人继续用"123456"。

分工一:管理员(你)。 管 vaultwarden 的服务端(备份、升级、加固)、管组织(建共享、拉人踢人)、定规矩(主密码强度、2FA 必须开)。技术的事,你全包。

分工二:家人。 只做三件事:装客户端、设强主密码、开 2FA。别让他们管服务端,别让他们记服务器地址(浏览器收藏夹存好)。家人的学习成本,压到最低:能自动填充,就别让他们复制粘贴。

分工三:应急。 万一你不在,家人要查密码,怎么办?应急方案:指定一个"应急联系人"(比如配偶),他的 vaultwarden 账号在组织里,能看到家庭共享的密码;你的个人密码,写一份纸质 sealed(信封封好,存保险箱),注明"紧急时拆"。纸质是最后的兜底,平时不用,关键时救命。

分工四:交接。 密码库的" root 权限"(vaultwarden 管理员、NAS 私密配置),要有一个交接文档:万一你长期不在,谁接手、怎么接手。文档存 NAS 私密配置,家里人知道在哪。这不是悲观,是负责。数字遗产,和实体遗产一样,要安排。

密码管理的终点,不是"技术多牛",是"家人会用、出事有人接"。技术是手段,人才是目的。

主密码忘了:真的没办法

零知识架构下,主密码忘了,密码库就是一堆打不开的密文。没有"找回密码",没有"客服重置"。唯一的救命稻草:2FA 恢复码 + 应急纸质备份。2FA 恢复码能让你在丢手机时重设验证器,但主密码忘了,恢复码也救不了。所以主密码的备份,是"纸质 sealed 信封存保险箱"级别的事。写下来,封好,放好。这不是"不安全",这是"权衡":纸质丢了的概率,远小于"忘了主密码"的概率。两害相权,纸质赢。

九、总结

vaultwarden 的落地链条:轻量选型(Rust 实现、兼容官方客户端)→ Docker 部署 → nps 隧道 + nginx 公网化(WebSocket、500m 附件、301 跳转)→ 关注册 + 限流 + fail2ban 三层加固 → 每日 03:30 自动备份到 NAS。密码库是全家安全体系的"根",它的加固模式(限流 + fail2ban)后来成了全家的统一标准。记住两条铁律:SIGNUPS_ALLOWED=false 常年开启;备份不做恢复演练等于没备份。

相关阅读:《WireGuard 组网实战:把管理面板藏进 VPN》、《fail2ban 实战:从 SSH 到 Web 登录接口的防护》。