宝塔自建 bitwarden 密码管理器
我们生活在被数字包围的世界里。为了证明你是你,你对某个资源拥有所有权。那么就需要密码。最常用的各种网站,还别说银行密码信用卡等等。市面上虽然有 1Password 等优秀商业方案,但是要付费。主流浏览器 Chrome,Firefox 等也提供原生的密码保存方案。 但是, 密码毕竟是个人数据, 自部署(self-hosted)是最佳方案 免费密码管理器 bitwarden 的实际使用体验如何
更新 2025.07.16
更新 2022.09.17
更新 2022.08.02
更新 2022.07.31
更新 2022.07.30
更新 2024.07.28
使用宝塔面板 容易备份 容易管理
新建站点

新建站点,PHP 版本纯静态
,不创建数据库,同时将根目录复制
点击新建好的站点,为新站点申请 SSL (站点无 SSL 将影响功能使用,内网使用可查看此文章 绕过 bitwarden 无 ssl 情况导入密码)

新建 docker
从宝塔自带的软件商店搜索 docker 并安装

bitwarden_rs 是一个用于本地搭建 Bitwarden 服务器的第三方开源 Docker 项目。
bitwarden_rs 使用 Rust 编写,并改用 SQLite 数据库(现在也支持 MySQL 和 PostgreSQL),相对于官方版使用 MSSQL 数据库要求至少 2GB 内存,运行 bitwarden_rs 时只需要 10M 内存,可以说对硬件基本没有要求
wiki
安装后点击设置 - 镜像管理 填入 vaultwarden/server:latest

新建 docker,添加端口和目录映射,目录一定要选刚才创建网站的目录

配置反向代理
打开 配置文件
添加 websocket
配置 (不配置此项可能不会及时自动同步)

1 2 3 4 5
| upstream vaultwarden-ws { zone vaultwarden-ws 64k; server 127.0.0.1:3012; keepalive 2; }
|
打开 站点 - 反向代理
随便添加一个,因为后边还要手动调整

添加完成后点击 配置文件 ,手动编辑

覆盖粘贴如下内容
注意: 如果手动点击 状态(运行中)
按钮,自定义的配置文件内容会被宝塔修改,需要重新点配置文件,再覆盖粘贴一次
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
|
location / { proxy_pass http://127.0.0.1:5814; proxy_http_version 1.1; proxy_cache_bypass $http_upgrade; 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 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; }
location /notifications/hub { proxy_http_version 1.1; proxy_pass http://vaultwarden-ws; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
location /notifications/hub/negotiate { proxy_pass http://127.0.0.1:5814; }
|
保存即可,此时访问网址已经可以看到相关页面了,注册一个账号作为使用的主账号,可以导出 chrome 浏览器以前保存过的密码,然后导入到 Bitwarden
调整 docker
由于我是自己用的,所以还需要禁用注册
停止并删除 docker 管理器上的容器,因为需要用命令行去重新创建一个

打开系统命令行
1 2 3 4 5 6 7 8 9 10
| docker run -d --name Bitwarden \ -e ADMIN_TOKEN=yigefuzademima \ -e SIGNUPS_ALLOWED=false \ -e WEBSOCKET_ENABLED=true \ -e LOG_FILE=/data/vaultwarden.log \ -e TZ="Asia/Shanghai" \ -v /www/wwwroot/目录/:/data/ \ -p 5814:80 \ -p 3012:3012 \ vaultwarden/server:latest
|
使用 ADMIN_TOKEN=密码
环境变量来设置一个超级密码,密码具体自定义,一定要复杂一些
使用 SIGNUPS_ALLOWED=false
来关闭注册
使用 WEBSOCKET_ENABLED
开启 websocket
-v /www/wwwroot/xxx.xxx.com/:/data/ \
中 /www/wwwroot/xxx.xxx.com/
换为第一步新建站点、第二部新建 docker 选的的路径,这样不会丢失上一步注册的用户数据
LOG_FILE
指定日志输出路径
TZ
指定时区,方便查看日志 不修改无法使用 fail2ban
可用时区挂载替换此项 -v /etc/localtime:/etc/localtime
执行完成后刷新 docker 管理器会发现又重新出现了一个容器
设置容器自启动 (可选)
1 2
| docker update --restart=always Bitwarden
|
定时备份

使用宝塔的计划任务,定时备份网址数据到服务器本地 / 腾讯云 COS
也可选择备份目录,因为我们选择了网站目录作为数据根目录,所以效果是一样的
各版本客户端下载地址
bitwarden
fail2ban 配置
使用 fail2ban 可以保护登录,官方文档
安装
软件商店搜索 fail2 进行安装

(可选)为 fail2ban-regex
建立软连接
1
| ln -s /www/server/panel/pyenv/bin/fail2ban-regex /usr/bin/fail2ban-regex
|
除了用于 bitwarden 的防护,还可以保护 ssh

创建规则
使用文件管理打开 /etc/fail2ban/filter.d
目录
创建文件 vaultwarden.conf
内容如下
1 2 3 4 5 6 7
| [INCLUDES] before = common.conf
[Definition] failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$ ignoreregex =
|
创建文件 vaultwarden-admin.conf
1 2 3 4 5 6
| [INCLUDES] before = common.conf
[Definition] failregex = ^.*Invalid admin token\. IP: <ADDR>.*$ ignoreregex =
|
启用规则
打开文件 /etc/fail2ban/jail.local
加入如下内容,其中 logpath
指定的是真实日志地址,和 LOG_FILE
指定的路径是对应的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| [vaultwarden] enabled = true filter = vaultwarden port = 80,443 banaction = %(banaction_allports)s
maxretry = 3 findtime = 86400 bantime = 259200 logpath = /www/wwwroot/目录/vaultwarden.log
[vaultwarden-admin] enabled = true port = 80,443 filter = vaultwarden-admin banaction = %(banaction_allports)s
maxretry = 3 findtime = 86400 bantime = 259200 logpath = /www/wwwroot/目录/vaultwarden.log
|
重启服务

可以使用命令查看启动状态
1
| fail2ban-client status vaultwarden
|
⚠️ 使用宝塔 fail2ban 面板查看封禁用户
☣️[警告], 此操作不可逆,可能会对宝塔 fail2ban 造成损害,且只能在线查看,不支持配置
此操作是为了方便查看封禁信息

使用宝塔打开 /www/server/panel/plugin/fail2ban/config.json
填入
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
| { "sshd": { "act": "true", "port": "22", "maxretry": 3, "findtime": 86400, "bantime": 259200, "dir": "" }, "vaultwarden": { "act": "true", "port": "80,443", "maxretry": 3, "findtime": 86400, "bantime": 259200, "dir": "" }, "vaultwarden-admin": { "act": "true", "port": "80,443", "maxretry": 3, "findtime": 86400, "bantime": 259200, "dir": "" } }
|
docker-compose 配置
新建 docker-compose.yml
文件,粘贴此配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| services: bitwarden: container_name: Bitwarden environment: - ADMIN_TOKEN=SSF - SIGNUPS_ALLOWED=false - WEBSOCKET_ENABLED=true - LOG_FILE=/data/vaultwarden.log - TZ=Asia/Shanghai volumes: - "./bitwarden/:/data/" ports: - "80:80" restart: always image: "vaultwarden/server:latest-alpine"
|
更新并启动
1 2 3
| docker-compose up -d --build --remove-orphans
|
使用 vaultwarden-backup 进行备份
使用 vaultwarden-backup
,将 Bitwarden
加密备份到云盘上
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
| services: bitwarden: container_name: bitwarden environment: - ADMIN_TOKEN=AAA - SIGNUPS_ALLOWED=false - ENABLE_WEBSOCKET=true - LOG_FILE=/data/vaultwarden.log - TZ=Asia/Shanghai - LOG_LEVEL=info volumes: - "./bitwarden/:/data/" restart: always image: "vaultwarden/server:latest-alpine" networks: - my_net
backup: image: ttionya/vaultwarden-backup:latest container_name: bitwarden-backup restart: always environment: CRON: "0 20 * * *" ZIP_PASSWORD: "112233" ZIP_TYPE: "7z" BACKUP_KEEP_DAYS: 3 TIMEZONE: "Asia/Shanghai" PING_URL: "https://open.feishu.cn/open-apis/bot/v2/hook/1" PING_URL_CURL_OPTIONS: > -H "Content-Type: application/json" -d '{"msg_type":"text","content":{"title":"%{subject}","text":"%{content}"}}' PING_URL_WHEN_SUCCESS: "https://open.feishu.cn/open-apis/bot/v2/hook/" PING_URL_WHEN_SUCCESS_CURL_OPTIONS: > -H "Content-Type: application/json" -d '{"msg_type":"text","content":{"text":"✅ Backup succeeded"}}' PING_URL_WHEN_FAILURE: "https://open.feishu.cn/open-apis/bot/v2/hook/" PING_URL_WHEN_FAILURE_CURL_OPTIONS: > -H "Content-Type: application/json" -d '{"msg_type":"text","content":{"text":"❌ Backup failed"}}' volumes: - ./bitwarden:/bitwarden/data/ - ./backup/:/config/ networks: - my_net
|