如何自部署bitwarden实现免费使用TOTP功能

最近需要使用TOTP,一直在用的bitwarden要收费(10美元/年)。感觉没什么必要为这个功能花这么多钱,又不想再用一个Google Authenticator。

于是查了一下发现可以自部署bitwarden从而免费使用totp,用docker很快就能部署好

效果

转载教程

本文由 简悦 SimpRead 转码, 原文地址 blog.hentioe.dev

前言

Bitwarden 是一个流行的开源密码管理器,它能以浏览器扩展、网页、Windows/Linux/Android/iOS 客户端等形式提供密码管理服务。长期以来我都是它的用户,并订阅了其付费服务。但最近我改变了注意,我打算取消订阅并将它部署到自己的服务器中。

本文将介绍如何自行部署 Bitwarden 的官方服务端、第三方服务端,以及免费启用 TOTP 的方法。这是一篇新手向教程。过程十分简单!

原因

自行部署 Bitwarden 服务端,我个人有以下几个原因:

  • 自己掌握自己的密码,而不是交给他人。
  • 自行实现更为复杂的多层备份,降低密码丢失风险。
  • 免费使用 TOTP 功能。

我个人还是建议有 TOTP 需求的普通用户使用 Bitwarden 官方的付费服务,因为成本更低同时也是对开源软件的支持。

前提

你需要有一台服务器,SSL/TLS 证书,域名,以及一些基本的 Docker 使用知识。对于想取消付费服务的用户,满足这些前提的费用其实不会比 Bitwarden 官方的订阅便宜。它实际上适合有现成服务器资源的人。

部署服务端

本章节将介绍如何部署官方的服务端、第三方服务端(Vaultwarden),以及相应的 Docker Compose 配置模板。我先提前介绍下两种客户端的差异:

  • 官方服务端:
    • 来自官方的更新,兼容性有保障。
    • 使用 TOTP、组织等功能仍需付费。
    • 包含 SSO、LDAP 等大型组织需要的功能。
    • 内存占用巨大。
  • 第三方(Vaultwarden):
    • 内存占用极小。
    • 免费使用 TOTP、组织等功能。
    • 不包含 SSO、LDAP 等大型组织需要的功能。
    • 可能会出现更新不及时导致兼容性问题。

官方服务端

Bitwarden 的服务端部署官方提供了两个方案,旧方案尤其麻烦本文不做介绍。新方案还处于 beta 状态,但已经可用。我们部署新方案,它仅仅只需要一个镜像即可部署,非常简单。

创建 bitwarden/docker-compose.yml 文件:

services:
  self-host:
    image: bitwarden/self-host:beta
    restart: always
    env_file:
      - .env
    ports:
      - 5500:8080
    volumes:
      - ./_data:/etc/bitwarden
    environment:
      BW_DB_PROVIDER: sqlite
      BW_DB_FILE: /etc/bitwarden/db.sqlite3

创建 .env 文件:

BW_INSTALLATION_ID=
BW_INSTALLATION_KEY=
BW_DOMAIN=
globalSettings__disableUserRegistration=false
adminSettings__admins=

在部署前需要填充 .env 中变量的值,具体如下:

  • BW_INSTALLATION_ID: 你的安装 ID,需要在 Bitwarden 官网申请。
  • BW_INSTALLATION_KEY: 您的安装密钥,需要在 Bitwarden 官网申请。
  • BW_DOMAIN: 你的域名,例如 example.com
  • globalSettings__disableUserRegistration: 是否禁用用户注册,在初次部署时请设置为 false
  • adminSettings__admins: 管理员的邮箱。

你需要进入此页面手动提交邮箱就可免费获得安装 ID 和 KEY,复制它们填入到 .env 对应变量的后面。

完成所有变量值的填充后,执行 docker compose up -d 启动服务。然后执行 docker compose logs -f 查看日志:

self-host-1  | Adding group `bitwarden' (GID 1000) ...
self-host-1  | Done.
self-host-1  | Adding user `bitwarden' ...
self-host-1  | Adding new user `bitwarden' (1000) with group `bitwarden (1000)' ...
self-host-1  | Not creating home directory `/home/bitwarden'.
self-host-1  | Adding new user `bitwarden' to supplemental / extra groups `users' ...
self-host-1  | Adding user `bitwarden' to group `users' ...
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/admin.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/api.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/events.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/icons.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/identity.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/nginx.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/notifications.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/scim.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,137 INFO Included extra file "/etc/supervisor.d/sso.ini" during parsing
self-host-1  | 2024-09-12 05:30:17,148 INFO RPC interface 'supervisor' initialized
self-host-1  | 2024-09-12 05:30:17,148 CRIT Server 'unix_http_server' running without any HTTP authentication checking
self-host-1  | 2024-09-12 05:30:17,148 INFO supervisord started with pid 1
self-host-1  | 2024-09-12 05:30:18,155 INFO spawned: 'identity' with pid 65
self-host-1  | 2024-09-12 05:30:18,159 INFO spawned: 'admin' with pid 66
self-host-1  | 2024-09-12 05:30:18,163 INFO spawned: 'api' with pid 67
self-host-1  | 2024-09-12 05:30:18,167 INFO spawned: 'icons' with pid 68
self-host-1  | 2024-09-12 05:30:18,171 INFO spawned: 'nginx' with pid 69
self-host-1  | 2024-09-12 05:30:18,175 INFO spawned: 'notifications' with pid 70

稍等片刻,如果日志如上那么表示部署成功。若出现一些以 WARN exited 开头的日志,就表示部分服务启动失败了。具体你可能要去 issues 中寻找答案。

以上配置模板使用 SQLite 数据库,因为它非常小巧小规模使用完全足够。

按照以上配置部署后,数据将保存在 _data 目录。若要迁移,先停止服务然后完整迁移数据目录即可。在访问前,需反向代理 5500 端口,并配置 SSL 证书。最后参考注册使用章节。

官方服务端我个人体验下来内存占用巨大(ARM64),不适合资源有限的服务器。为了写此文我部署了一个独立的实例,没有任何访问它的占用就达到 1GB 以上。强烈建议尝试 Vaultwarden,下文将介绍它。

第三方(Vaultwarden)

Vaultwarden 是 Bitwarden 的第三方服务端实现,它高度兼容官方客户端并具有几乎完整的功能可用性。和官方服务端相比,它架构十分简单,由 Rust 实现占用极小。我个人使用 Vaultwarden 而不使用官方服务端。

创建 vaultwarden/docker-compose.yml 文件:

services:
  server:
    image: vaultwarden/server
    restart: always
    ports:
      - 5600:80
    environment:
      - DOMAIN=${DOMAIN}
      - SIGNUPS_ALLOWED=${SIGNUPS_ALLOWED}
      - ORG_CREATION_USERS=${ORG_CREATION_USERS}
      - ADMIN_TOKEN=${ADMIN_TOKEN}
    volumes:
      - ./_data:/data/

创建 .env 文件:

DOMAIN=
SIGNUPS_ALLOWED=
ORG_CREATION_USERS=
ADMIN_TOKEN=

在部署前需要填充 .env 中的变量的值,具体如下:

  • DOMAIN: 你的域名(实际上是包含协议的地址),如 https://example.com
  • SIGNUPS_ALLOWED: 是否禁用用户注册,在初次部署时请设置为 false
  • ORG_CREATION_USERS: 允许创建组织的用户。
  • ADMIN_TOKEN: 管理员 Token,建议是 Argon2 哈希处理的 PHC 字符串。

先留空 ADMIN_TOKEN 变量,因为我们后续将从容器中执行命令生成它。完成其它变量值的填充后,执行 docker compose up -d 启动服务。然后执行 docker compose logs -f 查看日志:

server-1  | /--------------------------------------------------------------------\
server-1  | |                        Starting Vaultwarden                        |
server-1  | |                           Version 1.32.0                           |
server-1  | |--------------------------------------------------------------------|
server-1  | | This is an *unofficial* Bitwarden implementation, DO NOT use the   |
server-1  | | official channels to report bugs/features, regardless of client.   |
server-1  | | Send usage/configuration questions or feature requests to:         |
server-1  | |   https://github.com/dani-garcia/vaultwarden/discussions or        |
server-1  | |   https://vaultwarden.discourse.group/                             |
server-1  | | Report suspected bugs/issues in the software itself at:            |
server-1  | |   https://github.com/dani-garcia/vaultwarden/issues/new            |
server-1  | \--------------------------------------------------------------------/
server-1  |
server-1  | [2024-09-12 06:02:16.966][start][INFO] Rocket has launched from http://0.0.0.0:80

以上表示部署成功。接着我们向该容器发起命令生成 ADMIN_TOKEN

docker compose exec server /vaultwarden hash

按交互要求输入至少 8 位长度的密码,然后会得到一个有效的 ADMIN_TOKEN 配置。将它复制到 .env 即可,完成后再次执行 docker compose up -d 更新部署。

以上配置模板没有指定外部数据库,它将默认使用 SQLite。它非常小巧小规模使用完全足够。

按照以上配置部署后,数据将保存在 _data 目录。若要迁移,先停止服务然后完整迁移数据目录即可。在访问前,需反向代理 5600 端口,并配置 SSL 证书。最后参考注册使用章节。

Vaultwarden 的占用非常低,个人长期使用也基本只占用几十 MB。

注册使用

确保部署成功后,访问你绑定的域名并进入注册页面,创建自己的用户。完成后再修改 .env 文件,禁用注册:

官方服务端:

globalSettings__disableUserRegistration=true

Vaultwarden:

SIGNUPS_ALLOWED=false

再次执行 docker compose up -d 更新部署。

这对于个人使用是必要的,除非你想让自己部署的服务端作为公共服务被大家使用。

客户端配置

进入 Bitwarden 的登录页,点击「自托管」:

如果你已登录 Bitwarden 帐号,并不需要注销。点击自己的头像,添加其它帐号即可。

进入「自托管」页面后,填入你的域名,点击「登录」:

完成上述设置后保存,现在你已经可以用自己部署的服务端中的帐号登录和使用。如果是官方服务端,你仍需要付费购买 ID/KEY 才能使用 TOTP 功能。Vaultwarden 的话,你可以免费使用 TOTP 功能(在客户端中自动启用)。

导入数据

使用 Bitwarden 客户端或网页版,将自己的密码库导出为 JSON/CVS 格式,登录自托管后端的页面导入即可。当然,Bitwarden 官方的服务我们也不需要完全禁用,它可以作为后备方案以备不时之需(例如自托管服务中断了)。后续继续介绍自动同步密码到官方服务的方法。

同步数据

待更新。

结束语

这就是部署 Bitwarden 服务端的教程了。我个人偏向使用开源软件,所以坚持使用 Bitwarden 而不选择 LastPass/KeepPass/1Password 之类的商业产品。尤其是某些商业产品甚至还出现过数据泄漏的事件。不过对于自托管,也要注意服务器安全。

对于想免费使用 TOTP 的用户但又没条件自托管,我不建议你选择免费的第三方公共服务,因为很难有可信度。我建议你使用独立的 TOTP 管理器(如 Ente Auth),通常是免费的。