Featured image of post 使用 Vaultwarden 部署私有化 Bitwarden 实例

使用 Vaultwarden 部署私有化 Bitwarden 实例

Vaultwarden 是一个轻量级的开源 Bitwarden 服务器实现,使用 Vaultwarden 可以在自己的服务器上部署一个私有化的 Bitwarden 实例,从而更好地保护密码的安全性和隐私。详细步骤,即在其中……

前言

Bitwarden 是一款开源的密码管理工具,不仅能保存和管理密码,还拥有密码生成、自动填充、多端同步等功能。Bitwarden 的另一个重要优势是可以自托管,用户可以在自己的服务器上部署 Bitwarden,以获得更高的安全性和隐私保护。Vaultwarden 是一个由社区维护的 Bitwarden 服务端实现,相比于官方的 Bitwarden 服务器,Vaultwarden 更加轻量级,并且能够完全兼容官方的 API 和客户端。

本文将介绍如何使用 Vaultwarden 在 Ubuntu 服务器上部署一个私有化的 Bitwarden 实例。除了 Vaultwarden 服务器本身,我们还需要一个反向代理服务器来处理 HTTPS 请求,并且为了保证数据的安全性,还需要一个定期备份的机制。我们将使用 Caddy 作为反向代理服务器,因为它可以自动申请和续期 SSL 证书,并且配置简单易用。最后,我们还会介绍如何使用 Docker Compose 来管理这些服务,一共运行三个容器:Vaultwarden、Caddy 和备份服务。

配置

安装 Docker

首先,安装 Docker 和 Docker Compose:

sudo apt update && sudo apt upgrade -y
sudo apt install docker.io docker-compose -y
sudo systemctl enable docker --now
sudo usermod -aG docker $USER

创建目录结构

我们将所有的数据和配置文件都放在 /opt/vaultwarden 目录下,具体目录结构如下:

.
├── backup/                 # 备份目录
├── caddy/                  # Caddy 相关文件
│   ├── Caddyfile           # Caddy 配置文件
│   ├── config/             # Caddy 配置保存目录
│   ├── data/               # Caddy 数据保存目录
│   └── Dockerfile          # 创建自定义 Caddy 镜像的 Dockerfile
├── data/                   # Vaultwarden 数据目录
├── backup.sh               # 备份脚本
├── docker-compose.yml      # Docker Compose 配置文件
└── .env                    # 环境变量配置文件

使用以下命令创建目录结构,并将当前用户设置为 /opt/vaultwarden 目录的所有者:

sudo mkdir /opt/vaultwarden
sudo chown $(id -gn ${USER}):${USER} /opt/vaultwarden
cd /opt/vaultwarden
mkdir caddy data backup
mkdir caddy/{data,config}

Docker Compose 配置

首先在 /opt/vaultwarden 目录下创建 docker-compose.yml 文件,内容如下:

version: "3"

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    volumes:
      - ./data:/data
    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=false
      - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
    networks:
      - internal

  caddy:
    build:
      context: ./caddy
    container_name: caddy
    restart: unless-stopped
    ports:
      - "16443:16443"
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - ./caddy/data:/data
      - ./caddy/config:/config
    environment:
      - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
    networks:
      - internal

  backup:
    image: busybox:latest
    container_name: vaultwarden-backup
    restart: unless-stopped
    command: ["/opt/vaultwarden/backup.sh"]
    volumes:
      - ./data:/data
      - ./caddy:/caddy
      - ./backup:/backup
      - ./backup.sh:/opt/vaultwarden/backup.sh
    networks:
      - internal

networks:
  internal:
    driver: bridge

docker-compose.yml 中,我们配置了3个镜像,分别是 Vaultwarden、Caddy 和备份服务。

Vaultwarden 镜像使用官方的 vaultwarden/server:latest,并将数据目录挂载到主机的 ./data 目录下。环境变量中的 ADMIN_TOKEN 是 Vaultwarden 的管理令牌,用于访问管理界面,这里使用 ${VAULTWARDEN_ADMIN_TOKEN} 的语法,在 .env 文件中进行配置,避免在 docker-compose.yml 中明文写入。

Caddy 镜像使用自定义的 Dockerfile 构建,配置文件挂载到 /etc/caddy/Caddyfile,数据和配置目录分别挂载到主机的 ./caddy/data./caddy/config 目录下。环境变量中的 CLOUDFLARE_API_TOKEN 用于 Cloudflare DNS 验证,同样在 .env 文件中进行配置。另外,由于 443 端口可能被 ISP 屏蔽,我们使用非标的 16443 端口提供服务。

最后,备份服务的主体使用 bash 脚本实现,定期备份 Vaultwarden 和 Caddy 的数据。

配置 Caddy

/opt/vaultwarden/caddy 目录下创建 Caddyfile,内容如下:

your.domain.com:16443 {
    encode gzip
    reverse_proxy vaultwarden:80

    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
}

这里的 your.domain.com 需要替换为你自己的域名。如果在 docker-compose.yml 中配置了别的端口号,也需要相应地修改此处的端口号。{env.CLOUDFLARE_API_TOKEN} 引用了 docker-compose.yml 中传递的环境变量。

/opt/vaultwarden/caddy 目录下创建 Dockerfile,内容如下:

FROM caddy:2-builder AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare

FROM caddy:2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

这里利用了 caddy:2-builder 作为构建器,编译了带有 Cloudflare DNS 插件的 Caddy 2 可执行文件,并替换了 caddy:2 官方镜像中的可执行文件。由于在 docker-compose.yml 中已经配置了构建过程,我们并不需要手动调用 docker builddocker-compose 会自动处理。

配置备份

/opt/vaultwarden 目录下创建 backup.sh,内容如下:

#!/bin/sh

while true; do
  tar -czf /backup/vaultwarden-$(date +\%F-\%H\%M).tar.gz /data /caddy;
  find /backup -type f -mtime +7 -exec rm {} \;;
  sleep 86400;
done

这个脚本会每天备份一次 Vaultwarden 和 Caddy 的数据,并自动删除超过 7 天的备份文件。这个功能也可以使用 cron 定时任务来实现,但在这个简单的场景中, cron 有点太“重”了,使用脚本的方式更加轻量级。

配置环境变量

/opt/vaultwarden 目录下创建 .env 文件,内容如下:

VAULTWARDEN_ADMIN_TOKEN=your_admin_token
CLOUDFLARE_API_TOKEN=your_cloudflare_api_token

这里保存了 Vaultwarden 的管理令牌和 Cloudflare 的 API 令牌。Vaultwarden 的管理令牌可以是任意一个字符串,Cloudflare 的 API 令牌可以在 Cloudflare 的用户设置中找到。为了保证安全,应该把 .env 文件的权限设置为只有当前用户可读写。

chmod 600 /opt/vaultwarden/.env

运行

完成配置后,可以使用以下命令启动服务:

docker-compose up -d

一切正常的话,会有类似以下输出:

Creating network "vaultwarden_internal" with driver "bridge"
Creating caddy              ... done
Creating vaultwarden-backup ... done
Creating vaultwarden        ... done

查看 caddy 容器的日志,应该能看到成功申请证书的消息:

docker-compose logs caddy

访问 https://your.domain.com:16443,应该能看到 Vaultwarden 的登录界面。再访问 http://your.domain.com:16443/admin,应该能看到 Vaultwarden 的管理界面。使用在 .env 文件中配置的 VAULTWARDEN_ADMIN_TOKEN 进行登录,即可以配置 Vaultwarden 了。大部分配置保持默认即可,不过为了方便增加账号,推荐配置一个有效的 SMTP 服务器,GMail 或 QQ 邮箱均可,就可以通过邮件邀请其他用户注册了;如果不配置 SMTP 服务器,新增一个用户是比较麻烦的。