基于Vaultwarden和Keyguard的自托管密码管理实践
注:题图使用 Gemini 生成。
几年来我一直在市面上的主流密码管理方案间游走,上一个让我暂时安顿下来的是 Enpass。倒不是它体验有多出色,纯粹是因为「家人们」订阅了 Google Play Pass 能直接解锁高级版。直到前段时间订阅涨价,我们一致决定不再续费。我需要给手里这三四百个密码再次搬个家。
此时环顾一圈各家产品,可选项依然各有各的堵心:1Password 虽好,错过拼车好价就只能支付高昂的订阅费用;LastPass 安全丑闻频出,让人多少有些望而却步;KeePass 硬核且开放,但跨平台体验碎片化严重——最终选择回到 Bitwarden 算不上是最优解,但使用 TOTP 无需多装一个 2FA 应用这事儿也得额外付费,并且一直以来它们的客户端体验在上述产品中也并不算拔尖。
但 Bitwarden 另有所长——碰巧家里有一台 24 小时开机的 NAS,自托管一个 Vaultwarden 自然而然提上了日程。
为什么是 Vaultwarden
Vaultwarden 是一个由社区维护的非官方开源 Bitwarden 后端服务。与官方那套基于 .NET 和笨重数据库的自托管后端相比,Vaultwarden 镜像极其轻巧,常驻内存通常不过百兆;不仅核心功能完备,还能直接从后端解锁 TOTP 管理、多人共享等高级功能,非常适合个人和小微团队自建使用。
NAS 部署的首选方式
Vaultwarden 的部署方式多种多样,对于 NAS 来说,Docker 无疑是第一选择。一方面 Vaultwarden 的 Docker 镜像小巧、部署简单,无论你是否有相关经验都很容易上手;另一方面是在做好目录映射后,可以使用 NAS 本身的文件同步或备份功能保障数据安全。
Vaultwarden 的 Docker 部署过程不需要折腾太多参数,社区提供的 Docker Compose 模板也简单明了。如果你和我一样使用零售的成品 NAS(如极空间、绿联等),我们甚至都不需要去看 Compose 文件,直接在系统的图形化 Docker 部署界面就能搞定。
以下是几个我认为在部署时需要注意的几个参数:
- 镜像拉取:使用
vaultwarden/server的latest标签,更新容器时只需重新拉取镜像,在做好第 2 点的前提下,不会影响已经保存的密码数据。 - 目录映射:为了持久化保存密码库,我们需要将容器内部的
/data目录映射到 NAS 中的实体文件夹,以后需要手动备份或迁移到其他设备上时,直接复制该文件夹即可。 - 对于 Docker Compose 部署,我们在模板中找到
volumes字段下包含:/data的值,将冒号前面的路径替换为你在 NAS 上提前建好的真实文件夹路径(如/mnt/nvme16/bigk/Docker/vw/data:/data)。 - 端口映射:容器内默认使用
80端口,直接使用宿主机网络极易产生端口冲突,因此需要修改环境变量中的ROCKET_PORT,或推荐使用 bridge 网络并将80端口映射为 NAS 主机上的其他端口。 - 对于 Docker Compose 部署,我们需要确保
network_mode为"bridge"(或干脆不配置该字段),并在ports字段下找到包含:80的值,将冒号前的端口号改为你想使用的 NAS 主机端口号(如8808:80)。 - 访问和连接:Vaultwarden 要求可信的网络连接,在非
localhost环境下需要配置 HTTPS,因此需要提前做好准备,包括签好证书、配置反代或者找一个靠谱的内网穿透工具。
无论是图形化配置还是 Docker Compose,都强烈建议在环境变量(environment 字段)中配置 DOMAIN 的值为你要从公网连接进来的域名。
图形化部署的情况下,修改环境变量后可能需要重新创建容器;使用 Docker Compose 部署时,建议将环境变量写进 .env 文件中并由 Docker Compose 文件引用,后续维护和配置权限会更加方便。
Docker 部署完成后,我们可以使用浏览器输入 IP 地址和端口号访问 Vaultwarden。当浏览器显示 Vaultwarden 页面时,说明部署成功。但这并不代表我们已经可以使用它。
HTTPS 与互联网访问
正如前面所提到的,除非直接在 NAS 本地的 localhost 网络环境访问,否则直接用局域网 IP 打开,Vaultwarden 只会弹出拒绝访问的警告页面。
这是因为现代浏览器中有一道「安全上下文」的强制策略,密码管理器网页端所依赖的 Web Crypto API 加密接口只有在可信网络中才能被调用,而家庭内网常见的 HTTP 连接会被判定为不可信网络,Vaultwarden 发现无法调用该接口就会直接给出警告提示。
同理,如果我们需要随时随地都能访问到 Vaultwarden 的数据库(例如在公司电脑浏览器中使用 Bitwarden 自动填充插件),也必须通过可信的 HTTPS 连接。
Vaultwarden 内置了 HTTPS 功能,不过官方 Wiki 中已经明确表示这种方式不成熟,仍然建议大家使用反向代理来处理 HTTPS 请求,并通过 Let's Encrypt 或 Cloudflare 获取 SSL/TLS 证书。然而反向代理对网络环境有着严格要求,国内运营商的家庭宽带基本都是大内网,好一点的 NAT 1 可以借助 STUN 服务「打个洞」获得相对稳定的公网访问体验,而其他 NAT 类型多少都需要折腾一番。
不过你既然能看到这里,相信你已经非常了解反向代理的原理和各类工具的使用了,本文不再赘述。
如果你家和我一样是低等级 NAT,或者单纯只是想省事不折腾,那么我强烈推荐使用「赛博菩萨」Cloudflare 的 Tunnel 隧道功能。它能够将内网服务安全地映射出去,不仅能顺手解决 SSL/TLS 证书的麻烦,还能获得免费的 DDoS 防护、访问控制等网络安全能力。配置 Cloudflare Tunnel 也是易如反掌:
- 登录 Cloudflare 进入控制台,在左侧导航栏中进入「Zero Trust」,在新页面的导航栏中展开「网络」,进入「连接器」功能;
- 在打开的「隧道与网状网络」页面,点击「创建隧道」,选择「cloudflared」后根据指引继续操作;
- 来到安装 cloudflared 客户端的指引界面,根据所用系统选择安装 cloudflared 客户端(如需在 NAS 上安装依然推荐 Docker 方式);
- 从这一步开始,我们需要根据自身的实际情况进行操作:
- 如果你有自己的域名且已经托管到了 Cloudflare 中,那就直接运行页面中的命令建立连接,然后前往「已发布应用程序路由」页面中添加二级域名映射;
- 其他情况则需要使用
cloudflared tunnel --url http://[IP]:[Port]命令,将内网中的 Vaultwarden 访问地址映射至一个https://*.trycloudflare.com形式的临时域名中。 - 尝试通过域名访问 Vaultwarden 的页面,如果你能在浏览器地址栏中看到 HTTPS 连接,且可以正常显示登录页面,那么我们整个链路便跑通了。
需要注意的是,虽然没有域名也能搭建隧道,但 Cloudflare 给出的域名仅仅是临时地址,不仅名字又长又难记,而且每次重启服务后域名都会变化,因此我更建议去买一个便宜的域名然后托管到 Cloudflare。这是一个一劳永逸的方法,以后不止是 Vaultwarden,你家中所有的内网服务都可以在该域名下挂二级域名使用,并通过 Cloudflare Tunnel 实现更安全的内网穿透。即便你的服务遍布于不同设备、不同地理位置,也只需要在对应设备上安装一个 cloudflared 客户端并映射在同一域名下即可,完全不需要额外付费。
必要的权限管理
搞定公网访问后,我们已经可以创建账号、保存密码、跨设备同步了——你对象也可以,你表姑的邻居和那位邻居儿子同学的篮球队友也可以。
默认情况下,Vaultwarden 允许任何人注册账号,假如有人手抖输错了网址碰巧进入到了这个域名或者被脚本扫描到了,那他们可以在你的 Vaultwarden 服务中注册自己的账号并使用,甚至还能上传各种附件文件。
虽然这不太会影响你账号下的数据安全,但你也不想让自己的私有服务变成公共的免费网盘对吧?
所以在我们注册好自己的账号后,需要立即将 SIGNUPS_ALLOWED 这个环境变量的值设为 false(没有就新建一个变量)后重新部署容器,之后即使有人访问了你的服务也无法注册账号。
除了关闭注册,还有一件事与密码库的安全息息相关,那就是整个 Vaultwarden 的管理后台(即 /admin 页面),这个管理后台掌控了整个 Vaultwarden 服务和数据库。管理页面默认就是关闭的,不开启也完全不影响使用,但对于有着更高自定义需求的用户,我们需要在环境变量中设置 ADMIN_TOKEN 字段并添加一个极为复杂的 Token 值才能启用。
考虑到密码管理器并不是一个需要频繁调整设置的工具,所以我更建议在配置完成后删掉 ADMIN_TOKEN 字段,彻底关闭后台的访问功能,也不用再去管什么 Argon2 PHC 令牌保护了。

此外,Vaultwarden 同样支持主账号的 2FA 两步验证登录,验证方式包括 TOTP 验证码、通行密钥以及由 Duo Security 生成的验证代码。为了安全起见,在配置 2FA 时务必妥善保管 Vaultwarden 提供的紧急恢复代码。
迁移与使用
剩下的事情就简单得多了,登录后进入到「工具」页面,选择「导入」后就能快速迁移密码库。Vaultwarden 可以导入市面上绝大多数主流密码管理器的数据格式,我这三四百条密码数据直接选择「Enpass (JSON)」就能完美解析。在确认所有登录方式都迁移完成之前,我建议最好不要立即卸载上一个密码管理工具或清空密码库。有必要让两种工具并行一段时间。

浏览器插件方面,因为安全和生态的原因,目前依然只有 Bitwarden 官方插件可用,安装插件后选择自托管服务,输入刚才在 Cloudflare 发布的二级域名并登录后即可获得完整的自动填充功能。
至于移动端,为了兼顾多平台复用,Bitwarden 官方 App 带着一种明显的「移植感」,使用体验放到 2026 年实在算不上优秀。几年前我还在使用 Bitwarden 时,也经常会遇到手机端自动填充抓取失败、解锁无响应的糟心情况。
在 @克莱德 的推荐下,我更换了第三方客户端 Keyguard。这是一个开源的密码管理器前端工具,支持 Windows、macOS、Linux 以及 Android 和 Wear OS 平台,兼容 Bitwarden 和 KeePass 密码数据。其 UI 设计、交互逻辑和动画效果相比官方客户端都更加出色。

更重要的是,主流密码管理服务从 9 月初开始陆续支持了通行密钥的迁移,如果你在 Keyguard 设置中点击你的用户名,然后选择「从其他应用导入」,即可从其他支持通行密钥的密码服务中直接迁移通行密钥,免去了很多重新配置的繁琐流程。

Keyguard 还可以接管 Android 版 Chrome 浏览器的「第三方自动填充」服务。这是一项从 Android 14 开放的新特性,第三方密码管理器能够匹配网页 DOM 元素实现更准确的密码填充。加上 Keyguard 极其稳健的密码库本地保存功能,即使因为 Cloudflare 网络波动无法连接到自建数据库,它也能正常使用。

在使用官方 Bitwarden 服务的情况下,如果你有 TOTP 需求,也可以使用 Keyguard,因为 Bitwarden 实际上并未在服务端给免费用户封禁 TOTP 功能(端到端加密也看不出来里面保存了什么),只是前端没有给免费用户开放入口。Keyguard 可以绕过这一限制,不过在浏览器中可能需要你手动打开 Keyguard 复制验证码。
我在之前的《派评 | 近期值得关注的 App》中已经对 Keyguard 进行了简要介绍,感兴趣的朋友可以前往了解。
写在最后
目前这套密码管理体系已经稳定运行了一段时间,最近几天我还梳理了密码库分类、创建数据冷热备份等锦上添花的工作,这种感觉就像搬进新家后,总会忍不住仔细收拾家务一样。
自己搭建一套服务、打通前后端链路,听起来好像很复杂,但只要跑通过一次,后续再搭建其他服务也都是万变不离其宗。而且各类开源产品的玩法越来越丰富、配套越来越完善,自托管服务能带来比商业成品更可控、更自由的使用体验。
更别说现在还有 AI 加持,不懂的问题就截个图、问两句,配置过程中还能学到很多技术原理——如果你正在寻找密码管理服务或者需要一个能够自己掌控数据的新选择,希望本文所述的方案能够为你提供必要的参考。
> 关注少数派小红书,感受精彩数字生活 🍃
> 实用、好用的正版软件,少数派为你呈现 🚀
4位派友已充电