自建 Bitwarden 管理密码

gomkiri 发布于 2025-11-21 83 次阅读


AI 摘要

担心密码泄露?自建Bitwarden密码管理器,用Docker轻松部署,支持多端实时同步。从服务器配置到自动备份,手把手教你搭建专属密码库,告别重复密码的安全隐患。

事情的起因是这样的,最近 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:80
YAML

需要注意几行:

  • 10:将域名替换为实际使用的域名,在邀请时会用的。(据了解,二级身份验证的就可能也会跟域名有关,但是经过测试好像并没有关系)
  • 16:需要一个强密码,建议是使用openssl rand -base64 48生成一个,并在本地保存。
  • 32:设置我们希望的端口,注意不要跟服务器上已有的端口冲突

确认文件无误后,就可以在本目录下执行 docker compose up -d 来启动容器。如果想测试一下,我们可以将设置的端口在安全组中开放,然后使用 http 访问一下试试。

部署到公网

这一步我尝试了二种方式,大家选一个适合自己的就行:

  1. 使用 cloudflare 建立 Tunnel,将 cloudflare 作为服务的入口
  2. 直接在服务器进行 caddy 的反向代理

Cloudflare Tunnel 方案

第一步:创建隧道

  1. 在左侧找到 Zero Trust
  2. 点击左侧菜单栏中的 网络 -> 连接器
  3. 点击 创建隧道
  4. 隧道类型选择 Cloudflared
  5. 给隧道起一个名字,例如 vps-vaultwarden,完成创建

第二步:安装连接器

  1. 在环境中选择 docker , 然后回到服务器执行页面下方为我们提供的指令,指令类似于:docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoi……
  2. 完成之后回到 cf , 可以看到连接状态已经变成了 已连接
  3. 下一步

第三部:配置路由

这里决定了你用什么域名访问你的密码库。

  1. Public Hostname 选项卡中:
    • Subdomain:填 pass (或者你喜欢的名字,如 bw)。
    • Domain:在下拉菜单选择你托管在 CF 的域名。
    • Path:留空。
  2. Service 部分 (把流量转发给刚才运行的 Docker):
    • Type:选择 HTTP
    • URL:使用 地址:端口 的方式,端口是在安装步骤中自定义的端口,但是如果我们是使用 docker 部署的 vaultwarden (就比如我们的安装模式),地址应该写172.17.0.1 ,这是 docker 容器默认的 IP,或者也可以使用网络组的模式,不在多说。
  3. 点击 Save Tunnel

完成之后就可以去访问我们的域名了,理论上是没有任何问题的。

caddy 反向代理方案

这个方案更加简单,而且我的服务器上已经有在运行的 caddy 了,所以如何安装就不再赘述了。

  1. 在域名服务商添加一条A记录解析,解析到我们的服务器。
  2. 在 caddyfile 中添加下面内容。
  3. 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

  1. 在控制台左侧点击 存储和数据库 -> R2对象存储 -> 概述
  2. 创建存储桶,名字任意,例如:vw-backup
  3. 回到概述页 ,点击API Tokens右面的 Manage
  4. 点击 创建 Account API 令牌 ,权限为管理员读和写
  5. 保存好提供的Access Key ID, Secret Access Key, 和 Endpoint,这些信息再关闭页面后就找不到了,只能再次创建,建议时候后将本地记录页销毁,再使用时直接新建

第二步:在服务器上安装并配置 Rclone

  1. apt update , apt install reclone -y ,完成安装
  2. 使用rclone --version 确认安装成功
  3. 执行rclone config开始配置(输入前面的需要即可):
    • n (New remote) -> 名字填 r2
    • Storages3 (Amazon S3 Compliant Storage)。
    • ProviderCloudflare
    • access_key_id -> 填刚才 CF 展示的。
    • secret_access_key -> 填刚才 CF 展示的。
    • region -> auto
    • endpoint -> 填刚才 CF 展示的那个 URL。
    • 不需要高级配置
    • 一路回车默认即可。
    • 退出配置
  4. 完成后执行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保存即可。