HTTPS 是硬要求:反向代理与证书
为什么 HTTP 不行
这是部署阶段最重要的一条规则:Vaultwarden 必须跑在 HTTPS 下面。不是「建议」,是「必须」。官方的浏览器插件和手机 App 在连接纯 HTTP 地址时会直接拒绝,除非明确开启不安全的本地测试开关。
原因有两个。技术层面,浏览器插件申请的很多接口权限只在安全上下文里可用,HTTP 页面拿不到这些能力,功能会莫名缺失。安全层面,密码相关的流量以明文形式在互联网上传输本身就是不可接受的,链路中任何一个节点都能截获,而你的运营商节点并不比陌生人更值得信任。
| 浏览器表现 | 原因 |
|---|---|
| 插件提示无法连接 | 客户端拒绝 HTTP 服务器 |
| 页面功能部分失效 | 安全上下文能力缺失 |
| App 登录报错 | 同上,且无例外开关可用 |
所以在个人测试的局域网环境里,你可以用 HTTP 快速验证服务是否跑通;只要进入正式使用,就必须上 HTTPS。早点接受这一点,能少走很多弯路。也有人不服气,尝试用自签证书绕开,结果每个设备都要手动信任一次,家人根本无法接受。免费证书如此容易获得,没有必要走这条弯路。
反向代理选 Nginx 还是 Caddy
反向代理的作用是在 Vaultwarden 前面加一层,由它来处理 HTTPS 证书和域名解析,再把请求转发给后端容器。常见的两个选择是 Nginx 和 Caddy。
Nginx 是老牌选手,文档浩如烟海,几乎任何问题都能搜到答案。Caddy 的卖点是自动 HTTPS:配置文件里写上域名,它自动申请并续期证书,对新手友好得多。两件工具都能胜任,选你更熟悉或更愿意学的那个,而不是听起来更厉害的那个。
从安装方式看两者都简单。Nginx 各大发行版都有现成包,Caddy 同样提供包与单文件两种形态。在你已经有 Nginx 跑着其他服务的情形下,多加一段配置是自然之选;如果是全新开始且不想碰证书工具,Caddy 能省掉大半的学习曲线。
| 对比项 | Nginx | Caddy |
|---|---|---|
| 配置复杂度 | 稍高,语法严谨 | 极低,几行搞定 |
| 证书管理 | 需要额外工具配合 | 内置自动申请与续期 |
| 性能调优空间 | 大 | 够用 |
| 社区资料 | 极多 | 逐渐丰富 |
| 与现有服务整合 | 强 | 强 |
如果家里有多个自建服务,反向代理也会自然成为所有服务的统一入口。学会配一个,其余服务照葫芦画瓢,投入产出比很高。这也是为什么很多自建玩家把 Nginx 或 Caddy 本身当成家庭基础设施的标配组件。
Nginx 配置参考
下面是一份经过简化但可直接使用的 Nginx 配置,为叙述方便省略了部分高级调优:
server {
listen 443 ssl http2;
server_name vault.example.com;
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
client_max_body_size 64M;
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_set_header X-Forwarded-Proto $scheme;
}
location /notifications/hub {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
有两个细节值得注意。client_max_body_size 要调大,因为附件上传默认会超过 Nginx 的 1MB 限制,症状是上传稍大的文件就失败。第二段 location 处理的是 WebSocket 长连接,客户端的实时同步依赖它,漏掉这一段会导致密码更新不能及时推送到其他设备,表现就是「明明改了,另一台手机上要等很久才看到」。
Caddy 配置参考
Caddy 版本要短得多:
vault.example.com {
reverse_proxy /notifications/hub 127.0.0.1:8080
reverse_proxy 127.0.0.1:8080
}
把这段写进 Caddyfile,启动服务,剩下的 Caddy 全包:申请证书、续期、HTTP 自动跳转 HTTPS。这也是很多自建玩家最终选择 Caddy 的原因,配置越短,能错的地方越少。无论选哪个,背后的原理都是一样的:在前面终结 TLS,把明文流量留在本机内部。
两个工具还可以分工合作。常见的一种组合是 Nginx 负责流量转发,证书申请交给独立的工具以统一管理全家所有服务的证书。怎么组合取决于你家里现有的设施,没有标准答案,自己用得顺的就是好方案。
证书:自动申请与续期
HTTPS 证书绑定一个域名,由证书颁发机构签发。个人用最常见的选择是免费的 Let’s Encrypt,有效期三个月,通过工具自动续期后可以永久使用。另外还有 ZeroSSL 等同类机构,用 certbot 这类工具申请时可以互换,差别不大。
| 签发方式 | 原理 | 适用场景 |
|---|---|---|
| HTTP 验证 | 机构访问你的 80 端口确认域名所有权 | 有公网 IP 且开放 80 |
| DNS 验证 | 在域名解析里加一条 TXT 记录 | 内网服务或 80 端口被封 |
| 泛域名证书 | 一次覆盖所有子域名 | 子域名很多的家庭环境 |
证书过期是自建服务最常见的故障之一。症状很典型:某天突然所有客户端都连不上,但服务其实还在跑。解决办法是在部署时就配好自动续期,然后偶尔看一眼续期任务的执行日志,确认它确实在工作。Certbot 和 Caddy 各有自己的续期机制,别同时开两套,互相打架反而容易出事。

常见排错
部署 HTTPS 过程中你大概率会遇到其中一两个问题:
| 症状 | 排查方向 |
|---|---|
| 证书申请失败 | 检查域名解析是否生效、80 端口是否放行 |
| 客户端连不上但网页能开 | 检查反向代理与容器端口是否一致 |
| 同步延迟严重 | 检查 WebSocket 转发是否配置 |
| 上传附件报错 | 检查代理的请求体大小限制 |
| 证书过期后服务不可用 | 确认自动续期任务还在运行 |
排查这类问题有一个通用顺序:先看域名解析,再看端口连通性,最后看配置文件。从外往内逐层排除,比一上来就翻配置文件高效得多。善用 curl 加 -v 参数可以看到握手过程,是判断 TLS 层面问题的利器。
再补充一个高频疑问。配完 HTTPS 之后要不要保留 HTTP 的 80 端口监听?答案是要保留,但只用于跳转和证书申请的验证。80 端口里放一条 301 跳转把流量全部导向 443,既不影响体验,也给证书自动验民留了通道。别把 80 关掉,否则下次续期可能就失败。
转发头信息的意义
代理配置里那一串 set_header 不是摆设。后端容器需要知道真实客户端的 IP 与协议,才能正确处理信任判定与日志记录。
| 头信息 | 作用 |
|---|---|
| Host | 让后端识别请求的原始域名 |
| X-Real-IP | 记录真实客户端地址 |
| X-Forwarded-For | 传递完整的代理链路 |
| X-Forwarded-Proto | 告诉后端原始协议是 HTTPS |
这套约定是反向代理的通用姿势,学会之后迁移到任何自建服务都用得上,属于投入一次终身受益的知识。把这些小细节一次配对,后面几年都不会再为它们操心。

延伸阅读
- 软路由指南:理解端口放行与 NAT 转发的配置位置
- OpenWrt 基础:在路由器层面为服务做端口规划
