密码管理器是最适合放在 VPS 上长期运行的自托管服务之一。它不像相册、网盘、媒体库那样吃磁盘,也不像 AI 服务那样吃显卡和内存;但它的价值很高:浏览器插件、手机 App、桌面客户端、团队共享、随机密码、二步验证和跨设备同步,都会直接影响你的日常安全。
Vaultwarden 是一个用 Rust 实现的 Bitwarden 兼容服务端。它不是 Bitwarden 官方服务,但能兼容大多数 Bitwarden 客户端,资源占用很低,非常适合个人 VPS、小团队和家庭场景。很多 1C1G 甚至更小的 VPS 都能跑起来。
但也正因为它保存的是密码,部署时不能只追求“能打开页面”。本文会按生产思路讲清楚:如何用 Docker Compose 部署 Vaultwarden,如何用 Caddy 自动 HTTPS,为什么要关闭公开注册,SMTP 怎么配置,哪些目录必须备份,恢复时要注意什么,以及如何降低公网暴露风险。
适合。
Vaultwarden 的优势是轻量、稳定、客户端生态成熟。你可以继续使用 Bitwarden 浏览器插件、手机 App 和桌面客户端,只是服务器地址换成自己的域名。
适合的场景:
- 你想自建密码同步服务,不想把密码库托管在第三方云端。
- 你有一台长期在线的 VPS 和一个域名。
- 你需要给家人或小团队提供密码共享。
- 你希望低成本运行,机器资源有限。
- 你愿意认真做备份和恢复演练。
不适合的场景:
- 你不愿意维护服务器安全更新。
- 你没有第二份备份,只想把密码库放在唯一一台 VPS 上。
- 你会把管理员后台、注册入口和弱密码一起暴露公网。
- 你忘记主密码后希望服务器能帮你找回。
密码管理器的核心原则是:服务端被拿到,也不应该轻易拿到明文密码;但服务端仍然非常重要,因为它影响同步、登录、邀请、组织共享和数据可用性。
Vaultwarden 对资源要求很低:
| 用途 | 推荐配置 |
|---|---|
| 个人使用 | 1 vCPU / 512MB-1GB RAM / 10GB SSD |
| 家庭或小团队 | 1-2 vCPU / 1GB RAM / 20GB SSD |
| 多用户和附件较多 | 2 vCPU / 2GB RAM / 40GB+ SSD |
真正要关注的不是 CPU,而是:
- 数据目录是否持久化。
- 域名是否使用 HTTPS。
- 注册是否关闭。
- SMTP 是否能正常发邀请和验证邮件。
- 备份是否包含数据库、附件和密钥文件。
如果你的 VPS 同时跑很多 Docker 服务,建议先阅读 Docker 和反向代理基础。延伸阅读可以看:VPS 用 Caddy 反向代理完全指南 和 VPS 搭建 Portainer Docker 管理面板。
开始前建议准备:
- Ubuntu 22.04 / 24.04 或 Debian 12 VPS。
- 已安装 Docker Engine 和 Docker Compose 插件。
- 一个域名,例如
vault.example.com。 - 已开放 80/443 端口。
- 已配置基础防火墙和 SSH 安全。
确认 Docker 可用:
docker version
docker compose version
确认域名已经解析到 VPS:
dig vault.example.com +short
如果域名还没解析好,不要急着申请证书。Caddy、Nginx 或 Let's Encrypt 都需要 DNS 和 80/443 正常工作。
建议把 Vaultwarden 放在 /opt/vaultwarden:
sudo mkdir -p /opt/vaultwarden
sudo chown -R "$USER":"$USER" /opt/vaultwarden
cd /opt/vaultwarden
创建数据目录:
mkdir -p vw-data
Vaultwarden 默认把重要数据放在容器内 /data,所以我们必须把它挂载到宿主机目录,否则删除容器后数据就可能丢失。
创建 .env:
nano .env
写入下面内容,按自己的域名修改:
VAULTWARDEN_DOMAIN=https://vault.example.com
VAULTWARDEN_ADMIN_TOKEN=换成一串很长的随机值
VAULTWARDEN_SMTP_HOST=smtp.example.com
VAULTWARDEN_SMTP_PORT=587
[email protected]
[email protected]
VAULTWARDEN_SMTP_PASSWORD=换成邮箱授权码
生成随机 admin token:
openssl rand -base64 48
ADMIN_TOKEN 用于访问 Vaultwarden 的 /admin 管理页面。这个值非常敏感,不要写进公开仓库,也不要发给别人。
如果你暂时不想启用管理后台,可以不设置 ADMIN_TOKEN,或者部署后确认配置没问题再禁用管理入口。对个人用户来说,能不用 admin 页面就尽量少用。
创建 docker-compose.yml:
nano docker-compose.yml
写入:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
env_file:
- .env
environment:
DOMAIN: ${VAULTWARDEN_DOMAIN}
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "true"
WEBSOCKET_ENABLED: "true"
ADMIN_TOKEN: ${VAULTWARDEN_ADMIN_TOKEN}
SMTP_HOST: ${VAULTWARDEN_SMTP_HOST}
SMTP_PORT: ${VAULTWARDEN_SMTP_PORT}
SMTP_FROM: ${VAULTWARDEN_SMTP_FROM}
SMTP_USERNAME: ${VAULTWARDEN_SMTP_USERNAME}
SMTP_PASSWORD: ${VAULTWARDEN_SMTP_PASSWORD}
SMTP_SECURITY: starttls
volumes:
- ./vw-data:/data
ports:
- "127.0.0.1:8000:80"
这里有几个关键点:
vaultwarden/server:latest是官方常用镜像。./vw-data:/data保存数据库、附件、密钥和配置。127.0.0.1:8000:80表示只允许本机访问容器端口。SIGNUPS_ALLOWED: "false"关闭公开注册。INVITATIONS_ALLOWED: "true"允许管理员邀请用户。DOMAIN必须填写最终 HTTPS 域名,否则附件、邮件链接和客户端同步可能出现异常。
如果你还没配置 SMTP,可以先删除 SMTP 相关环境变量,等网页能打开后再补。但正式使用前建议配置邮件,否则邀请、验证和部分通知体验会变差。
在 /opt/vaultwarden 执行:
docker compose up -d
查看状态:
docker compose ps
查看日志:
docker compose logs -f --tail=100
本机测试:
curl -I http://127.0.0.1:8000
如果返回 HTTP/1.1 200 OK、301 或类似响应,说明容器已经能在本机访问。
注意:因为我们只绑定了 127.0.0.1,公网访问 http://服务器IP:8000 是不通的,这是预期行为。下一步要用 Caddy 或 Nginx 从 443 反向代理进来。
假设你的域名是 vault.example.com,Caddyfile 可以这样写:
vault.example.com {
encode zstd gzip
header {
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
X-Robots-Tag "noindex, nofollow"
}
reverse_proxy 127.0.0.1:8000 {
header_up X-Real-IP {remote_host}
}
}
保存后执行:
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
访问:
https://vault.example.com
Vaultwarden 官方文档也建议使用反向代理终止 TLS,而不是直接把容器的 HTTP 端口暴露给公网。这样公网只暴露 443,容器端口仍然只在本机可见。
如果你还没有 Caddy,可以先看:VPS 用 Caddy 反向代理完全指南。
第一次打开网页后,创建你的主账号。
创建完成后,要再次确认公开注册已经关闭:
docker compose exec vaultwarden printenv SIGNUPS_ALLOWED
应该输出:
false
为什么要关闭注册?因为 Vaultwarden 是密码管理服务,如果注册入口长期开放,公网扫描器、垃圾账号和撞库攻击都会增加你的维护压力。
新增用户建议使用邀请流程:管理员邀请家人或团队成员,对方通过邮件创建账号。这样比公开注册更可控。
SMTP 主要用于:
- 邀请新用户。
- 邮箱验证。
- 某些安全通知。
- 组织相关邮件。
常见邮箱配置思路:
VAULTWARDEN_SMTP_HOST=smtp.qq.com
VAULTWARDEN_SMTP_PORT=587
[email protected]
[email protected]
VAULTWARDEN_SMTP_PASSWORD=邮箱授权码
修改 .env 后重启:
docker compose up -d
然后进入管理页面或账户设置测试邮件。
注意:很多邮箱不允许使用登录密码直接 SMTP,需要单独生成“授权码”或“应用专用密码”。如果你用企业邮箱,也要确认 SPF、DKIM、DMARC 和发信限制,否则邮件可能进垃圾箱。
Vaultwarden 支持常见 Bitwarden 客户端的二步验证能力。强烈建议至少给管理员账号开启 TOTP。
建议做法:
- 登录 Web Vault。
- 进入账号安全设置。
- 开启两步登录。
- 使用 Aegis、1Password、Bitwarden Authenticator、Google Authenticator 等 TOTP 工具保存验证码。
- 保存恢复码到离线位置。
不要只把 TOTP 存在同一个 Vaultwarden 账号里。否则一旦你登录不上 Vaultwarden,同时又拿不到 TOTP,就会把自己锁在门外。
更稳妥的做法是:主密码记在脑中,恢复码离线保存,TOTP 保存在独立设备或独立应用里。
Vaultwarden 的 /admin 页面很方便,可以查看用户、邀请、配置和状态。但它也是一个高价值入口。
如果你启用了 ADMIN_TOKEN,至少要做到:
- 使用足够长的随机 token。
- 不把 token 写进公开仓库。
- 不在浏览器共享环境中保存。
- 尽量限制
/admin的访问来源。
更保守的方式是在 Caddy 里限制管理路径。例如只允许特定 IP 访问:
vault.example.com {
@admin path /admin*
@not_allowed_admin {
path /admin*
not remote_ip 你的固定IP/32
}
respond @not_allowed_admin "admin access denied" 403
reverse_proxy 127.0.0.1:8000
}
如果你没有固定 IP,可以考虑通过 WireGuard、Tailscale、Cloudflare Zero Trust 等方式访问管理后台。管理入口越少暴露,风险越低。
Vaultwarden 默认使用 SQLite,数据目录通常是 vw-data。官方备份文档明确说明,重要数据包括:
db.sqlite3:主要数据库。attachments/:附件。sends/:Send 文件,按需求备份。config.json:如果你用 admin 页面保存配置。rsa_key*:用于签名登录 token。
最简单的备份命令:
cd /opt/vaultwarden
mkdir -p /opt/backups/vaultwarden
docker exec vaultwarden /vaultwarden backup
tar czf /opt/backups/vaultwarden/vw-data-$(date +%F-%H%M).tar.gz vw-data
从 Vaultwarden 1.32.1 起,镜像里提供了内置 SQLite 备份命令:
docker exec -it vaultwarden /vaultwarden backup
备份文件不要只留在同一台 VPS 上。建议再同步到:
- 另一台 VPS。
- 对象存储。
- 家用 NAS。
- 加密后的云盘目录。
如果你已经有备份方案,可以把 Vaultwarden 加进去。延伸阅读:VPS 快照、备份、镜像有什么区别。
恢复前先停止服务:
cd /opt/vaultwarden
docker compose down
保留当前目录:
mv vw-data vw-data.broken.$(date +%F-%H%M)
解压备份:
tar xzf /opt/backups/vaultwarden/vw-data-你的日期.tar.gz -C /opt/vaultwarden
启动:
docker compose up -d
docker compose logs -f --tail=100
然后检查:
- 能否登录。
- 密码条目是否存在。
- 附件是否可下载。
- 组织共享是否正常。
- 手机和浏览器插件是否能同步。
备份不是“文件存在就算成功”,必须做过恢复演练才算可靠。密码管理器尤其如此,因为你最不希望在真正故障时才第一次尝试恢复。
如果你使用 latest,升级流程很简单:
cd /opt/vaultwarden
cp docker-compose.yml docker-compose.yml.bak.$(date +%F)
cp .env .env.bak.$(date +%F)
docker compose pull
docker compose up -d
升级后查看日志:
docker compose logs -f --tail=100
更谨慎的做法是固定版本标签,例如:
image: vaultwarden/server:1.36.0
个人用户用 latest 省事,但生产或团队场景更建议固定版本,测试后再升级。无论哪种方式,升级前都应该先备份 vw-data。
先看容器:
docker compose ps
docker compose logs --tail=100
再看本机端口:
ss -lntp | grep 8000
curl -I http://127.0.0.1:8000
如果本机 curl 不通,问题在容器;如果本机能通但域名不通,问题通常在 Caddy、DNS、防火墙或安全组。
检查 Caddy 反代地址是否和 Compose 端口一致:
Compose: 127.0.0.1:8000:80
Caddy: reverse_proxy 127.0.0.1:8000
两边端口必须对应。修改后执行:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
重点检查 DOMAIN:
docker compose exec vaultwarden printenv DOMAIN
应该是完整 HTTPS 地址:
https://vault.example.com
不要写成裸域名,也不要写成 HTTP。
检查 SMTP 配置:
docker compose logs --tail=200 | grep -i smtp
常见原因:
- SMTP 密码不是授权码。
- 端口和加密方式不匹配。
- 邮箱服务商限制第三方客户端。
- VPS 出站 SMTP 被云商限制。
- 发件人地址和账号不一致。
如果 25 端口被封,优先使用 587 + STARTTLS 或 465 + SSL。
使用邀请功能。你可以通过管理页面或组织邀请新用户。不要为了邀请一个人就临时长期打开公开注册。
如果必须临时开启:
SIGNUPS_ALLOWED: "true"
创建完成后立刻改回:
SIGNUPS_ALLOWED: "false"
然后:
docker compose up -d
上线前建议逐项确认:
- 域名使用 HTTPS。
- 容器端口只绑定
127.0.0.1。 -
SIGNUPS_ALLOWED=false。 - 管理员账号使用强主密码。
- 管理员开启 TOTP。
- SMTP 可用。
-
/admin已限制或不启用。 -
vw-data已备份到第二地点。 - 做过一次恢复演练。
- VPS 系统定期更新。
- SSH 不使用弱密码。
密码管理器不是普通博客。即使 Vaultwarden 本身足够轻量,部署习惯也必须更谨慎。
在 VPS 上搭建 Vaultwarden 的核心步骤并不复杂:创建数据目录,写 Docker Compose,把 /data 持久化,用 127.0.0.1:8000:80 避免直接暴露容器端口,再用 Caddy 把 https://vault.example.com 反向代理进来。
真正决定安全性的,是后续这些细节:关闭公开注册,配置 SMTP 邀请用户,管理员开启两步验证,限制 /admin,定期备份 vw-data,并真正测试恢复。
如果你只有一台低配 VPS,Vaultwarden 是非常值得部署的自托管服务;但如果你不愿意维护备份和安全更新,官方 Bitwarden 云服务反而可能更省心。自托管的自由,必须配套自托管的责任。