ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Vaultwarden自托管实战:用cpolar内网穿透搭建密码管理器

Vaultwarden自托管实战:用cpolar内网穿透搭建密码管理器 自己搭一个密码管理器其实是把“数据掌控权”从别人手里拿回来的过程。Bitwarden 是目前公认的开源密码管理方案而自托管的 VaultwardenBitwarden 服务端的社区实现又解决了官方服务端太重、太吃资源的问题。不过自托管之后会立刻撞上一个门槛你家宽带没有固定的公网 IP出门在外根本连不回家里那台服务器。我当初就是卡在这一步最后用 cpolar 把内网服务安全地映射了出去才真正把这套密码系统跑通。这篇文章就把整套流程拆开来讲包括为什么这么选、每一步怎么操作、会遇到哪些坑以及跑起来之后怎么维护。适用对象很明确有一台 NAS、旧电脑、云服务器或者树莓派想彻底掌控自己密码数据同时不愿意每年为密码管理服务付费的用户。不需要你有很强的网络基础只要会敲几条命令、看得懂简单的 Docker 配置就能跟着做完。1. 为什么要用 Vaultwarden 自托管而不是直接用官方云服务1.1 密码管理器自托管的底层逻辑密码管理器的核心职责是把你所有的账号密码、支付信息、安全笔记加密存储并在需要的时候通过主密码解密。所有的加密解密都在客户端本地完成服务器只保存密文。这也是 Bitwarden 客户端敢于开源的原因——就算服务器被脱库攻击者拿到的也只是一堆无法解密的乱码。但这套逻辑成立的前提是服务器代码本身没后门、加密实现正确。官方云服务当然可信但“可信”和“可控”是两码事。自托管意味着你可以审计服务端代码、决定数据存储位置、控制备份策略甚至完全断外网在局域网里用。对于把全部数字生活密钥都放在一个地方的工具来说这种掌控感我觉得值回折腾成本。还有一个非常现实的原因官方云服务端需要.NET运行时加 SQL Server内存占用轻松上 GB。对家里那台 2GB 内存的 NAS 来说根本跑不动。Vaultwarden 用 Rust 重写了服务端内存占用常年维持在几十 MBSQLite 单文件存储备份就是复制一个文件的事。1.2 Vaultwarden 与官方服务器端的功能差异Vaultwarden 并非 Bitwarden 官方出品而是一个社区逆向工程实现。它兼容 Bitwarden 官方客户端浏览器插件、桌面端、iOS/Android App的 API所以客户端不需要做任何修改。实测下来绝大多数核心功能都可用密码库同步、组织共享、附件存储、TOTP 两步验证、紧急访问等。但有一点要注意Vaultwarden 毕竟是兼容实现官方新增的功能会有延迟比如某些新的硬件密钥绑定的前端交互。对你日常使用影响不大但心里要有数——如果有一天某个官方新功能对你特别重要先确认 Vaultwarden 是否已跟上版本。另外还有一个决策点既然叫“密码管理器”一旦运行起来它就会成为你的“唯一钥匙”所以服务稳定性直接影响你能否登上其他网站。这一点决定了自托管方案必须做好两件事备份要自动化、访问链路要尽量稳定。这也是我坚持用 cpolar 而不是手动改路由器的原因——后面细说。2. Docker 部署 Vaultwarden参数解析与数据目录规划2.1 部署前的环境准备建议系统为 Ubuntu 20.04/22.04 或 Debian 11/122GB 内存以上。如果你的设备是 NAS群晖/威联通系统本身带 Docker也可以直接操作但命令路径和权限管理略有差异下文以 Linux 服务器终端为准。安装 Docker 顺手把 compose 插件也装上现在推荐用 docker compose 管理sudo apt update sudo apt install docker.io docker-compose-v2 -y sudo systemctl enable --now docker注意 Ubuntu 的 docker-compose-v2 插件包和 pip 安装的旧版 docker-compose 不是同一个东西下文全部以docker compose子命令为准。2.2 用 docker compose 定义 Vaultwarden先建一个目录专门放 Vaultwarden 的配置和数据mkdir -p /opt/vaultwarden cd /opt/vaultwarden创建docker-compose.ymlservices: vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden restart: always environment: DOMAIN: https://yourdomain.example.com SIGNUPS_ALLOWED: false ADMIN_TOKEN: 请生成一个足够长的随机字符串 volumes: - ./vw-data:/data ports: - 8080:80解释几个关键参数这些不是随便写的DOMAIN告诉 Vaultwarden 你最终对外访问的地址影响两步验证、邮件链接、WebAuthn 等功能的 URL 生成。这个参数必须和用户实际访问的地址一致否则会出现“客户端连接失败”这类诡异问题。SIGNUPS_ALLOWED部署期间先设成true注册完自己的账号后必须改成false否则你的实例会被全网扫描任何人都能注册账号并在你的服务器上存密文。ADMIN_TOKEN管理后台的访问口令必须设置。没有它你没法打开/admin页面也没法发邀请链接、查日志。ports把容器内的 80 端口映射到宿主机的 8080。之所以不用默认 80是因为 cpolar 和反向代理通常也需要占用端口错开能少很多麻烦。关于版本号不要在自托管服务上用latest之外的选择但也别完全不管更新。我的习惯是每两个月跑一次docker compose pull docker compose up -d小版本更新随更随用因为密码管理器涉及到安全漏洞修复。2.3 首次启动与账号注册执行docker compose up -d docker logs -f vaultwarden看到日志里出现类似Starting server on 0.0.0.0:80的输出就说明服务起来了。浏览器访问http://服务器IP:8080应该能看到 Bitwarden 的 Web 登录界面。这时先不要注册账号而是设置ADMIN_TOKEN并用它登录/admin页面确认管理后台可用后再回到首页注册你的账号。Vaultwarden 有一个机制第一个注册的账号会成为管理员前提是 SIGNUPS_ALLOWED 开启这个账号不能轻易删除否则整个实例的管理权限就丢了。注册完立刻去改配置nano /opt/vaultwarden/docker-compose.yml # 将 SIGNUPS_ALLOWED 改为 false docker compose up -d到这里局域网内的密码管理服务已经可用了。但你的客户端仍然无法“出门在外”连回来这正是下一章要解决的问题。3. cpolar 隧道配置从内网地址到公网访问的完整链路3.1 为什么选择 cpolar 而不是手动端口映射传统做法是去路由器后台做端口映射把公网 IP 的 443 端口转发到服务器的 8080。但只适用于两种情况宽带有公网 IP且运营商没封 443 端口。现在很多家宽拿到的都是大内网 IP路由器 WAN 口地址是 100.64.x.x 这种共享网段从公网根本路由不进来。就算有公网 IP443 端口也常常被运营商封禁你不得不用高位端口而高位端口会被手机流量、公司网络的各种防火墙拦截。cpolar 这类内网穿透工具解决的正是“无公网 IP 端口受限”这个场景。它在你的服务器上跑一个客户端主动向外部的 cpolar 服务器建立长连接外部用户访问 cpolar 分配的域名时流量会经由这条隧道转发到你的内网服务。这类工具市面上很多frp 和 ngrok 生态也成熟但 cpolar 胜在三个点隧道配置有 Web 后台管理不用手动编辑 frpc.ini免费套餐提供 HTTP/HTTPS 隧道能满足密码管理器的证书需求国内访问速度整体优于 ngrok 官方线路。免费版隧道域名随机变化这符合密码管理器吗我建议用付费固定域名原因在第 4 章讲证书时会说清楚。3.2 安装 cpolar 与认证在 Vaultwarden 所在服务器上安装curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash安装完成会多出一个cpolar命令。先注册 cpolar 账号登录后台拿到一个认证 token然后执行cpolar authtoken 你的token这个命令会把认证信息写入~/.cpolar/cpolar.yml。注意如果你用 root 用户安装那么认证信息在/root/.cpolar下如果用普通用户再 sudo那么路径可能在普通用户 home 下不同用户切过去可能找不到凭据日志报 401 时先查这个。3.3 创建第一个 HTTP 隧道先用一条命令快速验证链路通不通cpolar http 8080终端会显示随机分配的域名类似https://xxxxx.cpolar.top。浏览器访问这个域名如果看到 Vaultwarden 登录页说明隧道已经通了。但注意这个功能没有持久化关掉终端隧道就断了。正确做法是在 cpolar Web 后台配置固定隧道。登录 cpolar 后台进入“预留”页面。如果是付费套餐先在“保留域名”里添加一个自定义域名比如vw.yourname.cpolar.top然后添加隧道时选择这个保留域名本地地址填127.0.0.1:8080协议选 HTTP。为什么隧道地址填127.0.0.1因为 cpolar 客户端就运行在 Vaultwarden 同一台机器上直接走回环接口避免经过外部交换机也顺便绕开防火墙引流的麻烦。cpolar 默认自动为 HTTP 隧道附加 HTTPS 支持这是关键点下一章展开。编辑 cpolar 配置文件通常在~/.cpolar/cpolar.yml时手动声明隧道名可以更清晰tunnels: vaultwarden: proto: http addr: 8080 domain: vw.yourname.cpolar.top然后重启 cpolar 服务sudo systemctl restart cpolar此时 cpolar 的免费套餐和付费套餐差异会直接影响后续使用免费套餐的隧道域名带动态路径证书不好配付费套餐支持自定义子域名和保留域名证书链完整。密码管理器场景建议上付费套餐一个月一杯咖啡的钱换稳定的访问入口。4. HTTPS 证书与移动端实测自托管密码库真正可用的最后一环4.1 为什么必须启用 HTTPS浏览器有一个安全策略在 HTTPS 页面请求 HTTP 资源会被拦截反过来也一样。如果用户通过https://vw.yourname.cpolar.top访问 Vaultwarden但 Vaultwarden 返回的静态资源和 API 响应全是 HTTP浏览器控制台会刷满 mixed content 报错密码库根本加载不出来。更重要的一点密码管理器的传输链路不可信等于密码明文在网上裸奔。虽然客户端加密后传输但 TLS 层仍然必不可少——它是防止窃听和中间人攻击的第一道防线。cpolar 的 HTTP 隧道默认有一个好行为它会自动为首选域名申请 Lets Encrypt 证书并托管 TLS 终结。也就是说你不用在 Vaultwarden 容器里配证书也不用在后端 Nginx 里写证书路径cpolar 到用户浏览器这一段落了 HTTPScpolar 到本机回环接口这一段走明文 HTTP。这个链路模型是可接受的因为回环接口上没有任何中间设备。4.2 客户端连接配置以 iOS/Android 和浏览器为例这步是大多数教程不细讲、但新手最容易懵的地方。Bitwarden 客户端默认连接的是官方服务器你必须把服务器 URL 改成自己的地址。浏览器扩展安装 Bitwarden 浏览器扩展后点击右上角设置图标找到“服务器 URL”选择“自托管”输入https://vw.yourname.cpolar.top保存后回到登录页用你之前注册的邮箱和主密码登录移动端 AppiOS/Android打开 App 后先别急着登录点右上角或左上角的设置按钮一般是个齿轮或头像一个找到“服务器 URL”或“自托管”选项输入与自己域名一致的地址保存后 App 会重新加载再输入邮箱和主密码这里容易踩的坑把地址填成了http://服务器IP:8080或者填了一个带路径的地址。Vaultwarden 的 API 是直接从根路径挂载的任何路径后缀都会让客户端在请求api/...时拼接出错误 URL。如果你在用浏览器扩展和手机 App 的时候遇到An error has occurred之类提示第一件事就是核对 URL 是否以https://开头、有没有多余路径、能不能在浏览器里打开这个域名看到登录页。4.3 实测常见错误与处理我把跑通前后遇到的高频问题整理一下每一条都对应一个明确的处理动作现象原因解决浏览器访问隧道域名显示“不安全”证书未签发或域名被浏览器拦截等待几分钟证书自动申请检查域名拼写cpolar 后台确认隧道状态为 active手机 App 登录提示“连接失败”URL 填错或网络无法触达隧道用手机浏览器先访问一遍域名确认能打开再检查 URL 是否多打斜杠网页能开但登录后一直转圈Vaultwarden 的 DOMAIN 设置与访问地址不一致修改 docker-compose.yml 的 DOMAIN 为最终 HTTPS 域名重启容器cpolar 日志提示 401 Unauthorizedtoken 未认证或用户不对重新执行cpolar authtoken确保和启动 cpolar 服务的用户一致还有一类问题不常见但很危险你用的是免费版的随机域名域名一旦变化客户端里保存的服务器 URL 就失效。手机端你可以在 App 里更新但浏览器扩展如果开了“自动锁定”而且是靠主密码登录那倒还好可如果你开了“记住我”那么所有设备的登录态都会在域名切换时失效这是灾难性的体验。而自定义域名永久不变就彻底绕开了这个坑。5. 跑起来之后的事备份体系、常见故障与我的几点使用心得5.1 建立无脑备份链路密码管理器没有备份等于定时炸弹。Vaultwarden 的存储核心是 SQLite 数据库文件和config.json它们都在./vw-data目录里。备份策略极其简单把整个目录打压缩包至少保留最近 7 天。我每天凌晨 3 点跑一次备份脚本任务如下#!/bin/bash BACKUP_DIR/opt/backups/vaultwarden DATE$(date %F) mkdir -p $BACKUP_DIR cd /opt/vaultwarden docker exec vaultwarden sqlite3 /data/db.sqlite3 .backup /data/db-backup.sqlite3 tar czf $BACKUP_DIR/vw-$DATE.tar.gz vw-data find $BACKUP_DIR -name *.tar.gz -mtime 14 -delete用sqlite3 .backup而不直接cp db.sqlite3的原因SQLite 在写入时直接复制数据文件可能拿到损坏的快照.backup是官方推荐在线备份方式。如果容器里没有 sqlite3 命令可以先装也可以接受极小概率的备份不一致——但没必要冒险。备份文件若只在同一台机器上硬盘挂了就全没了。建议任何云盘、另一台 NAS、对象存储里放一份。密码库密文即使泄露也不是明文所以备份传云端的安全等级比裸传文件高得多。5.2 换了域名或者服务器迁移怎么处理自托管服务最麻烦的一件事就是迁移。Vaultwarden 的迁移比很多自托管软件简单因为它把所有状态都存到了vw-data目录停容器打包 vw-data 目录传到新服务器的相同路径改 docker-compose.yml 里的 DOMAINdocker compose up -d但如果只是换了 cpolar 隧道域名不迁移服务器那么要做两件事改 Vaultwarden 的 DOMAIN 环境变量然后重启容器所有已登录的客户端重新设置服务器 URL 并重新登录。这里注意一个隐藏行为Bitwarden 客户端在检测到新设备登录时会给注册邮箱发一封验证邮件。如果你在局域网环境没配 SMTP邮件发不出去登录会卡在“验证邮箱”这一步。解决方式是在管理后台把新设备登录验证选项关掉或者干脆配置好 SMTP。验证邮件这个功能一旦卡住非常容易让人误以为服务挂了实际只是邮件发不出去。我最初在这里浪费了半个小时。5.3 一些并不在官方文档里的建议部署完成后有几个容易被忽略的安全加固点主密码强度是安全链的起点建议 4 个随机单词加数字和符号长度不少于 16 位。几乎可以这么说如果有人能记住你的主密码那它就太弱了。开启两步验证Vaultwarden 自带 TOTP 验证器支持。第一步用密码第二步用验证码两层都拿下才进得去。别把验证器和密码存在同一个设备里用独立的验证器 App。定期做恢复演练每季度从备份目录里把 vw-data 恢复到一台临时容器试着用客户端登录一次。真到数据丢了才想起验证备份可用往往已经晚了。cpolar 隧道的访问密码在 cpolar 后台可以给隧道设置访问密码Basic Auth前置校验后再进入 Vaultwarden等于多一层门禁。这个功能对暴露到公网的服务很有价值。我实际用下来的体感是Vaultwarden cpolar 这套组合稳定运行几个月基本不用管。偶尔看一眼 cpolar 后台看下流量走势遇到版本更新就 pull 一次镜像。整个系统的复杂度都集中在最初的搭建和第一次客户端连接上跑通之后就只是日用工具了。最后分享一个小技巧Vaultwarden 的 Web 界面本身就是个很好用的密码库查看器但日常我更推荐直接装官方桌面客户端配合浏览器扩展的自动填充体验最顺。手机端打开面容解锁出门付款、登录各种 App 都能一键填充密码那种“所有密码都在兜里”的踏实感是自托管带给我最大的回报。
返回列表