杏泉网络:应用篇(Vaultwarden)
前情提要:
如何搭建自己的『暗网』
杏泉网络:DNS篇
杏泉网络:OSPF篇
杏泉网络:OSPF篇
杏泉网络,不能光搭,得用。
一些不适合公开的服务就可以跑在网内,供私人享受,这其中自然也就包括了密码管理器。本文使用Bitwarden及其第三方服务器Vaultwarden,而且,划重点,是不使用 Docker 的情况下安装 Vaultwarden
前言
密码管理器是个好东西,尤其是最近各大密码泄露事件之后,对于密码管理器的需求也就更迫切了。就密码而言,理论上最合适的处理方式是Passkey,但是还有大把网站不支持这个东西,所以密码管理器依然是不可或缺的。
现在问题来了,用哪家?
经常被拿来比较的自然就是(自托管Vaultwarden的)Bitwarden和Keepass。老实说,笔者一直以来是在『用』后者。『用』字打双引号的一个原因是,并没有真正实现我的目标,也就是多端使用。诚然,Keepass的数据库文件可以通过Syncthing等软件做到多端同步,但是毕竟Keepass在设计上只是一个单机密码管理器,如果要多设备同步,那引入了第三方软件,增加了故障点。而且笔者也不是很习惯在手机上跑同步软件,所以最终考虑了一会儿,还是选择自建Vaultwarden,换换口味也不错。
下载
官方推荐的安装方式是Docker,但是笔者不是很喜欢在没有Docker的设备上使用Docker。幸好官方也告诉你怎么不使用Docker来安装,照着来操作就是了:
# 本次部署使用的节点:1.us.xq(198.18.3.1)
# 以下操作假定你的Vaultwarden位于/etc/vaultwarden/
# 如果不在,请自行修改
mkdir /etc/vaultwarden/
cd /etc/vaultwarden/
wget https://raw.githubusercontent.com/jjlin/docker-image-extract/main/docker-image-extract
chmod +x docker-image-extract
./docker-image-extract vaultwarden/server:latest
# data目录,先新建好
mkdir data
cd output
cp vaultwarden ../
cp -r web-vault/ ../
cd ../
配置
Vaultwarden的配置....有点绕,倒不如说用习惯Docker的朋友可能会熟悉些。如果你是初次启动,需要先在可执行文件的同一目录下生成一个.env
文件,文件的示例版本可以在这里查看。笔者根据实际情况,做了一份(相对来说)较小的版本:
# 这个就是刚刚新建的data目录
DATA_FOLDER=/etc/vaultwarden/data
WEB_VAULT_FOLDER=/etc/vaultwarden/web-vault/
WEB_VAULT_ENABLED=true
# 笔者使用的是MariaDB而不是SQLite
# 如果你不想用外部数据库,这一条就可以不设置
# 或者指向你的sqlite数据库文件位置
DATABASE_URL=mysql://<USER>:<PASS>@127.0.0.1:3306/<DB_NAME>
# 没用过Rust的朋友(比如站长)可能不知道,ROCKET是Rust的一个Web库
# 所以如果要修改web页面相关内容,在此修改
# 至于端口,无关紧要,不冲突即可,因为前面还要加反代
ROCKET_ADDRESS=127.0.0.1
ROCKET_PORT=8080
# 关掉新用户注册
SIGNUPS_ALLOWED=false
# 这个下面说
ADMIN_TOKEN=<请看下面>
# 最终访问的域名
# 作为演示,笔者给他分配的是vw.1.us.xq
DOMAIN=https://vw.1.us.xq
这里说一下ADMIN_TOKEN
,可以通过执行./vaultwarden hash
,然后输入两遍你想要的管理员密码来获取。
安装为服务
新建文件/etc/systemd/system/vaultwarden.service
,写入如下内容
[Unit]
Description=VaultWarden Service
After=network.target nss-lookup.target
Wants=network.target
[Service]
User=root
Group=root
Type=simple
LimitAS=infinity
LimitRSS=infinity
LimitCORE=infinity
LimitNOFILE=999999
WorkingDirectory=/etc/vaultwarden/
ExecStart=/etc/vaultwarden/vaultwarden
ExecStop=kill $MAINPID
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
保存。然后执行:
systemctl enable vaultwarden.service --now
systemctl status vaultwarden.service
应该能看到服务在运行
SSL反代
因为Vaultwarden要求SSL访问,官方推荐的做法是在前面放一个反向代理,例如nginx。
编辑nginx的虚拟主机文件(对于Debian,一般来说就在/etc/nginx/sites-enabled/
下面新建),输入:
# 不要忘记把IP等内容替换为你自己的设置内容
server {
listen 198.18.3.1:443 ssl;
listen [fd04:17:1:0000::1]:443 ssl;
ssl_certificate /path/to/your/cert.crt;
ssl_certificate_key /path/to/your/private.key;
server_name vw.1.us.xq;
location / {
proxy_pass http://127.0.0.1:8080;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
listen 198.18.3.1:80;
listen [fd04:17:1:0000::1]:80;
server_name vw.1.us.xq;
return 301 https://$host$request_uri;
}
保存。然后重启nginx。此时通过https://vw.1.us.xq/admin
,应该可以看到管理面板了。
初始化
输入你刚刚设置的管理员密码,进入设置。需要注意的是,此处的设置被保存到data/config.json
,然后会覆盖掉环境变量中的设置。

第一页其实没有什么好修改的,主要就是确认下你的设置是否有误。重点是第二页Users。因为我们为了安全起见,关掉了用户注册功能,所以添加用户的操作会相对麻烦些。
首先,点进去之后,应该能看到下面有Invite User的地方。

在这里填写你的邮箱地址(放心,我们刚刚没有填写SMTP服务器,所以不会有邮件发出——理论上你完全可以填写一个非常用邮箱地址作为『低调的』登录名),然后点击Invite,应该能看到上面新增了一个用户。
接下来新开一个浏览器标签页,转到https://<你的域名>/#/register
。邮箱地址填写你刚刚输入的那个,密码就自己设置一个安全密码,然后直接注册就行——虽然关掉了注册,但是我们方才邀请了这个邮箱地址,所以是可以注册成功的。
注册成功,登录,就可以直接进入用户界面了:

然后你就可以从各个地方导入,开始使用,这里就不再赘述了。
安全防护
虽然运行在内网,但是一些必备的安全防护措施还是需要的。
关闭admin页面
如果就你一个人用的话,admin页面完全可以关闭掉,防止未授权访问。官方文档的教程是完全删除admin_token的键值对,这样当然更安全,但是考虑到每次打开都要重新粘贴一长串比较麻烦,因此可以通过在nginx上配置403来阻断访问。当然这么做肯定不如官方做法安全,毕竟本质上admin页面还是开启状态的,具体选择什么方案取决于你的安全需求。
编辑nginx虚拟主机文件,添加如下块:
location ~ ^/admin(/|$) {
deny all;
}
保存,然后重启nginx,访问/admin
应该能看到403页面。
备份
你应该不希望你的密码随着服务器消失而灰飞烟灭,经常备份是一个好选择。
笔者因为同时在写博客,所以已经有适当的备份措施了,只需添加针对Vaultwarden的选项即可。根据官方教程,需要备份的主要是三个:
- 环境文件(就是一开始设置的
.env
) - data 目录
- 如果采用外部数据库(例如本例),那么还需要备份数据库。
下面这个(写得很粗糙的)脚本应该可以帮助你完成备份的操作,当然你也可以对脚本进行修改,比如把数据库用户名密码给放进变量里,把路径也放进变量里,笔者在这里偷懒就算了。
#!/bin/bash
TODAY=$(date +%d)
DAY_OF_WEEK=$(date +%u)
echo "普通备份"
if [ ! -d "/path/to/vaultwarden" ];then
mkdir /path/to/vaultwarden
fi
cp -r /etc/vaultwarden/data /path/to/vaultwarden/data
cp -r /etc/vaultwarden/.env /path/to/vaultwarden/.env
mysqldump -u<用户名> -p<密码> --all-databases > /path/to/vaultwarden/vaultwarden.sql
# 判断今天的天数是否能被3整除
if [ $((TODAY % 3)) -eq 0 ]; then
echo "今日天数除以三余数为零,执行备份"
mysqldump -u<用户名> -p<密码> --all-databases > /path/to/vaultwarden/vaultwarden.3day.sql
fi
# 判断今天是否是周一
if [ "$DAY_OF_WEEK" -eq 1 ]; then
echo "今天是周一,执行备份"
mysqldump -u<用户名> -p<密码> --all-databases > /path/to/vaultwarden/vaultwarden.1week.sql
fi
# 判断今天是否是1号
if [ "$TODAY" -eq 1 ]; then
echo "今天是1号,执行备份"
mysqldump -u<用户名> -p<密码> --all-databases > /path/to/vaultwarden/vaultwarden.firstDay.sql
fi
将上述文件保存到cron_backup_vaultwarden.sh
,然后编辑crontab,加入:
1 0 * * * /path/to/scripts/cron_backup_vaultwarden.sh
保存。这样就会在每天0点1分执行一次备份到指定目录,同时在特殊日子(看注释可以知道)还会多备份一个指定版本的数据库,防止误操作修改数据库后备份也被修改了。
这里提一嘴文件中出现的/path/to/
:备份当然需要异地备份,所以笔者对这个目录,在两个地理上不同的地方设置了定时拉取(比如地点A是整点,地点B是半点),因此所有数据都会在三个不同的地方有保存,最大限度降低数据损坏的可能性(如果你不放心,大可加大拉取地点和频次)。拉取的方式就看个人喜好,笔者用的是rsync
,就只会拉取有修改的部分,降低传输开销:
# bk.sh
receiving incremental file list
./
vaultwarden.sql
32,944 100% 1.42MB/s 0:00:00 (xfr#1, ir-chk=1014/1020)
vaultwarden/
vaultwarden/.env
422 100% 412.11kB/s 0:00:00 (xfr#2, to-chk=116/9224)
....
写在最后
其实这个方法更合理的用途应该是国内服务器免备案搭建私人API服务,毕竟你客户端访问服务器也只是通过WireGuard(或者Shadowsocks,你喜欢的话)的方式,根本不会暴露HTTP/HTTPS端口出来
使用密码管理器,做好备份,享受美好生活
(完)