趁现在自己还记忆犹新,赶紧记录下搭建Vaultwarden的过程。
安全加固措施
- 用
MySQL替换默认SqLite数据库,并配置异地主从数据库备份 - 在Nginx配置
location / {return 403;}屏蔽WEB访问,只保留必要配置 - 启用
OpenVpn+SSL自签证书
搭建开源Vaultwarden
通过Docker容器安装
docker run -d \ --rm \ --name vaultwarden \ -p 8787:80 \ -p 3012:3012 \ -v /home/docker/vaultwarden:/data \ -e DATABASE_URL=mysql://user:password@127.0.0.1:8888/database \ -e SIGNUPS_ALLOWED=false \ -e WEBSOCKET_ENABLED=true \ -e INVITATIONS_ALLOWED=false \ -e ADMIN_TOKEN=your_admin_token \ -e DOMAIN=https://your_url.com \ vaultwarden/server:latest
|
80 web访问端口
3012 webscoket端口
/home/docker/vaultwarden建立目录用于容器外映射配置文件
-d 后台运行--rm 当容器停止时自动删除容器-e DATABASE_URL 配置数据源,默认SqLite(可选)-e SIGNUPS_ALLOWED 允许用户注册(首次用户注册后,删除容器,指定SIGNUPS_ALLOWED=false重新配置容器)-e WEBSOCKET_ENABLED 开启webscoket-e INVITATIONS_ALLOWED 允许邀请用户注册-e ADMIN_TOKEN 管理员令牌-e DOMAIN 配置访问域名(需要是https://xxx.com域名,不能配置ip地址),
切换MySQL数据库
在docker配置容器命令添加:
示例配置:DATABASE_URL=mysql://[[user]:[password]@]host[:port][/database]
# 上述docker命令已包括 -e DATABASE_URL=mysql://vaultwarden_user:strong_password@11.1.0.9:8888/vaultwarden
|
配置私有IP自签名证书
注意:低版本的openssl执行会失败
11.1.0.1是我自签名SSL证书的的IP地址,执行命令得到:ca.crt证书、 ca.key密钥
openssl req -x509 -newkey rsa:2048 -sha256 -days 3650 -nodes \ -keyout ca.key -out ca.crt -subj "/CN=11.1.0.1" \ -addext "subjectAltName=IP:11.1.0.1"
|
由于是使用的自签名证书,需要导入浏览器、安卓手机才能正常访问
配置openVPN
openvpn加固:
- ca.crt 根证书
- x.crt 签发证书
- x.key 签发证书密钥
- 用户名+密码
openvpn导入连接
在移动端导入openvpn配置,需要将.ovpn文件和依赖的根证书ca.crt、自签证书.crt、.key一并选择进行导入


附录
安卓APP相关软件
安卓手机app软件(谷歌商店)
OpenVpn Connect (3.7.1) :开启OpenVPN连接Bitwarden (2025.06.1):密码管理软件Bitwarden Authenticator (2025.6.0) 密码管理软件-两步验证工具
手机导入自签名证书
小米14的证书安装路径如下:
设置->隐私与安全->安全->更多安全设置->更多安全设置->加密与凭据->安装证书->CA证书
选择自签名IP的ca.crt证书安装到手机即可。
Nginx配置
server { listen 8443 ssl; # 监听ovpn地址 server_name 11.1.0.1; # 自签名证书 ssl_certificate /usr/local/nginx/conf/cert/vpn/11.1.0.1.crt; ssl_certificate_key /usr/local/nginx/conf/cert/vpn/11.1.0.1.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
# 仅允许openvpn下IP地址访问 allow 11.1.0.0/24; deny all;
# 屏蔽web端访问 location /{ return 403; }
# 允许 API 访问(确保客户端仍能同步) location /api/ { proxy_pass http://127.0.0.1:8787; 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; }
# 登录接口(web、pc、浏览器插件、app依赖) location /identity/ { proxy_pass http://127.0.0.1:8787; 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; }
# 允许 WebSocket(用于实时同步) location /notifications/hub { proxy_pass http://127.0.0.1:3012/notifications/hub; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
# 其他 location /notifications/hub/negotiate { proxy_pass http://127.0.0.1:8787; 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; }
|
启用MTLS双向认证
配置双向认证后,在公网环境也可以

创建CA根证书(证书颁发机构)
# 创建CA私钥 openssl genrsa -out ca.key 2048
# 创建CA根证书(有效期10年) openssl req -new -x509 -days 3650 -key ca.key -out ca.crt # 需要填写国家、组织等信息
|
创建客户端证书
# 创建客户端私钥 openssl genrsa -out client.key 2048
# 创建证书签名请求(CSR) openssl req -new -key client.key -out client.csr # 需要填写与CA证书类似的信息
# 使用CA签署客户端证书(有效期1年) openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
# 将客户端证书转换为PKCS12格式(方便浏览器导入) openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 # 需要设置导出密码
|
nginx配置
server { listen 9003 ssl; server_name 11.1.0.9;
# 标准SSL配置 ssl_certificate /usr/local/nginx/conf/cert/11.1.0.9/ca.crt; ssl_certificate_key /usr/local/nginx/conf/cert/11.1.0.9/ca.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; #ssl_ciphers HIGH:!aNULL:!MD5;
# 启用客户端证书验证 ssl_client_certificate /usr/local/nginx/conf/cert/CA/ca.crt; ssl_verify_client on; ssl_verify_depth 2; # 调整加密套件 ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305';
location /{ root /usr/local/nginx/html/snowyweb/dist; try_files $uri $uri/ /index.html; index index.html index.htm; } }
|