事情的起因是这样的,最近 qq 盗号现象频发,就连我也差一点中招,然后昨天晚上又梦到自己的密码都泄露了,我也深知目前把所有的密码都设置成一样的是很不安全的,于是在 L 站发帖求助,最终决定直接自建一个 Bitwarden ,并逐步的密码将随机化。
前置条件
完成这个自建过程最基础的要求是一台服务器(很小的就可以)和一个域名,最好再有一个cloudflare账号,因为 cf 有 10GB 的免费对象存储,可以作为密码的备份(如果使用 Google ,阿里等对象存储都一样,目的都是为了避免服务器数据丢失)
安装 vaultwarden
我们这里使用的其实并不是 Bitwarden-Server ,他对服务器的要求还是挺高的,但是社区开源了一个 Rust 重写版本,大大减小了部署门栏。
首先在合适位置创建 vaultwarden 文件夹,比如/opt下 ,然后添加一个docker-compose.yml:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
# 限制一下资源,虽然它用不了这么多,但在混合部署的服务器上是个好习惯
mem_limit: 512m
environment:
# 1. 域名配置:这对于邀请邮件中的链接生成非常重要
- DOMAIN=https://域名
# 2. 开启新用户注册:首次部署必须开启,注册完你自己后,建议改为 false 并重启
- SIGNUPS_ALLOWED=true
# 3. 后台管理 Token:只有拥有这个 Token 才能访问 /admin 页面
- ADMIN_TOKEN=粘贴_你的_openssl_生成的_长字符串_在这里
# 4. WebSocket:为了支持多端实时同步(如手机修改密码,浏览器插件立刻更新)
- WEBSOCKET_ENABLED=true
# 5. 日志记录:可选,方便排错
- LOG_FILE=/data/vaultwarden.log
- LOG_LEVEL=warn
volumes:
# 核心数据映射:这是你唯一需要备份的目录
- ./vw-data:/data
ports:
# 映射端口:宿主机端口:容器端口
# 如果 8080 被占用,请修改左边的数字,例如 3012:80
- 8080:80YAML需要注意几行:
- 10:将域名替换为实际使用的域名,在邀请时会用的。(据了解,二级身份验证的就可能也会跟域名有关,但是经过测试好像并没有关系)
- 16:需要一个强密码,建议是使用
openssl rand -base64 48生成一个,并在本地保存。 - 32:设置我们希望的端口,注意不要跟服务器上已有的端口冲突
确认文件无误后,就可以在本目录下执行 docker compose up -d 来启动容器。如果想测试一下,我们可以将设置的端口在安全组中开放,然后使用 http 访问一下试试。
部署到公网
这一步我尝试了二种方式,大家选一个适合自己的就行:
- 使用 cloudflare 建立 Tunnel,将 cloudflare 作为服务的入口
- 直接在服务器进行 caddy 的反向代理
Cloudflare Tunnel 方案
第一步:创建隧道
- 在左侧找到
Zero Trust - 点击左侧菜单栏中的 网络 -> 连接器
- 点击 创建隧道
- 隧道类型选择 Cloudflared
- 给隧道起一个名字,例如 vps-vaultwarden,完成创建
第二步:安装连接器
- 在环境中选择 docker , 然后回到服务器执行页面下方为我们提供的指令,指令类似于:
docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoi…… - 完成之后回到 cf , 可以看到连接状态已经变成了 已连接
- 下一步
第三部:配置路由
这里决定了你用什么域名访问你的密码库。
- Public Hostname 选项卡中:
- Subdomain:填
pass(或者你喜欢的名字,如bw)。 - Domain:在下拉菜单选择你托管在 CF 的域名。
- Path:留空。
- Subdomain:填
- Service 部分 (把流量转发给刚才运行的 Docker):
- Type:选择
HTTP。 - URL:使用 地址:端口 的方式,端口是在安装步骤中自定义的端口,但是如果我们是使用 docker 部署的 vaultwarden (就比如我们的安装模式),地址应该写
172.17.0.1,这是 docker 容器默认的 IP,或者也可以使用网络组的模式,不在多说。
- Type:选择
- 点击 Save Tunnel。
完成之后就可以去访问我们的域名了,理论上是没有任何问题的。
caddy 反向代理方案
这个方案更加简单,而且我的服务器上已经有在运行的 caddy 了,所以如何安装就不再赘述了。
- 在域名服务商添加一条A记录解析,解析到我们的服务器。
- 在 caddyfile 中添加下面内容。
systemctl restart caddy重启caddy服务。
域名 {
encode gzip
reverse_proxy 127.0.0.1:8032 {
header_up X-Real-IP {remote_host}
}
}Plaintext完成之后就可以去访问我们的域名了,理论上是没有任何问题的(当然添加解析记录可能需要一定的时间)。
关闭注册功能
到这里我们的服务就已经可用了,但是还有没有结束,现在依然保留了用户注册功能,作为只用的密码管理员,我们当然要将这个功能给关掉,但是为什么不一开始就禁用呢?因为一开始就禁用了的话我们自己也注册不了了傻宝🤣
确定不再需要注册功能后,修改docker-compose.yml中的SIGNUPS_ALLOWED 项改为 false ,然后执行 docker compose up -d 就可以
但是我们回到登录页依然可以看到注册按钮,不要慌,注册一下试试,会直接报错。
配置定期数据备份
这里使用的备份方案是,每天将备份文件发送到 Cloudflare R2 一次。
第一步:开通 Cloudflare R2
- 在控制台左侧点击 存储和数据库 -> R2对象存储 -> 概述
- 创建存储桶,名字任意,例如:vw-backup
- 回到概述页 ,点击
API Tokens右面的Manage - 点击 创建 Account API 令牌 ,权限为管理员读和写
- 保存好提供的
Access Key ID,Secret Access Key, 和Endpoint,这些信息再关闭页面后就找不到了,只能再次创建,建议时候后将本地记录页销毁,再使用时直接新建
第二步:在服务器上安装并配置 Rclone
apt update,apt install reclone -y,完成安装- 使用
rclone --version确认安装成功 - 执行
rclone config开始配置(输入前面的需要即可):n(New remote) -> 名字填r2。Storage选s3(Amazon S3 Compliant Storage)。Provider选Cloudflare。access_key_id-> 填刚才 CF 展示的。secret_access_key-> 填刚才 CF 展示的。region->auto。endpoint-> 填刚才 CF 展示的那个 URL。- 不需要高级配置
- 一路回车默认即可。
- 退出配置
- 完成后执行
rclone lsd r2:,应该就可以看到刚刚创建的桶的名字了(vw-backup)
第三步:编写备份 Shell 脚本
在/opt/vaultwarden 下创建一个 backup.sh :
#!/bin/bash
# === 配置区 ===
BACKUP_PATH="/opt/vaultwarden/backups"
DATA_PATH="/opt/vaultwarden/vw-data"
RCLONE_REMOTE="r2:vw-backup" # r2是刚才配置的名字,vw-backup是桶名
# !!!请修改这个密码,这是备份文件的解压密码!!!
ZIP_PASSWORD="YourStrongPasswordHere123!"
DATE=$(date +%Y%m%d_%H%M%S)
ARCHIVE_NAME="vw_backup_${DATE}.zip"
# === 1. 准备环境 ===
mkdir -p $BACKUP_PATH
# === 2. 暂停容器 (保证数据库一致性) ===
echo "Stopping Vaultwarden..."
docker compose -f /opt/vaultwarden/docker-compose.yml stop
# === 3. 压缩并加密 ===
# 使用 zip -e 设置密码,-r 递归
echo "Compressing and Encrypting..."
cd /opt/vaultwarden
# 注意:这里把你整个数据目录打包了
zip -P "$ZIP_PASSWORD" -r "$BACKUP_PATH/$ARCHIVE_NAME" vw-data
# === 4. 恢复容器 ===
echo "Starting Vaultwarden..."
docker compose -f /opt/vaultwarden/docker-compose.yml start
# === 5. 上传到 Cloudflare R2 ===
echo "Uploading to R2..."
rclone copy "$BACKUP_PATH/$ARCHIVE_NAME" "$RCLONE_REMOTE"
# === 6. 清理 ===
# 删除本地超过 7 天的备份(节省VPS硬盘)
find $BACKUP_PATH -name "*.zip" -type f -mtime +7 -delete
# 删除云端超过 30 天的备份(rclone 命令)
# --min-age 30d 表示只删除 30 天前的文件
rclone delete --min-age 30d "$RCLONE_REMOTE"
echo "Backup done: $ARCHIVE_NAME"Plaintext需要注意第六行和第八行,其中第六行的配置要与之间一致,而第八行的密码是我们备份文件的解压密码!
完成之后可以先测试一下:chmod +x /opt/vaultwarden/backup.sh添加执行权限, apt install zip -y 添加 zip指令,/opt/vaultwarden/backup.sh执行文件,不出意外的话,我们的桶中就多一个 zip 备份文件。
第四步:设置定时文件
执行crontab -e ,第一次可能会让我们选择使用那个文本编辑工具,根据自己的习惯选择即可,然后在文件中添加:0 3 * * * /opt/vaultwarden/backup.sh >> /opt/vaultwarden/backup.log 2>&1保存即可。
Comments NOTHING