使用 Docker Compose 和 Nginx 部署 Vaultwarden
Vaultwarden 是 Bitwarden 服务端的 Rust 重写版
为什么选用第三方而不选择官方?
Vaultwarden 兼容官方客户端,空载内存占用只有几十 MB。一台便宜的1C1G VPS 就能跑得很稳
而官方服务端最低配置要求是2G Ram
本文中的域名、端口、安装目录和证书路径都是示例,不能原样照搬。执行命令前,请按下表替换成自己的配置
| 示例值 | 用途 | 替换建议 |
|---|---|---|
vault.example.com | Vaultwarden 域名 | 换成已经解析到 VPS 的域名 |
127.0.0.1:8080 | Vaultwarden 本机监听地址 | 端口冲突时换成未占用端口,并同步修改 Nginx |
/opt/vaultwarden | 安装与数据目录 | 换目录时同步修改本文所有相关命令 |
/etc/ssl/vault.example.com/fullchain.pem | TLS 证书 | 换成自己的证书完整链路径 |
/etc/ssl/vault.example.com/private.key | TLS 私钥 | 换成自己的证书私钥路径 |
127.0.0.1:8443 | 可选的 Nginx TLS 回落地址 | 仅在使用 Xray/3X-UI 回落时按实际配置修改 |
确认服务器已安装安全更新,并为域名配置有效的 HTTPS 证书。不要把管理密码、ADMIN_TOKEN、TLS 私钥或备份文件提交到公开仓库。
请求路径
安装 Docker
服务器上没有 Docker 的话,用官方便捷脚本安装:
curl -fsSL https://get.docker.com | sudo shsudo systemctl enable --now docker确认 Docker Engine 和 Compose 插件都在:
docker --versiondocker compose version如果第二条命令报 docker: 'compose' is not a docker command,说明只装了引擎、没装 Compose 插件。不同发行版的包名不一样,Debian 系一般是 docker-compose-plugin。
创建安装目录
程序配置和持久化数据我放在 /opt/vaultwarden:
sudo install -d -m 750 /opt/vaultwarden/datacd /opt/vaultwarden改用其他目录的话,后面的 .env、compose.yml、启动和备份命令都要一起改。
生成管理令牌
Vaultwarden 的管理后台接受 Argon2 PHC 字符串。明文 ADMIN_TOKEN 会在启动日志里触发安全警告,所以最好生成哈希:
sudo docker run --rm -it vaultwarden/server:latest /vaultwarden hash按提示输入管理密码,命令会输出一行以 $argon2id$ 开头的字符串。注意一点:登录管理后台时输入的是原始密码,不是这串哈希。
原始管理密码和 Argon2 哈希都不要公开。哈希还原不出密码,但可以拿去离线爆破,也能被复制到另一套 Vaultwarden 配置里冒充你的后台。
创建环境文件
创建 /opt/vaultwarden/.env:
sudo nano /opt/vaultwarden/.env写入下面的内容。域名换成自己的,ADMIN_TOKEN 替换为刚才生成的完整 Argon2 字符串,外层单引号要留着:
DOMAIN=https://vault.example.comADMIN_TOKEN='$argon2id$v=19$m=19456,t=2,p=1$REPLACE_WITH_YOUR_HASH'SIGNUPS_ALLOWED=falseTZ=Asia/Shanghai高亮的两行是必须改的
第二行加单引号的作用是防止 Compose 把哈希里的 $ 解析成变量
接着收紧权限:
sudo chown root:root /opt/vaultwarden/.envsudo chmod 600 /opt/vaultwarden/.envSIGNUPS_ALLOWED=false 会关闭公开注册,建议保持关闭,后面可以通过管理后台邀请注册
创建 Compose 配置
sudoedit /opt/vaultwarden/compose.ymlservices: vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden restart: unless-stopped env_file: - .env ports: - "127.0.0.1:8080:80" volumes: - ./data:/data高亮那行是整份配置里最重要的部分,容器的 80 端口映射到宿主机 127.0.0.1:8080,前缀里的 127.0.0.1 如果写成 "8080:80" 会绑到 0.0.0.0,任何人都能用 http://IP:8080 绕过 Nginx 直接摸到明文服务。
8080 被占用的话先找个空闲端口:
sudo ss -lntp换端口时,Compose 里的映射和 Nginx 的 proxy_pass 必须一致,改一处漏一处就是 502
启动容器:
cd /opt/vaultwardensudo docker compose up -dsudo docker compose ps看日志和本机响应:
sudo docker compose logs --tail=100 vaultwardencurl -I http://127.0.0.1:8080curl 返回 200 OK 就说明容器这一层没问题了,然后配置 Nginx
配置 Nginx
先确认域名已经解析到这台 VPS,证书覆盖 vault.example.com。然后创建站点配置:
sudo nano /etc/nginx/conf.d/vaultwarden.confserver { listen 80; listen [::]:80; server_name vault.example.com;
return 301 https://$host$request_uri;}
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name vault.example.com;
ssl_certificate /etc/ssl/vault.example.com/fullchain.pem; ssl_certificate_key /etc/ssl/vault.example.com/private.key;
client_max_body_size 128M;
location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1;
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;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_buffering off; }}高亮的是要修改的地方:两个证书路径、proxy_pass 的端口(前面改过就同步改),以及域名 vault.example.com。
client_max_body_size 128M 管的是附件上传上限。默认值只有 1M,往密码库里塞图片或文件时会被 Nginx 直接拒掉,返回 413。
Upgrade 和 Connection 是给 WebSocket 用的,Vaultwarden 靠它做多设备实时同步,少了这两行也能正常登录,只是在一台设备上改的密码不会立刻推到另一台
检查配置,再重载:
sudo nginx -tsudo systemctl reload nginx如果nginx -t 不通过就回去检查配置。重点查看 server_name 、证书文件路径、花括号、端口
可选:接入 Xray 或 3X-UI 回落
没在用 Xray/3X-UI 回落的话,直接无视这节。
如果端口 443 由 Xray 接管,可以回落给 Nginx,Nginx 的 TLS 监听地址得和回落目标对上。假设回落目标是:
127.0.0.1:8443那么 Nginx 的 HTTPS 监听要改成同一个端口:
server { listen 80; listen [::]:80; server_name vault.example.com;
return 301 https://$host$request_uri;}
server { listen 443 ssl http2; listen [::]:443 ssl http2; listen 127.0.0.1:8443 ssl http2; server_name vault.example.com;
ssl_certificate /etc/ssl/vault.example.com/fullchain.pem; ssl_certificate_key /etc/ssl/vault.example.com/private.key;
client_max_body_size 128M;
location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1;
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;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_buffering off; }}这里的 8443 同样是示例,必须和自己的回落目标完全一致。
Xray 和 Nginx 不能同时占用同一个 IP 的 TCP 443。改之前先跑一下,看清是谁在监听:
sudo ss -lntp | grep ':443'创建首个用户
访问管理后台,域名换成自己的:
https://vault.example.com/admin用生成 Argon2 哈希时输入的原始密码登录,在后台上方点击Users邀请自己的邮箱
然后就可以进入主页,直接使用被邀请的邮箱作为账号注册
https://vault.example.com更新 Vaultwarden
更新前先备份,确认备份完成再拉新镜像重建容器:
cd /opt/vaultwardensudo docker compose pullsudo docker compose up -dsudo docker compose logs --tail=100 vaultwarden我不建议给密码服务挂 Watchtower 之类的自动更新。这东西一挂,你连不上的可能不只是网页,还有所有设备上的密码库。先读版本说明,手上留着能恢复的近期备份。
备份与恢复
数据库、附件和配置全在 /opt/vaultwarden/data。直接打包正在写入的 SQLite 文件可能拿到不一致的快照,所以最好是停一下容器:
cd /opt/vaultwardensudo docker compose stop vaultwardensudo tar -czf "/root/vaultwarden-data-$(date +%F-%H%M%S).tar.gz" \ -C /opt/vaultwarden datasudo docker compose start vaultwarden备份文件落在 /root,里面是完整的密码库数据,要加密保存并定期复制到另一台设备。改过安装目录或备份目录的,命令要跟着改。
恢复之前先停容器,并且确认目标目录没写错。下面的命令会替换现有 data 目录:
cd /opt/vaultwardensudo docker compose stop vaultwardensudo mv data "data.before-restore-$(date +%F-%H%M%S)"sudo tar -xzf /root/vaultwarden-data-YYYY-MM-DD-HHMMSS.tar.gz \ -C /opt/vaultwardensudo docker compose start vaultwarden第 3 行用 mv 而不是 rm,是给自己留条退路,恢复出来的数据不对时还能换回去。YYYY-MM-DD-HHMMSS 是占位符,换成实际的备份文件名。确认恢复正常后再决定要不要删掉 data.before-restore-*。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!







