搭建 Vaultwarden 个人密码保险箱

2026年08月06日·工具效率·#PVE #容器化·30次浏览

摘要:本文介绍在PVE家庭云服务中部署自托管密码管理器Vaultwarden,搭配Bitwarden客户端实现端到端加密。通过Docker Compose与Caddy配置HTTPS,完成部署。备份方面,编写脚本停止服务压缩数据,保留30天,并上传至阿里云OSS实现容灾,最后通过crontab定时每天凌晨4点自动备份。

搭建 Vaultwarden 个人密码保险箱

前言

书接上回《基于 PVE 搭建 All In One 家庭云服务》,在家的小主机上搭建了一套虚拟化环境并安装了 Docker,就需要安装自托管应用让它发挥价值了。

就我个人而言,我的大部分密码都存在了支付宝一个叫“钢铁匣”的小程序里,2FA 则使用的是谷歌的身份验证器 APP。每次打开网站需要登录输入账密时,都要打开小程序找半天密码,很是费事。而且大部分密码虽然都长差不多,但都不相同,记忆不了一点。

为了摆脱记忆的困扰,以及密码的安全(保证每个平台密码不一样),就需要使用到密码管理器了。我选用的是 Vaultwarden1 作为服务端,搭配 Bitwarden2 的客户端,做到密码的端到端加密且自托管。

至于为什么不直接使用 Bitwarden 呢?一方面是 Bitwarden 的免费计划不支持 2FA 密钥,另一方面是听说它的私有部署比较重量级,而 Vaultwarden 比较轻量化且完全兼容 Bitwarden 客户端。

本文一方面介绍部署和使用,但是最重要的还是需要保证数据的可靠性,通过备份以及上传异地,保证密码数据不丢。

部署

通过 Docker Compose 编排部署,因为 Vaultwarden 要求访问必须使用 HTTPS,所以需要加上一个 Caddy 反向代理自动颁发证书。

docker-compose.yml编排文件如下:

yaml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    volumes:
      - ./vw-data:/data  # 数据持久化目录
    networks:
      - vault-net
    environment:
      # 必须替换为你的真实域名(需包含 https://)
      - DOMAIN=https://vw.local
      # 时区      
      - TZ=Asia/Shanghai
      # 首次部署设为 true 以注册管理员,注册后务必改为 false
      - SIGNUPS_ALLOWED=true
      # 生成管理员令牌,用于访问后台 /admin 管理面板。首次设置完成后置空,有需要再临时填入
      - ADMIN_TOKEN=123123
      # 是否启用网页端
      - WEB_VAULT_ENABLED=true
      # 是否启用多端实时同步
      - WEBSOCKET_ENABLED=true
      # 是否开始加密分享
      - SENDS_ALLOWED=false
  
  caddy:
    image: caddy:2
    container_name: caddy
    restart: always
    ports:
      # HTTP 端口,用于 ACME 验证和自动跳转 HTTPS
      - "80:80"
      # HTTPS 端口
      - "443:443" 
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy/data:/data
      - ./caddy/config:/config
      - ./caddy/logs:/logs
    environment:
      # 同意 Let's Encrypt 服务条款
      - ACME_AGREE=true
    networks:
      - vault-net
    depends_on:
      - vaultwarden

networks:
  vault-net:
   driver: bridge 

配置caddy/Caddyfile对 Vaultwarden 进行反向代理:

text
vw.local {
  tls internal  # 只在内网使用时,使用自签名证书。外网使用去掉这行
  reverse_proxy vaultwarden:80
}

启动项目:

bash
docker compose up -d

容器启动
容器启动

然后在本地配置 host 文件指定vw.local的 IP 为 Docker 的 IP。浏览器访问时,会提示证书不可信,要么手动信任,要么手动安装 caddy 的根证书到设备上。

本地测试手动信任证书
本地测试手动信任证书

之后创建账号,登录使用即可。创建账号后,务必关闭注册,然后重新启动项目。

部署成功
部署成功

备份

在 Vaultwarden Wiki 中有提到相关备份事项3,因为是个人使用,我采用的是非使用期间停机完整备份,保证数据一点不丢。

编写备份脚本backup.sh,包含停机、备份、压缩、重启、清理历史:

bash
#!/bin/bash
set -e

# 1. 目录切换与检查
cd "$(dirname "$0")"
[ -f "docker-compose.yml" ] || { echo "❌ 找不到 compose 文件"; exit 1; }
[ -d "./vw-data" ] || { echo "❌ 数据目录不存在"; exit 1; }

# 2. 停止服务
echo "🛑 停止 Vaultwarden..."
docker compose down
sleep 10

# 3. 备份
echo "📦 压缩备份..."
datestamp=$(date +%Y%m%d_%H%M%S)
backup_dir="./vw-backups"
mkdir -p "${backup_dir}"
if zip -9 -r "${backup_dir}/${datestamp}.zip" ./vw-data/ && [ -f "${backup_dir}/${datestamp}.zip" ]; then
    file_size=$(du -h "${backup_dir}/${datestamp}.zip" | cut -f1)
    echo "✅ 备份文件创建成功: $file_size"
else
    echo "❌ 备份创建失败"
    exit 1
fi

# 4. 启动服务
echo "🚀 启动 Vaultwarden..."
docker compose up -d
sleep 10
SERVICE_NAME=$(docker compose config --services | head -1)
if docker compose ps "$SERVICE_NAME" | grep -q "Up"; then
    echo "✅ $SERVICE_NAME 已启动"
else
    echo "❌ $SERVICE_NAME 启动失败"
    docker compose ps
    exit 1
fi

# 5. 清理
echo "🧹 清理30天前的备份..."
deleted=$(find "$backup_dir" -name "*.zip" -type f -mtime +30 -delete -print | wc -l)
remaining=$(find "$backup_dir" -name "*.zip" -type f | wc -l)
echo "📊 删除了 $deleted 个旧备份,当前保留 $remaining 个备份"

echo "✅ 备份完成!"

先安装脚本中使用到的压缩工具,添加运行权限,即可运行:

bash
apt install zip
chmod +x backup.sh
./backup.sh

备份成功
备份成功

而 Vaultwarden 的所有数据都挂载到宿主机的vw-data数据目录,所以备份恢复只需要停机、删除vw-data目录、解压备份文件转移到数据目录即可。

备份恢复
备份恢复

容灾

当备份文件与项目都运行在同一台机器时,对重要数据来说是很不安全的。万一机器崩溃了,备份就丢失了,不妥。

这里要做第二份备份,把备份文件上传到对象存储中。这里使用阿里云 OSS 对象存储提供的命令行工具完成。

使用前,安装并配置ossutil4,写入配置文件ossutil.ini,并按照实际修改:

ini
[default]
accessKeyID=yourAccessKeyID
accessKeySecret=yourAccessKeySecret
# region 需要修改成实际存储桶所在地域
region=cn-shenzhen
buckets=prod-bucket

[buckets prod-bucket]
# 把 zyaer-vw-backup 修改成实际存储桶名
zyaer-vw-backup =
  # 同地域ECS可以设置成内网endpoint,也可以设置成不同地域的外网endpoint,理论上不同地域更安全
  endpoint=https://oss-cn-shenzhen.aliyuncs.com

然后在备份脚本尾部添加阿里云上传脚本代码:

bash
# 6. 备份容灾
echo "☁️ 正在上传最新备份至阿里云OSS..."
BACKUP_FILE_PATH="./vw-backups/${datestamp}.zip"
# 需要注意,这里 zyaer-vw-backup 需要修改成自己实际存储桶名
OSS_TARGET_PATH="oss://zyaer-vw-backup/"    

if ossutil -c ./ossutil.ini cp "$BACKUP_FILE_PATH" "$OSS_TARGET_PATH" -f; then
    echo "✅ 备份文件已成功上传至 $OSS_TARGET_PATH"
else
    echo "❌ 备份上传失败,请检查配置。"
    # 根据你的需求决定是否让脚本在此失败
    # exit 1
fi

备份上传成功示例如下:

备份上传阿里云对象存储成功
备份上传阿里云对象存储成功

定时

直接使用 Linux 系统的 crontab,首次运行会提示选择文本编辑器:

bash
crontab -e

在打开的文件末尾新增定时器,每天凌晨4点执行备份脚本,保存并退出文本即可。

bash
# 脚本中路径修改成实际绝对路径
0 4 * * * /root/vaultwarden/backup.sh >> /root/vaultwarden/backup.log 2>&1

配置定时任务
配置定时任务

结语

最后,我们的项目目录如下:

text
./vaultwarden/
├── docker-compose.yml    # 容器编排文件
├── caddy/                # Caddy 数据目录
│   └── Caddyfile         # 反向代理配置文件
├── vw-data/              # Vaultwarden 数据目录
├── vw-backups/           # Vaultwarden 备份目录(自动生成)
├── ossutil.ini           # 阿里云 OSS 配置文件
├── backup.log            # 备份脚本运行日志(自动生成)
└── backup.sh             # 备份脚本

至此,我们就拥有了一个只属于自己的个人密码保险箱,所有数据都是加密的,只要主密码不泄露,我们的所有账号密码都不会泄露。同时备份与容灾也给了我们的密码一个保障,避免单点故障导致的数据丢失。

按照本文搭建好服务端后,如果是内网设备则再接入内网穿透,后续配合 Bitwarden 的各种客户端,即可享受到多端同步的乐趣了。

Footnotes

  1. Vaultwarden

  2. Bitwarden

  3. Backing up your vault

  4. 命令行工具ossutil 2.0

搭建 Vaultwarden 个人密码保险箱

https://www.zyaer.com/posts/set-up-vaultwarden-personal-password-safe

作者发布时间Licensezyaer2026-08-06CC BY-NC-SA 4.0
下一篇已是最新文章