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

这套约定是反向代理的通用姿势,学会之后迁移到任何自建服务都用得上,属于投入一次终身受益的知识。把这些小细节一次配对,后面几年都不会再为它们操心。

请求从客户端到容器

延伸阅读