资讯详情

资讯详情

从零自建Vaultwarden:轻量开源密码管理器的完整部署指南

这两年我身边越来越多人开始聊密码管理但聊来聊去总绕不开一个问题密码都存在别人服务器上心里多少有点不踏实。我自己折腾过好几轮云端的密码管理服务最后还是选了 Vaultwarden 作为自建方案。这款轻量级开源密码管理器把密码库、两步验证、分享、附件这些能力都包装在一个极小的服务里跑在云主机甚至树莓派上都毫无压力。今天这篇就是我从零到一部署这套系统的完整记录包括选型思路、架构设计、实操命令以及踩过的各种坑。Vaultwarden 适合谁我认为是对数据主权有一定要求、愿意花一两个小时维护一台小服务器的人。不适合完全不想碰服务器、只想打开就用的朋友。但如果你正处于想自建又怕麻烦的观望阶段这篇内容会告诉你真正做下来并没有想象中复杂。1. 先想清楚为什么要把密码库握在自己手里1.1 云密码库的便利与顾虑很多人不理解云端的密码管理工具明明挺好用浏览器插件、手机 App、自动填充一应俱全为什么还要自找麻烦说实话以前我也不太在乎觉得大厂的加密技术肯定比我自己部署得强。但后来我意识到便利和数据主权是两回事。云端方案把加密后的密码库托管在别人的数据中心你对它的依赖是双重的既要信任他的加密实现又要信任他的运营稳定性和账号安全。一旦服务商出现故障、调整收费、下架功能哪怕只是某个 IDC 机断电你的使用体验都会受影响。更关键的是即使密文泄漏后被暴力破解的成本极高心理上那种底层的失控感始终挥之不去。我遇到过不止一次在一些网络环境下无法同步明明记着密码库的 URL 标准却访问不了自己的数据那种体验很憋屈。1.2 自建方案的真实取舍自建意味着你把密码库放在自己的服务器上域名、存储、导出、备份都由自己控制。换句话说只要服务器活着、备份完好密码就永远是你的。断网、服务商跑路、账号被封这类风险基本消失。但代价同样真实服务器维护成本包括系统安全补丁、容器更新、证书续期。需要考虑备份策略否则服务器宕机时可能比云端更惨。公网暴露面增大需要做基本的访问控制、限流、防火墙。所以我不是劝所有人自建而是想说这个方案的核心竞争力是可控。如果你愿意为可控承担一点运营工作Vaultwarden 几乎是最佳选项因为它在功能完整性和部署成本之间取得了一个非常舒服的平衡点。2. Vaultwarden轻量在哪兼容到什么程度2.1 一个二进制搞定整套密码管理Vaultwarden 的核心特点就是轻量。和官方服务端动辄占用几百 MB 内存相比Vaultwarden 运行起来常常只有几十 MB 左右而且依赖极少。部署形式常见的是 Docker 镜像也支持直接编译出单个可执行文件来跑。它实现的功能却一点不少加密密码库存储、多设备同步、网站自动填充、安全笔记、支付卡、身份信息、附件、密码生成器、两步验证、组织分享、用户管理、目录同步。这些听起来像一个大项目该有的功能被塞进了一个非常小的进程里。从技术角度看Vaultwarden 本身是用 Rust 写的。Rust 的高效内存管理和安全性让这个服务在高并发下也能保持很低开销。对普通家庭或小团队使用来说几十个用户、上百台设备的压力它都扛得住。2.2 客户端生态直接复用这是它最聪明的亮点Vaultwarden 的服务端接口与主流的开源密码管理客户端生态高度兼容。这意味着你不用重新装一堆专用客户端手机、电脑、浏览器上已有的那些密码管理扩展和 App只要在设置里把服务器地址改成你自己的域名就能直接连上。所以我部署完以后家人手机装好对应 App把登录服务器地址改成我给的域名输入主密码密码库就同步过去了。复制、自动填充、两步验证这些功能与云端版几乎一致。对普通用户来说部署者只需要给他们一个地址和一个账号他们没有感知到自建的复杂度。2.3 什么时候不建议自建这个我得直说。如果你属于以下三类人自建并不是最优解对服务器零基础且没有学习意愿的人。密码管理的基础设施若自己没信心维护风险可能比信任云端还大。手上没有任何长期运行的服务器也不想为此专门买一台的人。除非你有树莓派常年开着否则额外成本不值得。需要官方 SLA、企业级合规认证的团队。Vaultwarden 是社区项目定位不是商业交付法律合规、审计能力都比不上正规云服务。看清这些边界以后再动手部署后面才不会别扭。3. 自建前的准备与整体架构设计3.1 硬件和系统要求Vaultwarden 的资源需求低到令人放松。官方建议的内存大约 1 GB但实际跑起来内存占用经常只占一小部分。CPU 单核就够小规模使用。存储方面密码库本身是文本为主的数据加上数据库索引几千条密码也不会占多大空间但附件会占地方建议至少预留 5 GB 到 10 GB。操作系统方面Debian 或 Ubuntu 这类 Linux 发行版最顺手。Windows 也能跑 Docker但生产环境没必要给自己加难度。我个人的习惯是一台干净的云主机预装 Docker 和 Docker Compose然后全部以容器方式运行。树莓派用户也可以跑但备份和系统维护要多上心一点。3.2 域名、端口与网络规划部署 Vaultwarden 建议有一个域名不光是访问好记主要是客户端接入和 HTTPS 证书签发都方便。即便只是内网使用一个局域网域名也比 IP 地址省心否则以后换服务器 IP所有客户端都要重新配置。端口规划上Vaultwarden 容器内部常监听 80 端口我们习惯将 80 映射到宿主机的一个高位端口比如 8380再用 Nginx 反代 443 到 8380。这样做的好处是宿主机上不用暴露太多端口防火墙只需放开 80 和 443其他端口一律不开。3.3 部署架构建议我最终的部署结构是这样的一台云主机系统盘和数据盘分开确保系统重装不影响密码数据。Docker 里运行 Vaultwarden 容器数据目录挂载到宿主机的持久化目录。宿主机运行 Nginx负责 HTTPS 终结、WebSocket 代理、请求大小限制。数据库使用默认的 SQLite而不是额外接 MySQL 或 PostgreSQL。有人会问为什么小规模部署不建议外接数据库因为 Vaultwarden 默认 SQLite 对这个场景已经足够稳健备份只需要拷一个文件恢复极其简单。外接数据库反而增加一个需要维护的组件还容易在备份一致性上出问题。4. 实操Docker 部署完整流程4.1 准备目录和基础环境先清理环境确认 Docker 和 Compose 插件可用。假定使用 Debian 系系统基础命令很简单。sudo apt update sudo apt upgrade -y sudo apt install -y docker.io docker-compose-plugin sudo systemctl enable --now docker确认 Docker 正常运行docker version docker compose version然后创建 Vaultwarden 的数据目录sudo mkdir -p /opt/vaultwarden/data sudo mkdir -p /opt/vaultwarden/backup目录规划非常关键。数据目录存放 SQLite 数据库、配置文件、附件、密钥等备份目录用来放定时备份产物。两者分开可以在脚本里只备份 data不需要担心备份目录被循环包含。4.2 编写 docker-compose 配置我不想用一条 docker run 把参数写成长串太难看也无从维护。更推荐用 docker-compose 文件把端口、环境变量、挂载、重启策略都写清楚以后升级也好处理。创建/opt/vaultwarden/docker-compose.ymlservices: vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden restart: unless-stopped environment: DOMAIN: https://vault.example.com SIGNUPS_ALLOWED: false WEBSOCKET_ENABLED: true ADMIN_TOKEN: 这里改成足够长的随机字符串 SMTP_HOST: smtp.example.com SMTP_FROM: vaultexample.com SMTP_PORT: 587 SMTP_SECURITY: starttls SMTP_USERNAME: vaultexample.com SMTP_PASSWORD: 你的SMTP密码 DATA_DIR: /data volumes: - ./data:/data ports: - 127.0.0.1:8380:80这几项需要逐个解释。DOMAIN是客户端访问时使用的完整 HTTPS 地址。这一项别乱填因为它会影响两步验证二维码、WebSocket 连接、邮件里的链接等一堆功能。我见过的多数问题比如扫描二维码后手机上打开链接不对基本都是这项写错。SIGNUPS_ALLOWED决定用户能否自助注册。部署完成后应尽快设为 false只允许管理员通过控制台创建用户避免公网上的陌生人跑过来注册把你服务器当免费密码库用。WEBSOCKET_ENABLED是实时同步开关。开了以后多个客户端之间能更接近实时推送更新而不是等到下次手动同步才看到变化。代价是在反向代理时多一个路径需要特殊处理这个下文会讲。ADMIN_TOKEN是进入管理后台的钥匙。可以用 OpenSSL 或openssl rand -base64 48生成一段足够长的随机字符串。这个 token 非常重要泄露等于别人能看你的部署信息、管理用户务必保存到单独的文件里权限设成仅 root 可读。SMTP_*系列是邮件服务配置。用它发送注册确认、两步验证恢复码、邀请邮件。如果没有 SMTP 能力可以先跳过但邀请用户和找回账号时体验会大打折扣。4.3 启动、验证与后续日志写好配置后进入目录启动cd /opt/vaultwarden docker compose pull docker compose up -d第一次启动会拉取镜像并创建容器。查看日志docker compose logs -f看到监听端口的提示基本说明服务起来了。再用 curl 验证curl -I http://127.0.0.1:8380返回 HTTP 200就说明本地服务正常。此时我还不会立刻开放公网访问先把反向代理和 HTTPS 搞定再对外暴露。4.4 反向代理与 HTTPSVaultwarden 本身能直接跑 HTTPS但更合理的做法是让 Nginx 或 Caddy 处理 HTTPSVaultwarden 只监听容器内部的 HTTP。这样以后换证书、加访问日志、加限流规则都很方便。以 Nginx 为例站点配置大致如下server { listen 80; server_name vault.example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; http2 on; server_name vault.example.com; ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem; client_max_body_size 100m; location / { proxy_pass http://127.0.0.1:8380; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /notifications/hub/ { proxy_pass http://127.0.0.1:8380/notifications/hub/; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_read_timeout 600s; } }这里最容易被忽略的就是/notifications/hub/这个 WebSocket 路径。如果漏掉这一句实时推送会失败表现为修改密码后另一个客户端半天不更新。原因是浏览器和服务器之间的 WebSocket 协议需要 Upgrade 头普通静态反代不会自动传递。证书建议用免费证书签发工具配合定时续期。续期后需要 reload Nginx通常在续期钩子里执行一条命令nginx -t systemctl reload nginx签发证书前要确保域名已经解析到服务器 IP且防火墙放行 80 端口否则验证请求不会到达服务器。5. 关键配置与使用细节5.1 客户端接入方法这是全家桶中最常被问到的一步。打开手机上的密码管理 App在登录界面一般会有一个服务器选项或自托管地址的入口把https://vault.example.com填进去即可。首次登录后它会从服务器拉取密码库。桌面浏览器扩展的做法也类似登录页面通常默认连接官方服务器需要手动展开设置填入自定义服务器地址再刷新登录页。部分扩展版本对自托管地址检查比较严格填之前确认是https://开头不要漏掉。一旦登录成功主密码会保存在本地加密过的缓存里。之后即使服务器临时不可用浏览器也能读取本地缓存登出前都能查看密码片段。但新增修改会等网络恢复后同步这是很多登录器的统一行为不是只有自建才这样。5.2 导入、导出与迁移从旧密码管理器迁移过来最稳妥的路径是先在旧的工具里导出 CSV 或 JSON 文件再登录 Vaultwarden 网页在工具菜单里选导入。导入前留个心眼导出出的 CSV 里有大量明文密码千万不要通过公共网盘、聊天工具发送。我自己的习惯是在本机导出导入完成后立刻删除文件并开启两步验证。导出方面Vaultwarden 可以导出 JSON 和 CSV。建议至少每半年导出一次加密 JSON 备份并存到离线位置比如本地加密硬盘。这样哪怕服务器彻底没了也有最后一层兜底。5.3 组织与共享、两步验证如果家庭成员或小团队一起用组织共享非常实用。管理员登录管理后台后可以关闭开放注册创建用户账号再把某个组织里的密码集共享给指定成员。比如家庭共用的各类账号、团队里的服务器密钥凭证都能用一套密码库组织起来。不过要理解一个安全边界密码库的加密是基于账户主密码的共享密码也会被组织密钥加密。组织中每个用户能解开共享项目的明文这是正常机制不是漏洞。所以给谁加权限要想清楚。两步验证方面Vaultwarden 支持 TOTP 验证码器。你可以在网页端个人设置里启用两步验证之后登录时除了主密码还要输入动态码。这一步强烈建议所有用户都开启。但开启后一定要保留恢复码或者确保邮箱可用否则手机丢失又忘记恢复码密码库就永久锁死谁都救不回来。5.4 忘记密码与恢复保护Vaultwarden 的数据模型是端到端加密的服务端不知道你的主密码。所以忘记主密码没有恢复码或紧急访问联系人时基本等于永久丢失密码库。这也是很多用户初次感受自建密码工具时最难接受的一点。尽量提前做几件事开启账号恢复选项配合邮件验证。把恢复码打印出来放在物理保险处。设置紧急联系人访问功能允许信任的人在一段时间后申请访问密码库。这些听起来繁琐但就像是给家门配了备用钥匙丢一把不至于回不了家。6. 备份、更新与持续运营6.1 备份数据库与附件备份是自建 Vaultwarden 整个过程中最值得投入时间的地方。密码管理服务的核心资产是数据库和附件目录只要这两样在灾难恢复就不是问题。简单可靠的备份方式是先使用 sqlite3 备份命令生成一致性良好的数据库文件再连同附件和配置文件一起打包。计划任务里可以这样写核心步骤sqlite3 /opt/vaultwarden/data/db.sqlite3 .backup /backup/vaultwarden/db.sqlite3.bak tar czf /backup/vaultwarden/vaultwarden_$(date %F).tar.gz -C /opt/vaultwarden data注意不要直接 tar 运行中的数据库文件因为 SQLite 在写入时直接拷贝可能得到不一致的状态。先用 SQLite 自带的在线备份机制生成副本再打包这样不仅一致性有保障还不用停服务。备份文件产生后至少再同步一份到与服务器物理隔离的地方。例如用 rsync 推到另一台机器或者挂载对象存储定期上传。只有服务器本地的备份遇到机房火灾、硬盘故障时就是零备份。6.2 版本升级Vaultwarden 迭代比较快偶尔会有安全更新和功能修复。升级流程我给固定步骤cd /opt/vaultwarden docker compose pull docker compose up -d镜像更新后容器会基于新镜像重新创建。升级前先看一眼当前容器版本备份数据再升级。尤其是跨大版本时最好先看官方更新日志确认有没有破坏性变更。我在生产环境的原则是没有异常就保持稳定有安全更新就尽快上。升级后检查痕迹很简单docker inspect vaultwarden | grep Image docker compose logs --tail50如果服务起不来回滚方案也很清晰之前的镜像 tag 还在本地或仓库里改回旧版本再 up 即可。前提是你没有在升级过程中改动数据格式否则回滚可能遇到数据库版本不兼容。所以升级前备份这个东西什么时候都是底线。6.3 日常健康检查与告警自建服务最怕的是它挂了我不知道。Vaultwarden 本身没有非常强的告警体系但我们可以用简单的脚本做健康检查每分钟请求一次本地端口连续失败就触发通知。比如下面这个思路curl -fsS http://127.0.0.1:8380/alive /dev/null || echo vaultwarden down | mail -s alert backupexample.com更精细一点可以检查公网 HTTPS 访问是否正常甚至检查 HTTP 状态码是否为 200。把这些脚本放进 cron配合一个邮件或即时通信 webhook就能实现基础的告警能力。存储监控也不能忘。密码库虽然小但附件膨胀起来很快。df -h定期检查或配置磁盘告警避免数据库在磁盘写满时损坏。7. 常见问题与排查技巧实录7.1 网页能开但客户端一直登录失败这是新手最常遇到的。先检查 DOMAIN 环境变量是否完整尤其有没有漏掉https://。客户端在填写服务器地址后会请求接口路径如果反向代理没有正确转发Authorization头也会出现握手 401。还有一种情况是客户端 App 内置证书校验系统时间错误会导致 TLS 验证失败。我遇到过一次手机时间漂移了所有 HTTPS 服务都提示证书无效调回自动时间后一切正常。7.2 WebSocket 推送不生效修改一条密码后要过很久才在另一个设备看到多半是反向代理没有配置/notifications/hub/的 Upgrade 转发。加上 Nginx 那段proxy_set_header Upgrade配置重启 Nginx 即可。另外要留意宿主机上 Vaultwarden 是否真的开了WEBSOCKET_ENABLED。有些镜像默认关闭光配反代也没用。7.3 邮件发送失败邮件关系到账号邀请、找回码、通知。常见原因是 SMTP 端口或安全协议不匹配。587 端口一般配 STARTTLS465 端口通常配 TLS。有些主机商限制出站邮件端口需要先测试能否连接 SMTP 服务器。我建议第一次配置 SMTP 时先在管理后台手动发一封测试邮件而不是等用户邀请时才发现配置错误。排错时看日志最直观邮件服务相关的错误信息都会打出来。7.4 忘记 ADMIN_TOKEN如果管理后台登录不了只能改环境变量。编辑 docker-compose 文件里的ADMIN_TOKEN然后执行docker compose up -d容器重建后管理后台会用新的 token。这里的风险是旧 token 会失效如果有管理脚本依赖旧值记得同步更新。7.5 备份恢复时打不开密码库恢复流程第一步是停容器避免它写入旧数据把恢复的数据覆盖。然后把备份里的 data 目录完整拷回再启动容器。如果只是想恢复某一条密码不要试图直接用 SQLite 改库很容易造成不可预知的数据损坏。更可行的方式是整套回滚或者借助导出的加密 JSON 进行部分导入。7.6 资源占用突然升高遇到容器内存或 CPU 飙升先看日志有没有异常请求或暴力破解尝试。Vaultwarden 默认对登录失败有速率限制但如果日志里全是一个 IP 反复尝试要在反向代理层面加一层更严格的限制比如对账号登录接口做低频次限流。还有一个隐蔽原因附件上传大文件时Nginx 的client_max_body_size不够客户端会反复重试造成流量和资源浪费。按我上面的配置把它设为 100m基本覆盖了大多数照片和文档附件。结尾说实话把 Vaultwarden 部署到能稳定给家人用的这个状态我用了一整个周末其中一半时间在研究反向代理的 WebSocket 转发。不过跑顺之后心是真的定了。密码库在自己手里备份策略清清楚楚客户端体验也是完整的这种踏实感不是简单一句方便能替代的。如果你也打算自建一套我只有一个建议部署完成当天把所有恢复码、备份文件的位置写下来放到房间里能锁的抽屉里剩下的就交给它安静工作吧。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →