我朋友有个习惯:所有网站的密码都让 Chrome 记住。

上次他电脑重装系统,浏览器没登录账号,收藏夹、密码全丢了。找了半天,最后靠手机上一个一个试,折腾了一晚上。

我问他为什么不买个密码管理器,他说 1Password 一年三百多,有点贵。

那就自己搭一个。Vaultwarden,Bitwarden 的轻量实现,一个容器,几十兆内存,功能该有的都有。

这篇是完整部署记录。

Vaultwarden 是什么

Bitwarden 官方服务端是 Java 写的,跑起来要好几 G 内存。

Vaultwarden 是社区用 Rust 重写的实现,兼容 Bitwarden 的官方客户端,一个容器 100M 左右内存就能跑。

我自己用了小半年,密码、密钥、银行卡信息全在里面。

一、先解决 HTTPS 问题

这一步不能跳。

Bitwarden 的所有客户端都强制要求 HTTPS,用 http 连不上(浏览器插件直接报错,手机 App 也不行)。

所以顺序是:

  1. 先准备好域名解析(比如 vault.你的域名.com 指到服务器)
  2. 先搭好 Nginx Proxy Manager 或者手写 nginx 配证书
  3. 再启动 Vaultwarden

我这边是用 Nginx Proxy Manager 套的证书,后面有一篇专门写它。

二、compose 配置

services:
  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    restart: unless-stopped
    environment:
      - DOMAIN=https://vault.你的域名.com
      - SIGNUPS_ALLOWED=false
      - INVITATION_ALLOWED=true
      - ADMIN_TOKEN=换成你自己的长随机串
      - TZ=Asia/Shanghai
    volumes:
      - /opt/docker/vaultwarden/data:/data
    ports:
      - "127.0.0.1:8222:80"
    mem_limit: 256m

几个参数解释一下:

参数作用
DOMAIN你的访问地址,客户端用它拼 WebSocket 和邀请链接,必须填 https
SIGNUPS_ALLOWED是否开放注册。装完先设 true 注册自己,再改 false
INVITATION_ALLOWED允许管理员发邀请
ADMIN_TOKEN管理面板的口令,必须设,不设就没法进 /admin

注意端口映射写成 127.0.0.1:8222:80,只监听本机,外网通过反代进来。直接暴露 8222 到公网,等于把密码库挂在公网上。

三、启动并注册

cd /opt/docker/vaultwarden
docker compose up -d
docker compose logs -f

看到 Rocket has launched from 就起来了。

先把 SIGNUPS_ALLOWED 设成 true,重启容器,然后访问 https://vault.你的域名.com 注册第一个账号。

注册完立刻改回 false:

docker compose down
# 编辑 compose,SIGNUPS_ALLOWED 改成 false
docker compose up -d

四、客户端配置

浏览器插件:Chrome 商店搜 Bitwarden,装完点设置,服务器地址填 https://vault.你的域名.com,然后用刚才注册的账号登录。

手机 App:应用商店搜 Bitwarden,登录前先点设置里的"自托管环境",填同样的地址。

桌面客户端:官网下载 Windows/Mac 版,同样改服务器地址。

登录后会自动同步,新增的密码在各端都能看到。

五、管理面板

访问 https://vault.你的域名.com/admin,输入 ADMIN_TOKEN 进去。

能做这些事:

我给朋友开了个账号,他自己维护自己的密码,我看不到他的内容——Vaultwarden 里每个用户的密码库是加密隔离的,服务端只有密文。

六、备份:这一步千万别省

密码库丢了,比丢手机还麻烦。

Vaultwarden 的数据全在 /opt/docker/vaultwarden/data 里,核心是 db.sqlite3。

备份方式:

# 停容器保证一致性
docker compose stop vaultwarden

# 打包整个 data 目录
tar czf /backup/vaultwarden-$(date +%Y%m%d).tar.gz \
  -C /opt/docker/vaultwarden data

docker compose start vaultwarden

或者用 sqlite 的在线备份(不停容器):

docker exec vaultwarden sqlite3 /data/db.sqlite3 \
  ".backup /data/backup-$(date +%Y%m%d).sqlite3"

备份文件要放在另一台机器或者网盘上,别和原数据放同一块盘。

我设了个每周日凌晨的定时备份,用 rclone 同步到另一台机器。

七、踩过的坑

坑一:不设 ADMIN_TOKEN

第一次装完,/admin 打不开,报 404。查了才知道没设 ADMIN_TOKEN,管理面板根本没启用。

坑二:反代没配 WebSocket

密码库有个实时同步功能,靠 WebSocket。Nginx 反代时要把 Upgrade 头透传,不然多端同步会有延迟,得手动刷新。

Nginx Proxy Manager 里勾上 "Websockets Support" 就行,手写 nginx 要加:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

坑三:附件目录权限

Vaultwarden 上传附件(比如证件照片)存在 data/attachments,容器里的用户是 UID 1000。如果宿主机目录属主不对,上传会失败,日志里报 Permission denied。

sudo chown -R 1000:1000 /opt/docker/vaultwarden/data

坑四:忘记主密码就完了

Vaultwarden 服务端存的是加密后的数据,主密码忘了,谁也没法帮你解。只能从备份恢复,或者用恢复码。

所以注册时生成的 Emergency Kit(应急恢复码)一定要打印出来或者存到别的地方。

八、这套东西的价值

对比一下:

方案一年成本数据在哪
1Password约 300 元别人服务器
Bitwarden 官方免费版够用,高级版 10 美元别人服务器
自建 Vaultwarden电费几十块自己机器

自建的代价是要自己维护、自己备份、自己保证 HTTPS。

但对有点技术基础的人来说,这套是值得的——密码这东西,存在自己机器上心里踏实。

最后

Vaultwarden 是我 Docker 全家桶里最没存在感的一个服务:装完就忘了,256M 内存,几年不用管。

但它是最重要的一项。照片丢了是遗憾,密码丢了是灾难。

下一篇写 Nginx Proxy Manager,把这一堆服务统一收进 https。

---

如果你也在折腾这套服务,碰到卡住的地方,可以加我微信 lige0552 聊聊。白天要上班,消息回得慢,看到都会回。