目录

自己部署Bitwarden服务

Bitwarden 是一个开源的密码管理器解决方案,拥有多个平台的客户端。它采用的方式是云端数据库、客户端同步和离线使用的模式,类似现在的 1password。其优势在于:

  • 官方许可私有化部署;
  • 代码开源,安全性高;
  • 拥有完善的多平台客户端支持,包括 Linux、Android、主流浏览器都覆盖;
  • 支持保存 TOTP 密钥;

本文记录如何在 Linux 上部署 bitwarden_rs

安装 docker

参考 docker 官方文档

安装 bitwarden_rs

bitwarden_rs 并不是 bitwarden 的官方项目,而是从官方项目中衍生的第三方实现。bitwarden 的 server 项目使用 .NET 语言和 MSSQL 数据库,生成的 docker 镜像体积较大,第三方作者于是用 rust 重写,并使用 sqlite 数据库,并实现了官方的一些付费功能,该 docker 镜像体积较小,方便部署。

拉取 docker 镜像:

1
docker pull bitwardenrs/server:latest

新建数据目录:

1
mkdir bitwarden-data

新建环境变量配置文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
DOMAIN=your_domain
SIGNUPS_ALLOWED=false
WEB_VAULT_ENABLED=true
INVITATIONS_ALLOWED=false
WEBSOCKET_ENABLED=true
ROCKET_WORKERS=20
SHOW_PASSWORD_HINT=false
LOG_FILE=/data/bitwarden.log
IP_HEADER=X-Real-IP
TZ=Asia/Shanghai

注意第一次运行时,先把 SIGNUPS_ALLOWED 设置为 true,并修改 DOMAIN,以方便创建用户和导入密码库。

启动 docker 容器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
export BITWARDEN_DATA=/root/bitwarden-data/

docker run -d \
-v $BITWARDEN_DATA:/data/ \
-p 127.0.0.1:10001:80 \
-p 127.0.0.1:10002:3012 \
--env-file=$BITWARDEN_DATA/bitwarden.env \
--name=bitwarden \
--restart=always \
bitwardenrs/server

配置 nginx

作为一个密码管理器服务,为了安全必须开启 HTTPS。关于 HTTPS 的配置请参考项目 mrchi/secure-nginx

这里只展示为 Bitwarden 设置的请求转发规则

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
	# reverse proxy
	location / {
		proxy_pass http://127.0.0.1:10001;
		include nginxconfig.io/proxy.conf;
	}

	# notification
	location /notifications/hub {
		proxy_pass http://127.0.0.1:10002;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# notification
	location /notifications/hub/negotiate {
		proxy_pass http://127.0.0.1:10001;
		include nginxconfig.io/proxy.conf;
	}

配置 fail2ban

fail2ban 是一个通过监视应用日志并进行正则表达式匹配,将多次登录失败的 IP 通过设置 iptables 进行封禁的工具。给 Bitwarden 设置 fail2ban 可以一定程度上防止主密码遭受暴力破解。

安装

1
apt install fail2ban

在设置前,检查 docker 容器的 TZ 环境变量和 IP_HEADER 环境变量设置正确。前者影响日志的时间,后者影响日志中记录的真实访问 IP。

首先创建一个过滤器,在 /etc/fail2ban/filter.d 目录新增文件 bitwarden.local,写入以下内容

1
2
3
4
5
6
[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =

然后创建一个 jail,在 /etc/fail2ban/jail.d 目录新增文件 bitwarden.local,写入以下内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[bitwarden]
enabled = true
port = 80,443
name = bitwarden
filter = bitwarden
banaction = iptables-multiport
logpath = /root/bitwarden-data/bitwarden.log
maxretry = 3
bantime = 14400
findtime = 14400

假如你对外监听的端口不是 80 和 443,那么要修改成实际使用的端口,否则 fail2ban 会设置成错误的 iptables,无法禁止 IP 对实际端口的访问。

修改完成后,重启 fail2ban

1
systemctl restart fail2ban

此时即可故意输入错误的密码,查看 jail 状态中的记录数是否增加

1
fail2ban-client status bitwarden

输错达到 3 次后,当前 IP 应该就不能再访问服务器的 80 和 443 端口。解封 IP

1
fail2ban-client set bitwarden unbanip XX.XX.XX.XX

备份

Bitwarden 的模式决定了服务器端的数据永远是最新的,虽然 iOS 和 Android 的客户端支持导出数据,但客户端不会在后台自动同步密码库。若长时间未打开,密码库将不会是最新版本。

此时对服务器数据进行备份就显得尤为重要。服务器端数据是加密的,没有主密码很难解开(话不能说的太绝对)。我们可以定时将将容器挂载目录打包,上传到网络存储。

这里以通过 webdav 上传到坚果云为例。

/etc/cron.daily 目录下新建文件 bitwarden-backup,写入以下内容

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/sh

set -e

filename="bitwarden-`date +%F`.tar.gz"
cd /root
tar czf "${filename}" bitwarden-data/
curl -u "USERNAME:APP_PASSWD" -T "${filename}" "https://dav.jianguoyun.com/dav/bitwarden/"

rm "${filename}"

增加可执行权限

1
chmod a+x bitwarden-backup

参考链接