Vaultwarden 1.37.4 Docker Compose 部署指南
基于 Ubuntu 22.04 实测 Vaultwarden 1.37.4 的 Docker Compose 部署全流程:compose.yml 编写、服务启动与初始化验证、argon2 管理员令牌、关闭开放注册、nginx 反向代理 HTTPS 与升级流程。
Vaultwarden 1.37.4 Docker Compose 部署指南
> 目标:读完本文后,你可以在一台 Ubuntu 22.04 服务器上用 Docker Compose 完成 Vaultwarden 1.37.4 的部署、初始化(管理员令牌、关闭开放注册)、HTTPS 反向代理接入与升级,并知道每一步如何验证成功。
一、环境信息
本文所有操作与回显均来自下表环境的真实执行结果,命令可直接对应复现。
| 项目 | 实测值 |
|---|---|
| 操作系统 | Ubuntu 22.04.4 LTS(内核 6.8.0-138-generic) |
| Docker | 29.8.1(docker --version 实测) |
| Docker Compose | v5.5.1(docker compose version 实测) |
| Vaultwarden | 1.37.4(vaultwarden/server:1.37.4,latest 当前指向该版本) |
| Web Vault | 2026.7.0 |
| 反向代理 | nginx(部署实例实测版本 nginx/1.31.6) |
| 数据目录 | /opt/data/vaultwarden(挂载到服务内 /data) |
| 服务端口 | 宿主机 8222 → 服务 80 |
| 域名示例 | vault.example.com(反代与证书使用) |
先确认编排工具可用:
# docker compose version
Docker Compose version v5.5.1
二、compose.yml 文件编写
2.1 部署规划
单服务部署是最小可行形态:一个数据卷、一个端口映射、四个环境变量。生产上还差两件事——HTTPS 反向代理(第五章)与管理员令牌/关闭注册(第四章)。本篇的目录规划如下:
| 路径 | 用途 |
|---|---|
| /opt/data/vaultwarden | 数据目录,挂载为服务内 /data,数据库、附件、密钥都在这里 |
| /opt/data/vaultwarden/compose.yml | 编排文件(与数据同目录便于整体备份) |
2.2 生成管理员令牌(部署前完成)
Vaultwarden 的管理台口令建议使用 argon2id 哈希存储(明文口令只在你脑子里,文件里只放哈希)。在宿主机安装 argon2 工具并生成:
# apt-get install -y argon2
# echo -n "q1w2e3r4" | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4
$argon2id$v=19$m=65540,t=3,p=4$NXJIcE1kMURMRGZ3OTBYZDgrdlRSWFIwWXVsNElFdlU3V0ZtakZuWUF4ST0$jXhsLhviXX2rEyQmARrfcXrT3H75bs+0D0EPbqgVBnM
参数含义:-e 输出 PHC 编码格式、-id 使用 argon2id 变体、-k 65540 内存 64 MiB、-t 3 迭代 3 轮、-p 4 并行度 4,这是官方 wiki 推荐的参数组。整串 $argon2id$... 就是写入 ADMIN_TOKEN 的值;登录管理台时输入的是生成它所用的明文口令(本例 q1w2e3r4)。
官方还提供了交互式生成工具 /vaultwarden hash。实测在管道(无终端)环境下执行会直接失败,回显如下,可作为排错参考:
# printf 'q1w2e3r4\nq1w2e3r4\n' | docker exec -i vaultwarden-1.37.4-server /vaultwarden hash
Generate an Argon2id PHC string using the 'bitwarden' preset:
thread 'main' (212) panicked at src/main.rs:160:69:
called `Result::unwrap()` on an `Err` value: Os { code: 6, kind: Uncategorized, message: "No such device or address" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
结论:该工具要求交互式终端(TTY),能交互时按提示输入两次口令即可;无法交互时(脚本、CI、管道)用上面的 argon2 命令行等价生成。
2.3 编写 compose.yml
创建 /opt/data/vaultwarden/compose.yml,内容如下(与本机实测文件一致):
services:
vaultwarden:
image: vaultwarden/server:1.37.4
container_name: vaultwarden-1.37.4-server
restart: unless-stopped
ports:
- "8222:80"
volumes:
- /opt/data/vaultwarden:/data
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "false"
INVITATIONS_ALLOWED: "false"
ADMIN_TOKEN: "$$argon2id$$v=19$$m=65540,t=3,p=4$$NXJIcE1kMURMRGZ3OTBYZDgrdlRSWFIwWXVsNElFdlU3V0ZtakZuWUF4ST0$$jXhsLhviXX2rEyQmARrfcXrT3H75bs+0D0EPbqgVBnM"
要点说明:
container_name固定为vaultwarden-1.37.4-server,便于日志查看与命令引用;- 数据卷直接挂载宿主机目录,备份时整体拷贝即可;
ADMIN_TOKEN中每个$必须写成$$——Compose 会把$$转义为字面$,否则编排层会把它当作变量插值导致校验失败。实测转义后服务进程拿到的就是单$开头的 PHC 字符串;DOMAIN必须写成对外访问的完整地址(含协议)。实测不设置时服务默认http://localhost,附件下载链接等会指向错误地址(《Vaultwarden 1.37.4 配置参数详解》有实测对照);- 版本标签锁定为
1.37.4而不是latest,升级节奏由自己控制(第七章)。
写入文件后先做语法校验:
# docker compose -f /opt/data/vaultwarden/compose.yml config --quiet && echo OK
OK
三、服务启动与初始化验证
3.1 拉起服务
# docker compose -f /opt/data/vaultwarden/compose.yml up -d
Image vaultwarden/server:1.37.4 Pulling
Image vaultwarden/server:1.37.4 Pulled
Network vaultwarden_default Creating
Network vaultwarden_default Creating
Network vaultwarden_default Created
Network vaultwarden_default Created
Container vaultwarden-1.37.4-server Creating
Container vaultwarden-1.37.4-server Created
Container vaultwarden-1.37.4-server Starting
Container vaultwarden-1.37.4-server Started
首次启动会自动拉取指定版本并启动服务。查看运行状态:
# docker compose -f /opt/data/vaultwarden/compose.yml ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
vaultwarden-1.37.4-server vaultwarden/server:1.37.4 "/start.sh" vaultwarden 2 seconds ago Up 2 seconds (health: starting) 0.0.0.0:8222->80/tcp, [::]:8222->80/tcp
STATUS 显示 health: starting,服务内置健康检查(访问 /alive),片刻后变为 healthy。
3.2 启动日志检查
# docker logs vaultwarden-1.37.4-server | head -12
/--------------------------------------------------------------------\
| Starting Vaultwarden |
| Version 1.37.4 |
|--------------------------------------------------------------------|
| This is an *unofficial* Bitwarden implementation, DO NOT use the |
| official channels to report bugs/features, regardless of client. |
| Send usage/configuration questions or feature requests to: |
| https://github.com/dani-garcia/vaultwarden/discussions or |
| https://vaultwarden.discourse.group/ |
| Report suspected bugs/issues in the software itself at: |
| https://github.com/dani-garcia/vaultwarden/issues/new |
\--------------------------------------------------------------------/
# docker logs vaultwarden-1.37.4-server | grep "Rocket has launched"
[2026-10-17 08:32:56.280][start][INFO] Rocket has launched from http://0.0.0.0:80
横幅显示版本 1.37.4,Rocket has launched from http://0.0.0.0:80 表示监听就绪(0.0.0.0:80 对应宿主机 8222)。
3.3 三项连通性验证
# curl -s http://127.0.0.1:8222/alive
"2026-10-17T08:33:41.838622Z"
# curl -s -o /dev/null -w "GET / -> %{http_code}\n" http://127.0.0.1:8222/
GET / -> 200
# curl -s -o /dev/null -w "GET /admin -> %{http_code}\n" http://127.0.0.1:8222/admin
GET /admin -> 200
/alive返回 UTC 时间字符串:进程健康;/返回 200:Web Vault 可访问;/admin返回 200:管理台入口就绪(未登录时展示口令输入页)。
3.4 初始化注册第一个用户
若部署时按 2.3 节关闭了注册,第一个用户需要在关闭前注册,或临时放开注册完成后再关闭。实测顺序:先以默认配置(SIGNUPS_ALLOWED 默认 true)启动 → 浏览器打开 http://<服务器>:8222 注册主账户 → 再按第四章关闭注册并重建服务。注册动作由客户端本地派生密钥后提交密文材料,实测 1.37.4 强制 PBKDF2 迭代不低于 100000 轮(网页端默认 600000 轮)。
四、管理员令牌与关闭注册
4.1 配置生效方式
ADMIN_TOKEN 与 SIGNUPS_ALLOWED 在 2.3 节的 compose.yml 中已写入。修改环境变量后需要重建服务实例才能生效(up -d 会检测到变更并重建)。也可改用 /admin 管理台在线修改(管理台会生成数据目录下的 config.json,优先级高于环境变量,详见《Vaultwarden 1.37.4 配置参数详解》),两种方式选一种,避免互相覆盖造成困惑。
4.2 管理台登录验证
用生成 argon2 哈希时的明文口令登录(注意:不是提交哈希串本身):
# curl -s -i -c /tmp/vw_cookies.txt -X POST http://127.0.0.1:8222/admin \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode 'token=q1w2e3r4' | head -1
HTTP/1.1 200 OK
返回 200 即登录成功,服务下发名为 VW_ADMIN 的会话 Cookie(HttpOnly、仅作用于 /admin 路径、有效期 1200 秒即 20 分钟),Cookie 文件中实测记录为:
#HttpOnly_127.0.0.1 FALSE /admin FALSE 1792227099 VW_ADMIN eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3OTIyMjU4OTksImV4cCI6MTc5MjIyNzA5OSwiaXNzIjoiaHR0cHM6Ly92YXVsdC5leGFtcGxlLmNvbXxhZG1pbiIsInN1YiI6ImFkbWluX3BhbmVsIn0.SK7KVKCoUxLD4_b-01_hiHlJUhaetMjFeHT5rs3dKAKKWdgGw1Z6u0SfRKs9PY6KMCb7MpnhteQfUb3W2a6rGKCeUnHgtlf_AoZgocGf7QKnKaC48qpVgUylg_-xogcE1Urmf7KB0WgggxwYcGJrm9CnhVgRDXEC9uVBPUqVKu84JslXkQm99lsHx_I2H4LxbkO3Cyj5KFhfN9dCnCttCYWf-gNx-rtpPpDAdJg55cAu4K50YCXLYcQMidZdXinkQ2AHzcGGkryWz6mQMOctKuxIKi_WxqMBm4H3bRLpi2Ba_sLdIY_eftmAXpRzicVNTM8tgEtW_vKA-4Kv6FtG8Q
解码该 JWT 的 iss 字段是 https://vault.example.com|admin——包含了 DOMAIN 配置值,这也是 2.3 节强调 DOMAIN 要写对外地址的原因之一。错误口令的实测回显(HTTP 401,页面内错误文案):
# curl -s -o /dev/null -w "%{http_code}\n" -X POST http://127.0.0.1:8222/admin \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode 'token=wrong-token'
401
# curl -s -X POST http://127.0.0.1:8222/admin \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode 'token=wrong-token' | grep -o 'Invalid admin token[^<]*'
Invalid admin token, please try again.
管理台登录还有限流保护:实测同一来源连续错误尝试,前 2 次返回 401,第 3 次起返回 429(限流窗口 300 秒、突发额度 3 次为默认配置):
attempt 1 -> 401
attempt 2 -> 401
attempt 3 -> 429
# curl -s -i -X POST http://127.0.0.1:8222/admin \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode 'token=wrong-token' | head -1
HTTP/1.1 429 Too Many Requests
# curl -s -X POST http://127.0.0.1:8222/admin \
-H "Content-Type: application/x-www-form-urlencoded" --data-urlencode 'token=wrong-token' | grep -o 'Too many requests[^<]*'
Too many requests, try again later.
被限流后等待窗口结束或重启服务即可恢复(限流状态保存在内存中)。
4.3 关闭注册验证
SIGNUPS_ALLOWED=false 后尝试注册(实测两步注册流程的第一步就会被拒绝):
# curl -s -w "\nHTTP %{http_code}\n" -X POST http://127.0.0.1:8222/identity/accounts/register/send-verification-email \
-H "Content-Type: application/json" -d '{"email":"user1@vaultwarden.local","name":"user1"}'
{"message":"Registration not allowed or user already exists","validationErrors":{"":["Registration not allowed or user already exists"]},"errorModel":{"message":"Registration not allowed or user already exists","object":"error"},"error":"","error_description":"","exceptionMessage":null,"exceptionStackTrace":null,"innerExceptionMessage":null,"object":"error"}
HTTP 400
服务日志同步出现:
[2026-10-17 08:14:27.652][vaultwarden::api::identity][ERROR] Registration not allowed or user already exists
[2026-10-17 08:14:27.652][response][INFO] (register_verification_email) POST /identity/accounts/register/send-verification-email => 400 Bad Request
看到 Registration not allowed 即加固生效。后续新成员可由管理员在管理台用邀请机制(INVITATIONS_ALLOWED)加入。
五、反向代理 HTTPS 前置说明
5.1 为什么必须 HTTPS
Vaultwarden 的全部数据加解密发生在客户端(《Vaultwarden 介绍与选型指南》第三章),但认证令牌与页面内容仍是明文 HTTP 传输,公网暴露必须套 TLS。实测要点有三:DOMAIN 写反代对外的 https 地址;反代传递 X-Real-IP/X-Forwarded-For,否则服务日志与限流记录到的是代理地址,无法做来源风控(《Vaultwarden 安全加固指南》的 fail2ban 联动依赖真实 IP);反代需放行 WebSocket 升级以保证实时同步。
5.2 自签证书(内网)或正式证书(公网)
内网可用自签证书,公网建议 Let's Encrypt。实测自签生成:
# openssl req -x509 -newkey rsa:2048 -keyout /tmp/vw.key -out /tmp/vw.crt \
-days 3650 -nodes -subj "/CN=vault.example.com"
# openssl x509 -in /tmp/vw.crt -noout -subject -dates
subject=CN = vault.example.com
notBefore=Oct 17 08:22:33 2026 GMT
notAfter=Oct 14 08:22:33 2036 GMT
5.3 nginx 反代配置
反代配置核心内容如下(/etc/nginx/conf.d/vaultwarden-proxy.conf 或站点目录等价位置):
server {
listen 443 ssl;
server_name vault.example.com;
ssl_certificate /etc/nginx/ssl/vw.crt;
ssl_certificate_key /etc/nginx/ssl/vw.key;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 525M;
location / {
proxy_pass http://127.0.0.1:8222;
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 https;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
client_max_body_size 525M:官方 wiki 建议值,避免大附件被代理层拦截;Upgrade/Connection两行保证 WebSocket(实时同步通知)可升级;proxy_pass指向 Vaultwarden 实际可达地址。
实测部署形态:nginx 独立实例监听 8443,转发到宿主机 8222(把上面配置中 listen 443 改为 listen 8443,证书路径指向挂载位置,proxy_pass 指向 host.docker.internal:8222):
# docker run -d --name vaultwarden-nginx -p 8443:443 \
--add-host=host.docker.internal:host-gateway \
-v /tmp/bwtest/vw.crt:/etc/nginx/ssl/vw.crt:ro \
-v /tmp/bwtest/vw.key:/etc/nginx/ssl/vw.key:ro \
-v /tmp/bwtest/vaultwarden-proxy-container.conf:/etc/nginx/conf.d/default.conf:ro \
nginx:alpine
0bbfcb4786d124d01d3414647906f5986d902e4062f6c951b8e5a845bba08f67
# docker exec vaultwarden-nginx nginx -v
nginx version: nginx/1.31.6
5.4 HTTPS 链路验证
# curl -sk https://127.0.0.1:8443/alive
"2026-10-17T08:23:54.292263Z"
# curl -sk -o /dev/null -w "https / -> %{http_code}\n" https://127.0.0.1:8443/
https / -> 200
# curl -sk -o /dev/null -w "https /admin -> %{http_code}\n" https://127.0.0.1:8443/admin
https /admin -> 200
三条全部通过说明 TLS 卸载与转发正常。自签证书下浏览器会提示不受信任(测试用 -k 跳过),公网换正式证书后消失。上线前把 DOMAIN 与反代对外地址核对一致,可在 /admin/diagnostics 的域名配置检查项确认(实测该页输出 HTTPS 状态与域名匹配结果)。
5.5 防火墙收敛
HTTPS 接入后,公网只需保留 443(或自定义的 8443),8222 建议仅内网可达。Ubuntu 22.04 自带 ufw,实测本机当前状态:
# ufw status
Status: inactive
生产启用时按实际网络策略配置规则,原则是:反代监听地址对公网开放,Vaultwarden 原始端口只对内放行;同时保持管理台 /admin 不对公网开放(可在反代层对 /admin 路径加访问控制,详见《Vaultwarden 安全加固指南》)。
六、日常运维命令
# 查看状态
# docker compose -f /opt/data/vaultwarden/compose.yml ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
vaultwarden-1.37.4-server vaultwarden/server:1.37.4 "/start.sh" vaultwarden 2 seconds ago Up 2 seconds (health: starting) 0.0.0.0:8222->80/tcp, [::]:8222->80/tcp
# 重启服务(数据不受影响)
# docker compose -f /opt/data/vaultwarden/compose.yml restart
Container vaultwarden-1.37.4-server Restarting
Container vaultwarden-1.37.4-server Started
# 停止并移除服务实例(数据目录保留)
# docker compose -f /opt/data/vaultwarden/compose.yml down
Container vaultwarden-1.37.4-server Stopping
Container vaultwarden-1.37.4-server Stopped
Container vaultwarden-1.37.4-server Removing
Container vaultwarden-1.37.4-server Removed
Network vaultwarden_default Removing
Network vaultwarden_default Removed
# 再次启动
# docker compose -f /opt/data/vaultwarden/compose.yml up -d
Network vaultwarden_default Creating
Network vaultwarden_default Created
Container vaultwarden-1.37.4-server Creating
Container vaultwarden-1.37.4-server Created
Container vaultwarden-1.37.4-server Starting
Container vaultwarden-1.37.4-server Started
# 健康检查
# curl -s http://127.0.0.1:8222/alive
"2026-10-17T08:33:41.838622Z"
down 只移除服务实例与内部网络,/opt/data/vaultwarden 中的数据库、附件、密钥全部保留。备份策略见《Vaultwarden 运维手册》。
七、升级
7.1 升级原则
数据格式由服务自身兼容(SQLite 库结构自动迁移),升级只需要替换服务版本。两条纪律:先备份再升级(《Vaultwarden 运维手册》第三章);每次只升一个小版本段,出错好回退。
7.2 升级步骤
- 备份数据目录(含 db.sqlite3 与 attachments);
- 修改 compose.yml 中的
image标签为目标版本,例如vaultwarden/server:1.38.x; - 拉取新版本并重建(实测 pull/up 的输出形态,升级时把标签换成新版本即可):
# docker compose -f /opt/data/vaultwarden/compose.yml pull
Image vaultwarden/server:1.37.4 Pulling
Image vaultwarden/server:1.37.4 Pulled
# docker compose -f /opt/data/vaultwarden/compose.yml up -d
Container vaultwarden-1.37.4-server Recreate
Container vaultwarden-1.37.4-server Recreated
Container vaultwarden-1.37.4-server Starting
Container vaultwarden-1.37.4-server Started
- 验证:看启动日志横幅新版本号、
curl /alive正常、网页登录一次并在/admin/diagnostics核对数据库检查无报错; - 回退:把 image 标签改回旧版本执行
up -d即可(若新版本已迁移数据库,回退前必须先还原备份,禁止直接降版本运行)。
7.3 版本跟进建议
订阅 GitHub Releases 通知,安全更新尽快跟进;大版本更新前先在测试环境跑通再上生产。Web Vault 版本随服务一起更新,无需单独处理。
八、参考链接
- Vaultwarden 官方 Wiki(部署总览):https://github.com/dani-garcia/vaultwarden/wiki
- 官方 Wiki(Docker Compose 部署章节):https://github.com/dani-garcia/vaultwarden/wiki/Using-Docker-Compose
- Docker Hub 页面:https://hub.docker.com/r/vaultwarden/server
- 官方 Wiki(HTTPS 反代配置示例):https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS
- 官方 Wiki(fail2ban 与日志联动):https://github.com/dani-garcia/vaultwarden/wiki/Fail2Ban-Setup
- Let's Encrypt 证书签发(certbot):https://certbot.eff.org/
- 本专栏相关:《Vaultwarden 介绍与选型指南》《Vaultwarden 1.37.4 配置参数详解》《Vaultwarden 安全加固指南》《Vaultwarden 运维手册》
- 相关文档:《Keycloak Docker Compose 部署指南》《OpenBao Docker Compose 部署指南》