密码这事儿,我决定自己管

去年 LastPass 第二次被爆库的时候,我终于下决心迁移密码了。

不是在 LastPass 上一秒还在用下一秒就走的果决,是拖了大概半年。期间我一直在找一个替代品,要求就两个

  • 数据在我自己手里
  • 多个设备能同步

试过 KeePass 配坚果云,文件同步没问题,但手机端体验是真的烂。后来发现了 Vaultwarden。

Vaultwarden 是 Bitwarden 官方服务器端的 Rust 重写版,API 完全兼容。意思是 Bitwarden 客户端能直接用,浏览器扩展、手机 App、桌面端都不需要换,但服务器是你自己的。一句话总结:Bitwarden 的全功能,自己跑。

这篇文章把我搭建的完整流程记下来。如果你想自己管密码,跟着走一遍应该够。

为什么是 Vaultwarden

自托管密码管理器有几种选择

  • Bitwarden 官方自部署。Docker 镜像有,但吃内存,1GB 起步。
  • Passbolt。团队向,单人用不合适。
  • Teampass。UI 老旧。
  • Vaultwarden。对个人最友好,256MB 内存能跑,几万条密码不在话下。

我选了 Vaultwarden。理由很简单,客户端就是 Bitwarden,全平台覆盖,体验已经打磨得足够好。服务器端是个 30MB 的二进制,跑在 Docker 里。

准备

你需要这些

  • 一台服务器。家里的 NAS、便宜的 VPS、淘汰的笔记本都行。要求不高,1 核 512MB 内存足够。我跑在一台 1 核 1GB 的小鸡上,目前占用 80MB 内存。
  • 一个域名。https://vault.example.com。内网用 IP 也能跑,但 HTTPS 证书得自己签,多设备同步会麻烦。如果你有公网 IP,强烈建议搞个域名。
  • Docker 和 Docker Compose。

服务器和域名你大概率已经有了。下文假设你装了 Docker。

部署

新建一个目录,比如 /opt/vaultwarden,里面建一个 docker-compose.yml

version: '3'
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: https://vault.example.com
      SIGNUPS_ALLOWED: 'true'
      INVITATIONS_ALLOWED: 'true'
      SHOW_PASSWORD_HINT: 'false'
      LOG_LEVEL: warn
    volumes:
      - ./data:/data
    ports:
      - '8080:80'

几个关键参数解释一下

  • DOMAIN。这个影响客户端跳转的链接,必须是带协议的完整 URL。错了客户端会一直跳错。
  • SIGNUPS_ALLOWED。我这里临时开 true,因为要建第一个账号。建完立刻改成 false,否则会被脚本扫。
  • ./data:/data。所有数据都存这里,备份就备份这个目录。

启动

docker compose up -d

第一次启动会拉镜像,比较慢。起来之后访问 http://your-server:8080,能看到登录页就成功了。

第一个账号

立刻注册一个账号。注册完最重要的一件事,把 docker-compose.yml 里的 SIGNUPS_ALLOWED 改成 false,然后重启

# 编辑文件
nano docker-compose.yml
# 把 SIGNUPS_ALLOWED: 'true' 改成 'false'
# 重启
docker compose restart

这个坑我第一次踩过,忘了关注册,结果一周后服务器多了 8 个陌生账号。

启用 HTTPS

光 HTTP 不行,密码同步走 HTTP 等于裸奔。这里我推荐用 Caddy 反代,自动申请 Let’s Encrypt 证书。

新建一个 Caddyfile

vault.example.com {
    reverse_proxy localhost:8080
}

启动 Caddy

docker run -d \
  --name caddy \
  --network host \
  -v /opt/caddy/Caddyfile:/etc/caddy/Caddyfile \
  -v caddy_data:/data \
  -v caddy_config:/config \
  caddy:2

caddy_data 这个卷会缓存证书。第一次启动会等几十秒做 ACME 验证,完事儿之后 https://vault.example.com 就有小绿锁了。

如果你用 Nginx 也行,但配置 Let’s Encrypt 自动续期要折腾一下。Caddy 是开箱即用。

接 Bitwarden 客户端

服务器地址填 https://vault.example.com,账号密码就是刚才注册的那套。

  • 浏览器。Chrome / Edge / Firefox 都有 Bitwarden 扩展,登录后会同步所有密码。
  • 手机。App Store 或 Google Play 搜 Bitwarden,登录服务器用自建 URL。
  • 桌面。Bitwarden 桌面端基本是浏览器扩展套壳,但偶尔用。

所有设备登录一次之后,改密码、添加条目都会自动同步,双向的,秒级延迟。

导入旧密码

Bitwarden 网页端有「工具 → 导入数据」。支持 Chrome、LastPass、1Password、KeePass 等等十几种格式。

我的迁移路径是

  1. Chrome 导出 CSV
  2. Bitwarden 导入
  3. 逐条检查,尤其是特殊字符的密码,CSV 经常炸

提醒一下,CSV 是明文,导入完就删。

备份

Vaultwarden 的数据全在 ./data 目录。最简单的备份是定时把这个目录打包丢到对象存储。

# 手动备份
tar czf vault-$(date +%Y%m%d).tar.gz /opt/vaultwarden/data

我做的是每天凌晨 3 点跑一次 rsync 到家里的 NAS。脚本就不贴了,rsync 命令网上一搜一堆。

备份是救命用的。哪天服务器炸了,Vaultwarden 重建只要 5 分钟,但数据丢了就真的没了。

几个小坑

  • HSTS 缓存。你先用 HTTP 访问过,后来改 HTTPS,浏览器会一直拒。换个浏览器或清 HSTS 缓存。
  • 客户端服务器地址格式。必须是 https://vault.example.com,带端口也行(https://vault.example.com:8443),但不能带路径。
  • Organizations 不开。Bitwarden 的组织功能(团队共享密码)个人用不到。Vaultwarden 默认支持,但建议保持关闭状态。
  • 别忘了关注册。前面说过,再强调一遍。

我用了大半年,体感如何

最大的变化不是安全,是便利。Chrome 自动填充、Brave 同步、手机指纹解锁全用一个主密码管着。半年下来我大概新建了 200 多条记录,从银行到各种论坛。

主密码只有一个,20+ 位,大小写数字符号混。这个密码记在脑子里,不存任何地方。建议用密码短语,比如「我家猫爱吃三文鱼鱼罐头2024」,再加几个符号,就够安全又记得住。

如果哪天 Vaultwarden 项目死了(不太可能,社区很活跃),导出 JSON 重新导入到任何 Bitwarden 兼容的服务就行。数据是标准格式,不被绑架。

收尾

密码这事说大不大说小不小。LastPass 那两次事故是前车之鉴,商业密码管理器也保不齐被端。自托管不一定比云服务更安全,但至少不会因为别人被一锅端而波及。

如果你只想要一个简单方案,跟着本文的 docker-compose 抄一遍,二十分钟能跑起来。后面所有密码都丢进去,从此只记一个主密码。

种下你的想法

在花园里留下一条评论,和这篇文章一起生长。

COMMENTS