可以选择的方式

运行Vaultwarden有两种方式:直接运行二进制和docker运行,显然后者更方便,前者也需要先pull docker镜像再从里面提取。
配置有好几种方式:docker命令、docker compose、环境文件(.env)、管理面板(config.json),其中docker命令一长串改起来很麻烦,env文件包含了所有配置项,而docker compose可以只写与默认配置不同的项,所以我使用docker compose部署。

编写docker-compose.yml

这是最重要的部分,编写好后就可以直接部署了
如果你不需要邮件功能,也没有很多人共用一个Vaultwarden导致sqlite3的性能不够用,下面这个精简版足矣

services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
ports:
- 1701:80
volumes:
- ./vw-data:/data
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
DOMAIN: "你的域名"
WEBSOCKET_ENABLED: "true"
: "true"
WEB_VAULT_ENABLED: "false"
INVITATIONS_ALLOWED: "false"
TIME_ZONE: "Asia/Shanghai"
LOG_FILE: "/data/vaultwarden.log"

在注册完要用的账号后建议把SIGNUPS_ALLOWED和INVITATIONS_ALLOWED改为false更加安全
接下来说说可以添加的配置

邮件功能

Vaultwarden的邮箱功能可以用于双重验证,异常登录通知,账号激活。你需要有一个支持SMTP的邮箱用于发送这些邮件。Outlook可以参考官方指南,Gmail必须先启用双重验证然后添加一个应用密码才能使用SMTP。我用的阿里云新加坡轻量服务器,Outlook连不上,Google账号又只有一个,所以选择用自己的域名借助第三方服务搭建一个邮箱,这也是我比较推荐的方式。Vaultwarden官方wiki推荐的SMTP中sendgrid我审核没过,Brevo倒是搭建成功了但是发出的邮件一直被加入queue ,在仪表盘上queue又显示0,发ticket客服也不知道为什么。serv00自带一个开箱即用的邮箱但是就是因为免费又开箱即用所以被滥用了,已经被spamhaus标记了,发给Outlook直接拒收。。。绑定自己的域名倒是可以发出去,但是mailtester的分数也不太好看,而且不知道什么时候跑路(感觉要被薅秃了)。最后我选择了飞书国际版larksuite,教程可以参考这篇,搭好后需要在docker-compose.yml中添加以下内容

SMTP_HOST: "SMTP服务器地址,larksuite的是这个:smtp.larksuite.com"
SMTP_PORT: "465"
SMTP_SECURITY: "force_tls"
SMTP_FROM: "你SMTP的邮箱地址"
SMTP_USERNAME: "同上"
SMTP_PASSWORD: "账户密码"
SMTP_AUTH_MECHANISM: "Login"

对了,你可以在Mail-tester查看你的邮箱得分,分数越高越不可能被标记为垃圾邮件

启用Android/iOS的消息推送

vaultwarden兼容bitwarden的push,具体来说就是谷歌FCM和苹果APN。配置方法也不复杂,参考官方wiki的教程

使用MySQL作为后端

MySQL比sqlite3(vaultwarden自带且默认使用)性能更好,这里我们也运行在docker里面,在原来的yml下面加入以下内容:

mysql:
container_name: mysql
image: mysql:5.7
restart: always
environment:
- MYSQL_ROOT_PASSWORD=自己设置一个
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- ./mysql/data:/var/lib/mysql
- .mysql/logs:/var/log/mysql
- ./mysql/conf:/etc/mysql/conf.d

当然你也可以使用mysql8.2但是我服务器确实跑不动。
然后在vaultwarden的environment 那一段加入这一行:

DATABASE_URL: "mysql://root:你刚刚设置的MySQL数据库密码@mysql/vaultwarden"

其中DATABASE_URL的格式是

DATABASE_URL=mysql://[[user]:[password]@]host[:port][/database]

这里我用容器名代替对应容器ip地址,同一个docker-compose.yml可以不用加network。

部署

这里搬运docker官方的安装命令(使用apt)

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

接着进去docker-compose所在的目录,输入

docker compose up -d

部署你的项目。
如果有yml有更改只需再执行一次相同的命令,是不是很优雅?
注意⚠️这里有个坑,docker和compose之间是空格不是-,我之前部署时网上教程清一色的用docker-compose,但是实测部署后容器名前面会多一串乱码,而且更改yml后不能用上面的方法更新容器,只能删了重新创建。后来才知道好像docker-compose已经被弃用了,这个功能变为内置于docker命令中。
查看某个容器的日志可以用

docker logs 容器名

如果docker报错是YAML语法问题,可以把yml的内容复制到YAML Lint查错,比直接看报错要好找一点。
如果容器镜像有更新,只需

docker compose pull
docker compose up -d --remove-orphans

如果要删除yml中所有容器,只需

docker compose down

现在你就应该可以通过http://服务器IP:1701 访问vaultwarden了。

MySQL中的工作

如果你使用mysql,事还没完,还需要执行下面的命令允许ROOT用户远程访问(默认只允许localhost访问)并给vaultwarden创建一个数据库

docker exec -it mysql /bin/bash
mysql -u root -p你的密码
use mysql;
GRANT ALL ON *.* TO 'root'@'%';
flush privileges;
CREATE DATABASE vaultwarden;
flush privileges;

注意①-p和密码之间没有空格,有空格就会在执行命令后让你输入密码
②在mysql中执行的每行命令结尾都有分号

使用反向代理

这样更加安全。
网上教程无非nginx、caddy、cloudflare tunnel 三种,其中nginx性能比caddy好,caddy可以自动生成https证书,cloudflare tunnel配置最简单,这里使用cloudflare tunnel
注意必须要有自己的域名
首先注册一个cloudflare账号并添加一个你的域名,然后打开https://one.dash.cloudflared.com 选择Free计划,选择network中的tunnel,添加一个新的tunnel,然后随便选择一个平台和架构,复制下方出现的部署命令,命令中ey开头的就是这个tunnel的token。然后在public hostname中添加一个,Service type选择http地址填vaultwarden,点击保存
然后在yml结尾添加

cloudflared:
container_name: cloudflared
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel run
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
- TUNNEL_TOKEN=你的token

用这个方法的话可以把yml中vaultwarden的port那一段删了
如果你在非docker中部署cloudflared,需要把vaultwarden 的ports改为
127.0.0.1:1701:80
然后public hostname的地址填127.0.0.1:1701
这里有个坑,如果你此前已经在非docker部署了cloudflared,在docker再部署cloudflared就会无限重启

备份

建议添加系统定时任务,自动备份

crontab -e

格式是

分 时 天 月 年 要运行的命令

比如每年每月每天凌晨4点自动备份MySQL数据库

00 04 * * * docker exec mysql bash -c "exec mysqldump -u root -p你的数据库密码 --all-databases > /root/backup/mysql-$(date '+\%Y\%m\%d-\%H\%M').sql

如果用自带的sqlite3,命令可以用

sqlite3 data/db.sqlite3 ".backup '/path/to/backups/db-$(date '+%Y%m%d-%H%M').sqlite3'"

备份附件、send、rsa_key*这些文件直接用7z压缩就行了
如果要备份到云盘可以用rclone挂载云盘到本地