有关自建 bitwarden 的实践

前言

很离谱,已经搭建过了,结果忘记自己建过了,又由于事情忙一直没用上,现在用户密码忘了,管理员密码也忘了…

这次好好记录下在腾讯轻量云自建 bitwarden 服务的记录,实际服务选用修改过的 dani-garcia/vaultwarden

非必要步骤

安装 docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 移除旧版 docker,非必须,若服务器从未进行过 docker 操作,请直接跳过该步
$ sudo apt-get remove docker docker-engine docker.io containerd runc

# 自动安装流程, 无针对国内的加速设置,运行官方提供的脚本
$ sudo apt-get update
$ sudo apt-get install curl
$ export DOWNLOAD_URL="https://mirrors.tuna.tsinghua.edu.cn/docker-ce"
$ curl -fsSL https://get.docker.com/ | sh

# 手动安装流程, 使用清华源进行 ubuntu 和 docker 的加速
# 检查系统版本并修改软件源以提升下载和更新速度
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
$ hostnamectl
....
Operating System: Ubuntu 20.04 LTS

# 前往清华大学开源软件镜像站 Ubuntu 选择对应版本更新软件源,以 20.04 LTS 为例
# https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/
$ sudo sed -i "s@http://.*archive.ubuntu.com@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list
$ sudo sed -i "s@http://.*security.ubuntu.com@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list

# 更新 docker 相关源
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 重新更新
$ sudo apt-get update
$ sudo apt-get install docker-ce

# 启用 docker
$ sudo systemctl enable docker
$ sudo systemctl start docker

# 测试是否安装成功,输出以下内容可视为安装成功
$ docker run --rem hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:faa03e786c97f07ef34423fccceeec2398ec8a5759259f94d99078f264e9d7af
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

移除旧 vaultwarden

当有旧的 vaultwarden 服务时,首先将其移除,接着进行后续步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ sudo su root
# 查看当前活动中的所有 docker 容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxx xxx xxx xxx xxx xxx xxx
xxxxx xxx xxx xxx xxx xxx vaultwarden

# 查看 vaultwarden 的启动命令,简单检查,主要了解之前设定的端口
$ docker ps -a --no-trunc | grep vaultwarden

# 暂停并删除旧 vaultwarden 容器
$ docker stop <vaultwarden Container_ID>
$ docker rm <vaultwarden Container_ID>

# 检查 vaultwarden 旧容器确认删除,已无对应 container id 存在
$ docker ps -aq

部署 vaultwarden 镜像

1
2
3
4
5
6
7
8
# 拉取最新版本
$ docker pull vaultwarden/server:latest

# 配置并启动镜像, 8022 可改为自定义端口
$ docker run -d --restart=always --name vaultwarden -v /vw-data/:/data/ -p 8022:80 -p 3012:3012 vaultwarden/server:latest

# 检查是否启动
$ docker ps

理论上此时我们就可以直接通过 ip 地址 + 端口的方式直接访问 bitwarden,得到如下界面。

bitwarden 主界面

配置 nginx

直接 ip + 端口的访问方式固然直接有用,但大多数情况我们还是通过域名来进行访问的,这就要求我们需要进行相关访问设置,比如设置 nginx 来进行反代。

域名申请与购买见 腾讯云:域名注册

安装 nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ sudo apt update
$ sudo apt-get install nginx

# 检查 nginx 服务状态, 看到 Active: active(running) 说明正常运行
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2020-04-20 16:08:19 UTC; 3 days ago
Docs: man:nginx(8)
Main PID: 2369 (nginx)
Tasks: 2 (limit: 1153)
Memory: 3.5M
CGroup: /system.slice/nginx.service
├─2369 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
└─2380 nginx: worker process

# 如果遇到防火墙问题, 一般来说轻量云不设置的话不会有这个问题
$ sudo ufw app list
$ sudo ufw allow 'Nginx HTTP'
$ sudo ufw status
Status: active

To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)

寻找 nginx

如果之前已经安装过 nginx,但是已经忘了去哪儿配置相关文件不是我,可以这样找对应位置:

1
2
$ whereis nginx.conf
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz

配置 SSL 证书生成

申请:根据教程 域名型(DV)免费 SSL 证书申请流程 申请

安装:

  • 根据教程 Nginx 服务器证书安装 安装
  • 或下载证书至本地,通过 winscp 登录至服务器,然后将 .key 和 .crt 文件上传至自定义目录,比如 /etc/nginx/ssl

注意:如果 winscp 在上传修改文件或文件夹时提示权限不足,请重新登录,登陆时文件协议保持 SFTP,在高级中进行如下设置再尝试登录即可解决

winscp 设置 SFTP

winscp 设置 Shell

编写相关配置

作者的配置是为每个网站使用单独的 conf 文件,对 bitwarden 使用 https, 不被搜索引擎收录,开启日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 创建相关文件,此处应为你自己的 nginx 配置路径
$ cd /etc/nginx/conf.d
$ touch bitwarden.conf

# 参考 https://github.com/dani-garcia/vaultwarden/wiki/Proxy-examples
# bitwarden.conf
upstream bitwarden-default {
zone bitwarden-default 64k;
# 此处应为你设置的端口
server 127.0.0.1:8022;
keepalive 2;
}

# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
# 此处为你的域名,如 abc.def.xyz;
server_name your_server_name;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# 此处为你的域名,如 abc.def.xyz;
server_name your_server_name;

# SSL
ssl_certificate /etc/nginx/ssl/bitwarden.hellagur.com_bundle.crt;
ssl_certificate_key /etc/nginx/ssl/bitwarden.hellagur.com.key;

# restrict methods
if ($request_method !~ ^(GET|POST|PUT|DELETE)$) {
return '403';
}

# prevent search engine
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|^$") {
return 404;
}

# Allow large attachments
client_max_body_size 128M;

# only allow cloudflare ip
# include /etc/nginx/cfip.conf;
# deny all;

# logging
access_log /var/log/nginx/bw.access.log;
error_log /var/log/nginx/bw.error.log warn;

location / {
proxy_http_version 1.1;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;

# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

# 此处应为你设置的端口
proxy_pass http://127.0.0.1:8022;

# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}

location /notifications/hub/negotiate {
proxy_http_version 1.1;
proxy_set_header "Connection" "";

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 此处应为你设置的端口
proxy_pass http://127.0.0.1:8022;
}

location /notifications/hub {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Forwarded $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 此处应为你设置的端口
proxy_pass http://127.0.0.1:3012;
}
}

更新并校验配置文件

1
2
3
4
5
6
# 校验所有 nginx .conf 配置文件是否有效
$ nginx -t
$ nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# 刷新 nginx 配置
$ nginx -s reload

现在应该可以直接通过域名访问了,如果此时没有响应,稍微等待一段时间后应该就可以了。

添加限制

为更近一步保证安全,将添加管理员密码和禁止注册,在执行以下命令前请确保已创建好账户!由于制定了 volume 映射,所以不用担心数据被删除。

管理员可在禁止注册的情况下邀请新用户,ADMIN_TOKEN 的生成可见 Vaultwarden Wiki: 启用管理页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ sudo su root
# 查看当前活动中的所有 docker 容器
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
xxxxx xxx xxx xxx xxx xxx xxx
xxxxx xxx xxx xxx xxx xxx vaultwarden

# 查看 vaultwarden 的启动命令,简单检查,主要了解之前设定的端口
$ docker ps -a --no-trunc | grep vaultwarden

# 暂停并删除旧 vaultwarden 容器
$ docker stop <vaultwarden Container_ID>
$ docker rm <vaultwarden Container_ID>

# 检查 vaultwarden 旧镜像确认删除,已无对应 container id 存在
$ docker ps -aq

# 重新运行新容器, ADMIN_TOKEN 自定义
$ docker run -d --name vaultwarden --restart=always \
-e ADMIN_TOKEN=your_admin_token \
-e SIGNUPS_ALLOWED=false \
-v /vw-data/:/data/ \
-p 8022:80 \
-p 3012:3012 \
vaultwarden/server:latest

Admin 界面

有备无患

参考 部署自己的密码库 Vaultwarden 自动备份部分即可,通过 rclone 定期备份密码库至 one drive 等网盘。


有关自建 bitwarden 的实践
http://example.com/2022/12/03/有关自建-bitwarden-的实践/
作者
Steins Gu
发布于
2022年12月3日
许可协议