自托管 Vaultwarden 并配置 WebDAV 自动备份
我此前一直使用的是 Bitwarden 官方在欧洲的服务器,今年开始感觉在中国大陆连接性不太好,经常性的无法连接。由于各种原因,我的安卓设备不方便安装代理软件,但我有多台拥有中国路由优化的海外服务器,因此我选择在我自己的服务器上自托管 Vaultwarden,一个 Rust 写的 Bitwarden 轻量实现。为了确保密码库的安全和防止我手贱删库,我需要一套完整的方案:容器化部署 + WebDAV 异地备份 + 失败通知推送,突出一个安心!
最终我选择在洛杉矶 VPS 上通过 Caddy 反向代理 Docker 内安装的 Vaultwarden,并实现上述功能。
1. 安装 Docker
在开始之前,确保服务器已安装 Docker。用官方的一键安装脚本:
curl -fsSL https://get.docker.com | sh
2. 创建工作目录
建议将所有配置文件放在统一目录下,方便管理:
mkdir -p ~/vaultwarden/vw_data
mkdir -p ~/vaultwarden/rclone
cd ~/vaultwarden
目录结构如下:
~/vaultwarden/
├── docker-compose.yaml
├── .env
├── rclone/
│ └── rclone.conf
└── vw_data/ # Vaultwarden 数据目录
3. 编写 Docker Compose 配置
编写 docker-compose.yaml,包含 Vaultwarden 主程序和备份插件。注意,配置文件中使用的 ${VARIABLE} 语法会自动从后续步奏创建的 .env 文件中读取变量。
services:
vaultwarden:
image: ghcr.io/dani-garcia/vaultwarden:latest
container_name: vaultwarden
restart: unless-stopped
volumes:
- ./vw_data/:/data/
environment:
- DOMAIN=${DOMAIN} # 域名
- ADMIN_TOKEN=${ADMIN_TOKEN} # 管理员Token
- SIGNUPS_ALLOWED=false # 禁止注册
- LOG_LEVEL=error # 日志级别
- SENDS_ALLOWED=false # 禁止使用 Send
- TRASH_AUTO_DELETE_DAYS=7 # 自动删除回收站
ports:
- 127.0.0.1:8888:80 # 仅限本地访问,Caddy 反向代理
backup:
image: ttionya/vaultwarden-backup:latest
container_name: vaultwarden-backup
restart: unless-stopped
environment:
- RCLONE_REMOTE_NAME=WebDAV
- RCLONE_REMOTE_DIR=/vaultwarden-backup/
- CRON=0 3 * * * # 每天凌晨 3 点执行备份
- ZIP_ENABLE=TRUE # 启用压缩
- ZIP_PASSWORD=${BACKUP_PASSWORD} # 压缩密码
- ZIP_TYPE=7z # 压缩格式
- BACKUP_FILE_SUFFIX=%Y%m%d-%H%M%S # 备份文件名后缀
- BACKUP_KEEP_DAYS=30 # 保留备份天数
- TIMEZONE=Asia/Hong_Kong # 时区
- PING_URL_WHEN_FAILURE=https://ntfy.sh/${NTFY_KEY}|https://api.day.app/${BARK_KEY}/Vaultwarden备份失败/请检查日志?sound=alarm&level=timeSensitive&group=backup
- 'PING_URL_WHEN_FAILURE_CURL_OPTIONS=-H "Title: ⚠️ Vaultwarden 备份失败" -H "Priority: urgent" -H "Tags: warning,backup,vaultwarden" -d "备份任务执行失败,请立即检查服务器日志"'
volumes:
- ./vw_data/:/bitwarden/data/:ro
- ./rclone:/config/rclone
depends_on:
- vaultwarden
4. 配置环境变量 (.env)
为了安全和方便管理,我们将敏感信息抽离到 .env 文件中。
首先,生成 ADMIN_TOKEN 的 Argon2 哈希加密:
docker run --rm -it vaultwarden/server /vaultwarden hash
然后,创建环境配置文件 .env,将生成的哈希值填入:
cat <<EOF > .env
DOMAIN=https://vault.example.com
ADMIN_TOKEN=你的管理员Token哈希值
BACKUP_PASSWORD=你的备份压缩包密码
NTFY_KEY=你的ntfy密钥
BARK_KEY=你的Bark密钥
EOF
5. 配置 rclone (WebDAV 存储)
备份容器使用 rclone 将加密压缩包上传到 WebDAV 远程存储。WebDAV 服务我用的是 Koofr,多年前我就购买了 Koofr 的永久 100G 存储空间,长期用下来性价比很高。
# 交互式配置 rclone,在 ~/vaultwarden 路径下执行
docker run --rm -it \
-v $(pwd)/rclone:/config/rclone \
ttionya/vaultwarden-backup:latest \
rclone config
配置要点:
- Name: 输入
WebDAV。 - Storage: 选择
webdav。 - URL: 输入
https://app.koofr.net/dav/Koofr。 - Vendor: 选择
other。 - User/Pass: 输入 WebDAV 账号和应用专用密码。
- 注意: 密码必须通过此交互界面生成,rclone 会自动对其进行混淆(Obscure),直接在配置文件写明文会导致报错。
配置完成后,~/vaultwarden/rclone/rclone.conf 内容大致如下:
[WebDAV]
type = webdav
url = https://app.koofr.net/dav/Koofr
vendor = other
user = your_email@example.com
pass = xxx_your_obscured_password_xxx
配置完成后,即可启动服务:
docker compose up -d
6. Caddy 反向代理与 GeoIP 限制
为了提高安全性,使用带有 maxmind_geolocation 模块的 Caddy,限制仅允许中国大陆 IP 访问。
编辑 /etc/caddy/conf.d/vault.caddy:
# --- Vaultwarden ---
vault.example.com {
# 日志配置
log {
level INFO
output file /var/log/caddy/vaultwarden.log {
roll_size 10MB
roll_keep 10
}
}
# GeoIP 匹配器:仅允许中国大陆
@china {
maxmind_geolocation {
db_path "/etc/caddy/GeoLite2-Country.mmdb"
allow_countries CN
}
}
# 匹配成功:反代到 Vaultwarden
handle @china {
encode zstd gzip
reverse_proxy localhost:8888 {
header_up X-Real-IP {remote_host}
}
}
# 匹配失败:返回 403
handle {
respond "Access Denied: China only" 403
}
}
7. 坑点总结
1. rclone 配置文件路径
备份容器 ttionya/vaultwarden-backup 默认寻找配置的路径是 /config/rclone/rclone.conf。
在挂载时,建议挂载整个目录:- ./rclone:/config/rclone,这样 rclone 在更新配置时不会因为文件被占用(Device or resource busy)而失败。
2. RCLONE_REMOTE_NAME 匹配
docker-compose.yaml 中的 RCLONE_REMOTE_NAME 必须与 rclone.conf 中方括号内的名称完全一致。
例如配置里是 [WebDAV],环境变量就必须是 WebDAV。
8. 最后
从开始到放弃很快的,最后的最后,我删掉了所有内容,毕竟跟我自己的技术相比我还是更相信 Bitwarden 官方,,,,而且一年只需要 10美金十分良心了,慢点就慢点吧,又不是不能用🥲。