自托管密码管理器:实际需要付出什么
自托管一个密码管理器,意味着由你自己来运行那个加密同步服务器。你的客户端在设备上加密;你运营的服务器存储密文并为你做身份验证。那台服务器一旦被攻破,落到对方手里的是一个加密的 blob,而不是一份密码清单。
这是一项真实且持久的隐私收益。它同时也是一份维护承诺,而本文诚实的版本会把两者都讲清楚。
自托管实际改变了什么
这一点要说准确,因为期待出错的正是这里:
| 厂商云 | 自托管 | |
|---|---|---|
| 谁能读取你的保险库 | 没有人,前提是零知识 | 没有人,前提是零知识 |
| 谁能 删除 你的保险库 | 厂商 | 你 |
| 谁能看到元数据 | 厂商 | 你 |
| 谁可能被强制交出数据 | 厂商,在他们的司法辖区 | 你,在你的司法辖区 |
| 可用性责任 | 厂商 | 你 |
| TLS、打补丁、备份 | 厂商 | 你 |
| 成本 | 订阅费 | 服务器 + 你的时间 |
机密性方面的结论并没有改变。改变的是 对存储平面的控制权,以及信任链中都有谁。自托管移除的是第三方;它不会增加密码学。
什么时候值得
- 你已经在运行一些服务,并且有 NAS、家庭实验室或一台小型 VPS。
- 你的威胁模型里包含「服务商被攻破或被胁迫」。
- 你所在的司法辖区里,别人的数据托管对你是一种风险敞口。
- 你想为一个团队在你审计过的基础设施上提供共享集合。
- 你是那种享受五分钟 Docker Compose 加一个 cron 任务的人。
什么时候不值得
- 你从未运行过反向代理,需要先学 TLS、DNS 和防火墙规则。
- 不会有人记得打补丁。未打补丁的服务器是一种风险敞口,而不是安全上的胜利。
- 你是唯一用户,只在一台设备上。那就完全跳过服务器,用本地保险库。
- 你对一个业务关键系统需要保证的可用性,却没有任何备份计划。
对于后两种情况还有一条中间路线:一个 本地加密保险库,配合用于你自己设备的 Nearby 局域网同步,完全不要服务器。
五分钟搭起来
OpenKey Server 是一个带 PostgreSQL 的 FastAPI 应用,以 Docker Compose 栈的形式提供。
cd openkey_server
cp .env.example .env
openssl rand -hex 32 # paste this into JWT_SECRET in .env
docker compose up --build -d然后确认它状态健康:
| URL | 用途 |
|---|---|
http://localhost:8000 | API 基址 |
http://localhost:8000/docs | OpenAPI 文档 |
http://localhost:8000/health | 健康检查 |
架构迁移会在启动时自动运行。从 设置 → 数据 → 自托管服务器 连接一个客户端,然后在第一台设备上 注册,其余设备 登录。完整细节见服务器设置。
加固清单
这是人们会跳过的部分,而它恰恰决定了自托管究竟有没有帮上忙。来自安全指南:
不可妥协
- 一个至少 32 个字符的唯一
JWT_SECRET。 占位符值会在启动时被拒绝。自己生成一个;不要照抄示例。 - 带有效证书的 HTTPS。 客户端使用平台 TLS 栈且没有证书固定,因此一个拼错的
http://URL 或一张坏证书,就会在登录和同步时开启中间人攻击。请在 Caddy、nginx 或你的负载均衡器上终结 TLS。 - 明确的
CORS_ORIGINS允许列表。 绝不要用*。如果你使用浏览器扩展,请显式加入它的chrome-extension://和moz-extension://来源。 - Postgres 和原始 API 端口保持私有。 只暴露反向代理。
- 在代理上设置 HSTS,这样浏览器在首次访问后就绝不会回退到 HTTP。
强烈建议
- 在反向代理上做速率限制。 API 内建的限流器是内存中的,且 按工作进程 计算,所以在有多个工作进程或副本时,实际生效的上限会成倍增加。在 nginx 中加
limit_req,或在边缘加上 Caddy 速率限制。 - 仅当代理会覆写
X-Forwarded-For且你信任该路径时,才设置TRUST_PROXY_HEADERS=true。否则你的按 IP 限制会作用在代理上,而不是用户身上。 - 警惕邮箱枚举。
POST /auth/prelogin和POST /auth/lookup-public-key对未知邮箱返回 404,这有助于合法客户端,但也让人可以探测哪些地址已注册。请使用严格的速率限制和 TLS;对高敏感部署,还可选择使用 VPN 或 IP 允许列表。 - 备份 Postgres 并测试恢复。 一个从未从备份中恢复过的密码管理器服务器,只是一个假设。
- 监控
/health和 API 日志;一旦它停止响应就告警。
自托管同步服务器能做什么、不能做什么
| 它能 | 它不能 |
|---|---|
通过你的 auth_hash 验证你的身份 | 读取你的主密码 |
| 为条目、附件、组织和共享存储不透明密文 | 解密集合名称或条目载荷 |
| 删除或扣留你的数据 | 恢复一个被遗忘的主密码 |
| 看到元数据:邮箱、密文大小、时间规律 | 从数据库中重建你的保险库 |
| 由你来限流、打补丁或重启 | 在你忘记主密码后还能撑住 |
仔细读第四行:自托管服务器 不会 让你更能免于忘记密码的风险。它把一方从信任链中移除,同时把你加进来,成为那个可能丢失数据的运营者。忘记主密码 讲的是如何预防这一侧。
在依赖它之前你该知道的同步语义
- 按每项
revision最后写入获胜,而不是 CRDT。 两台设备上的并发编辑可能互相覆盖。重要时请一次只在一台设备上编辑。 - 删除会以墓碑形式同步,直到对端追上,因此删除在各处都不是立即生效的。
- Nearby 局域网同步使用同样的最后写入获胜规则,在已配对、已链接保险库的设备之间。
- 两者都不是备份。 至少保留一份加密的本地备份(OpenKey 中为
.okbak)。
最后这一点是最常被人弄错的,而它正是「我把保险库搬到了自己的服务器」和「我有一套恢复方案」之间的区别。
面向运营者的运维安全
- 把服务器运行在一台你有固定打补丁计划的主机上。未打补丁比交给厂商托管更糟。
- 把
JWT_SECRET放在密钥管理器中,或至少放在权限为 600 的文件里,而不是你的 shell 历史中。 - 日志保留是一种风险敞口:同步日志可能暴露时间规律和数据大小。轮转它们并设置上限。
- 备份 数据库,而不只是卷,并每季度验证恢复。
- 绝不要在没有 TLS 的不受信网络上暴露 API。
- 如果你需要可用性保证,就在负载均衡器后面放第二台主机,并接受同步冲突解决仍然是最后写入获胜这一事实。
OpenKey 如何让服务器对攻击者毫无用处
- 客户端用 Argon2id 从邮箱 + 主密码 + 盐派生主密钥。
- 登录会发送一个
auth_hash,它在证明知识的同时不泄露密码。 - 一把 保险库密钥 用 AES-256-GCM 加密集合名称和条目载荷。服务器只存储被包装的保险库密钥。
- 访问 JWT 生命周期很短;刷新令牌在静态存储时被哈希,并在使用时轮换。
- 附件以密文同步,每个上限 20 MB。
一份被盗的 postgres 转储只会给攻击者带来盐、KDF 参数、包装密钥和 blob。破解它意味着要攻击 Argon2id,而即便如此,他们手中的仍是没有密钥就读不懂的密文。这就是全部的安全论证,而它之所以成立,恰恰是因为主密码从未离开过客户端。
搜索数据说明
自托管是一个规模不大但真实存在的查询簇,而且它更多是围绕「open source」这个说法聚集,而非围绕「self-hosted」。Google Trends(全球范围,过去 12 个月)将这些词互相比较:
| 查询 | 簇内相对关注度 |
|---|---|
| passbolt | 100 |
| open source password manager | 55 |
| password manager self hosted | 13 |
| self-hosted password manager | 4 |
| keepass alternative | 1 |
这意味着「open source」是人们首先想到的说法,而「self-hosted」是他们随后落脚的说法 — 一次以偏好开始、以实现方式结束的搜索。「open source password manager」下的相关查询指向同一方向:KeePass 为 100,「open source password manager self hosted」为 84,Passbolt 为 78。前三名中有两个是人们正在比较的产品名,而不是某项功能的描述。
与头部词条相比,这些数字仍然很小。「Self-hosted password manager」是小众中的小众,而诚实的结论是:搜索这个短语的大多数人,是那些已经清楚自己想要什么的技术用户。
Method: Google Trends,全球范围,过去 12 个月,2026 年九月提取。数字为归一化的相对关注度(0–100),而非搜索量。
五分钟版本
自托管是在信任链中用你自己替换掉服务商。它不会增加密码学,它给你的清单上增加的是 TLS、备份、打补丁和速率限制。如果你已经在运行服务:Compose 栈、唯一的 JWT_SECRET、带有效证书的 HTTPS、明确的 CORS_ORIGINS,以及经过测试的备份。如果你没有,则改用本地加密保险库加 Nearby 局域网同步,并且无论哪种方式都至少保留一份加密的离线备份。
下一步
- 为何自托管你的密码保险库 — 支持这么做的理由
- 零知识同步详解 — 协议
- 服务器设置 — 安装、配置、生产环境加固
- 安全 — 威胁模型与运营者清单
