一、简介

Bitwarden 是一款自由且开源的密码管理服务,用户可在加密的保管库中存储敏感信息(例如网站登录凭据)。Bitwarden 平台提供有多种客户端应用程序,包括网页用户界面、桌面应用,浏览器扩展、移动应用以及命令行界面。Bitwarden 提供云端托管服务,并支持自行部署解决方案。

目前国内也有一些密码管理器,但是能够做到全平台使用的还没有,Apple 生态自带的密码管理器也挺好用,且已联通 Windows 平台,Microsoft Store 下载 iCloud 即可使用。参考文章:密码安全性概览

Edge 和 Chrom 自带的密码管理器,虽然不是明文保存,也可以贯通全平台,但终归不是专业的密码管理,还是会有泄露风险,第三方软件可以很轻松的获取。参考文章:Microsoft Edge 密码管理器安全性

专业的密码管理软件例如 LastPass、1Password 这些,订阅费用不便宜,成本比较高昂,相比同类 Bitwarden 就比较划算,免费版本就已经很好用,但免费版本不可以使用 2FA 等高级功能,这可以通过自行搭建解决。

官方的版本搭建对服务器要求很高,搭建不容易,GitHub 上有人用 Rust 实现了 Bitwarden 服务器,项目叫 vaultwarden,并且提供了 Docker 镜像,这个实现更进一步降低了对机器配置的要求,并且 Docker 镜像体积很小,部署非常方便。这个项目目前在 GitHub 也有 27.8k 的 star,非常受欢迎。

二、更新系统

1、和更新源同步

1
sudo apt update

2、显示出哪些软件可以更新

1
sudo apt list --upgradable

3、进行更新

1
sudo apt upgrade -y

4、也可以直接用复合命令更新

1
sudo apt update && sudo apt upgrade -y

三、安装 Docker

按照 官方文档 安装 docker

3.1、卸载旧版本

运行以下命令以卸载所有冲突的软件包

1
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

3.2、使用 apt 存储库安装

在新主机上首次安装 Docker 引擎之前,您需要 需要设置 Docker 存储库。之后,您可以安装和更新存储库中的 Docker

1、更新软件包索引并安装软件包以允许使用 基于 HTTPS 的存储库

1
sudo apt-get update
1
sudo apt-get install ca-certificates curl gnupg

2、添加 Docker 的官方 GPG 密钥

1
sudo install -m 0755 -d /etc/apt/keyrings
1
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
1
sudo chmod a+r /etc/apt/keyrings/docker.gpg

3、使用以下命令设置存储库

1
2
3
4
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

4、更新包索引

1
sudo apt-get update

3.3、安装 Docker 引擎

安装 Docker Engine、containerd 和 Docker Compose,要安装最新版本,请运行:

1
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

四、安装 nginx

4.1、安装 nginx

1、安装必备组件

1
sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring

2、导入官方 nginx 签名密钥,以便 apt 可以验证软件包真实性。

获取密钥

1
2
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

3、验证下载的文件是否包含正确的密钥

1
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

4、输出应包含完整指纹,如下所示:573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62

1
2
3
pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid nginx signing key <signing-key@nginx.com>

如果指纹不同,请删除该文件。

5、将 nginx 的稳定源加入系统

1
2
3
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

6、设置 nginx 官方源的优先级高于 Debian 系统的官方仓库

1
2
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx

7、更新源,并安装 nginx

1
sudo apt update
1
sudo apt install nginx

8、查看状态,启动 nginx

安装好的 nginx 默认是 dead 状态,需要启动,并设置开机启动。

  • 查看nginx服务的状态
1
systemctl status nginx
  • 启动nginx服务
1
sudo systemctl start nginx
  • 设置nginx开机启动
1
sudo systemctl enable nginx
  • 确认nginx服务的启动状态
1
systemctl status nginx
  • 相关命令
1
2
3
4
5
6
7
8
sudo nginx -V                       <-- 查看nginx的编译参数
cat /etc/nginx/nginx.conf <-- 查看nginx的配置文件
cat /etc/nginx/conf.d/default.conf <-- 还是nginx的配置文件
systemctl status nginx <-- 查看nginx服务的状态
sudo systemctl start nginx <-- 启动nginx服务
sudo systemctl enable nginx <-- 设置nginx开机启动
systemctl status nginx <-- 确认nginx服务的启动状态
ip a <-- 查看本机IP地址

4.2、 新建证书文件夹 cert

1
cd /etc/nginx
1
mkdir cert
1
cd
  • 将证书上传到 cert 文件夹

使用 Xftp 将下载好的证书上传到证书文件夹。

4.3、默认 nginx 配置文件

1、位于 /etc/nginx/conf.d/default.conf 的配置可以修改如下,开启 gzip,也可以按需开启缓存。

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
server {
listen 80;
server_name localhost;

#access_log /var/log/nginx/host.access.log main;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}

# 开启gzip
gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k; # 开始压缩的最小长度(再小就不要压缩了,意义不在)

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 1;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\."; #正则匹配UA,配置禁用gzip条件。此处表示ie6及以下不启用gzip(因为ie低版本不支持)

# 设置压缩所需要的缓冲区大小
gzip_buffers 32 4k; # 缓冲(压缩在内存中缓冲几块? 每块多大?)

# 设置gzip压缩针对的HTTP协议版本,没做负载的可以不用
# gzip_http_version 1.0;
# gzip_http_version 1.1; # 开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议)

# 开启缓存
# 缓存图片
# location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
# access_log off;
# expires 2d;
# }

#缓存js、css、视频文件
# location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
# access_log off;
# expires 24h;
# }

# 缓存html类型文件
# location ~* ^.+\.(html|htm)$ {
# expires 1h;
# }

# 缓存字体文件,配合gzip更好
# location ~* ^.+\.(eot|ttf|otf|woff|svg)$ {
# access_log off;
# expires 2d;
# }

# 格式
# expires 30s;
# expires 30m;
# expires 2h;
# expires 30d;
# expires max;

}

2、验证并重载 nginx 配置

1
nginx -t
1
nginx -s reload

五、部署 vaultwarden

5.1、新建数据文件夹

1
mkdir ~/.docker && cd ~/.docker
1
mkdir vaultwarden && cd vaultwarden
1
mkdir data && cd data

5.2、正式部署

1
docker pull vaultwarden/server:latest
1
2
3
4
5
docker run -d --name vaultwarden \
-v ~/.docker/vaultwarden/data/:/data/ \
--restart unless-stopped \
-p 9696:80 \
vaultwarden/server:latest

5.3、nginx 配置

  • 将准备好的域名解析到服务器的 IP

  • 将证书上传到 cert 文件夹

  • 使用 Xftp 将下载好的证书上传到证书文件夹。

  • nginx 配置上传到 /etc/nginx/conf.d 文件夹

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
# The `upstream` directives ensure that you have a http/1.1 connection
# This enables the keepalive option and better performance
#
# Define the server IP and ports here.
upstream vaultwarden-default {
zone vaultwarden-default 64k;
server 127.0.0.1:9696;
keepalive 2;
}

# Needed to support websocket connections
# See: https://nginx.org/en/docs/http/websocket.html
# Instead of "close" as stated in the above link we send an empty value.
# Else all keepalive connections will not work.
map $http_upgrade $connection_upgrade {
default upgrade;
'' "";
}

# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name test.ysbzcn.com;

if ($host = test.ysbzcn.com) {
return 301 https://$host$request_uri;
}
return 404;
}

server {
# For older versions of nginx appened http2 to the listen line after ssl and remove `http2 on`
listen 443 ssl;
listen [::]:443 ssl;
#http2 on;
server_name test.ysbzcn.com;

#证书位置
ssl_certificate /etc/nginx/cert/test.ysbzcn.com.pem;
ssl_certificate_key /etc/nginx/cert/test.ysbzcn.com.key;

#证书配置
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #安全链接可选的加密协议
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; #加密算法
ssl_prefer_server_ciphers on; #表示优先使用服务端加密套件。默认开启
ssl_session_timeout 10m; #缓存有效期

ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_buffer_size 1400;
add_header Strict-Transport-Security max-age=15768000;
ssl_stapling on;
ssl_stapling_verify on;

client_max_body_size 525M;

location / {
proxy_http_version 1.1;
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 X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_pass http://vaultwarden-default;
}

# Optionally add extra authentication besides the ADMIN_TOKEN
# Remove the comments below `#` and create the htpasswd_file to have it active
#
#location /admin {
# # See: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/
# auth_basic "Private";
# auth_basic_user_file /path/to/htpasswd_file;
#
# proxy_http_version 1.1;
# 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 X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
#
# proxy_pass http://vaultwarden-default;
#}
}
  • 验证并重载 nginx 配置
1
nginx -t
1
nginx -s reload

访问域名 https://test.ysbzcn.com/ 即可进入登陆页面。

5.4、禁止新用户注册

现在的状态是所有人都可以注册这个网站,这个东西只是自己使用,所以我们需要关闭掉注册,使用下面的命令。

不必担心,因为指定了 volume 映射,删除容器后不会删除数据。SIGNUPS_ALLOWED=false 代表禁止注册!

1
docker stop vaultwarden
1
docker rm -f vaultwarden
1
2
3
4
5
6
docker run -d --name vaultwarden \
-e SIGNUPS_ALLOWED=false \
-v ~/.docker/vaultwarden/data/:/data/ \
--restart unless-stopped \
-p 9696:80 \
vaultwarden/server:latest