应排除 .well-known 目录以保障 Let’s Encrypt 等 ACME 协议的 HTTP 验证正常工作;推荐用 if + set 变量控制跳转逻辑,避免嵌套 rewrite 或 location 冲突,确保 80 端口下仅对非白名单路径执行 301 跳转。

直接在 HTTP → HTTPS 重定向规则里排除特定目录,比如 .well-known,关键不是“绕过重定向”,而是让 Nginx 在判断是否跳转前,先识别出这些路径并跳过处理。用 if + set 组合是最稳妥、兼容性最好的方式,避免使用容易出错的嵌套 rewrite 或 location 匹配冲突。
为什么 .well-known 必须排除?
ACME 协议(如 Let’s Encrypt 自动续签)依赖 http://domain/.well-known/acme-challenge/xxx 这一路径走纯 HTTP 访问。如果该路径被强制 301 跳转到 HTTPS,验证请求就会失败,导致证书续签中断。
其他类似场景还包括:
• 部分监控探针或健康检查接口要求明文 HTTP
• 内部服务调用未启用 TLS 的临时调试路径
推荐写法:用变量控制跳转开关
在 server 块(监听 80 端口)中添加如下逻辑:
set $should_redirect "1";
if ($request_uri ~ ^/.well-known/ ) {
set $should_redirect "0";
}
if ($server_port = 80) {
set $should_redirect "${should_redirect}1";
}
if ($should_redirect = "11") {
return 301 https://$host$request_uri;
}
说明:
• 第一个 if 捕获 .well-known 路径,设为 "0"
• 第二个 if 确保只对 80 端口生效(防止 HTTPS server 块误触发)
• 合并成 "11" 是为了规避 Nginx 中 if 嵌套不支持的问题,比单纯用 $jump 更健壮
• 使用 return 301 比 rewrite ... permanent 更高效,且不触发内部重写循环
常见错误要避开
• 别在 location / { } 里写 rewrite:location 匹配优先级高,容易和静态文件服务、PHP 处理等冲突
• 别用 root 或 alias 匹配 .well-known:这只能解决文件服务问题,不能阻止重定向本身
• 别依赖 $scheme 判断:HTTP 请求的 $scheme 永远是 http,无法用于“排除”逻辑
• 测试时清空浏览器缓存或用 curl -I:301 会被强缓存,本地测试容易误判
多目录排除可扩展写法
需要同时放行多个路径时,把正则改成 OR 形式即可:
if ($request_uri ~ ^/(\.well-known|health|debug)/ ) {
set $should_redirect "0";
}
注意:
• ^/ 保证从 URI 开头匹配,避免误伤如 /api/v1/.well-known
• 点号 . 要转义为 \.,否则正则会匹配任意字符
• 多个路径之间用竖线 | 连接,括号包裹保持语义清晰


















