Nginx 如何把所有 HTTP 请求跳转到 HTTPS 且保留子域名?

Nginx 全站 HTTP 跳 HTTPS 且保留子域名:server_name 用通配或正则捕获 + return 301,$host 变量自动保留主机名;含完整配置、HSTS 提示与 FAQ。

最佳实践
Nginx 如何把所有 HTTP 请求跳转到 HTTPS 且保留子域名?封面

用 $host 变量做跳转目标:它提供规范化后的主机名(含子域名,不含端口),一条规则覆盖所有子域。

server {
    listen 80;
    server_name *.example.com example.com;

    return 301 https://$host$request_uri;
}

$host 保留子域名(api.example.com → https://api.example.com/...),$request_uri 保留完整路径和查询串。

各子域配置分散时的通用写法

如果请求没有匹配到其他具名 server,可以由默认 server 处理;它不能覆盖分散在其他文件中的具名配置:

# default_server 显式指定该监听地址/端口的默认 server
server {
    listen 80 default_server;
    server_name _;                    # 普通的不常用名称,不是匹配一切的特殊符号

    return 301 https://$host$request_uri;
}

只有未命中其他 server_name 的请求才由这里处理;已有具名 server 仍需单独配置跳转。公开入口应限定允许的域名,避免对任意 Host 生成跳转。

HTTPS 侧正常配

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate     /etc/nginx/ssl/example.com-wildcard.crt;   # 泛域名证书
    ssl_certificate_key /etc/nginx/ssl/example.com-wildcard.key;
    ...
}

多子域通常配一张泛域名证书(*.example.com),可覆盖一级子域,但不覆盖根域 example.com 或 a.b.example.com;Nginx 的通配 server_name 匹配范围与 TLS 通配证书不同。

先逐个检查实际使用的子域:HTTP 响应的 Location 是否保留主机名、路径和查询串,HTTPS 目标能否返回预期内容。观测云的 HTTP 拨测可持续请求这些端点,按状态码或响应内容判断结果;HTTP 跳转入口与 HTTPS 最终地址应分别覆盖。

可选:跳转后加 HSTS

确认 HTTPS 稳定运行后,在 443 的 server 块里加:

add_header Strict-Transport-Security "max-age=31536000" always;

浏览器此后一年内直接走 HTTPS,连 301 跳转都省了。⚠️ 没把握前别把 max-age 设大——设错后可通过可信 HTTPS 响应发送 max-age=0 清除客户端动态策略;无法送达时可能需等缓存过期。

常见问题(FAQ)

Q:$host 和 $server_name 有区别吗?
A:有。$host 依次取请求行主机名、Host 头或匹配的 server_name,并规范化;$server_name 是配置里写的第一个名字。保留子域名的场景必须用 $host。

Q:跳转后 POST 表单数据会丢吗?
A:301/302 允许客户端将 POST 改成 GET,不能保证保留请求体。必须保证表单 action 直接写 https 地址,跳转只是兜底;API 场景考虑 307/308(保持方法)。

Q:certbot 装的跳转配置为什么长得不一样?
A:certbot 用 if ($host = ...) { return 301 ... } 的写法,效果相同。return 写在 server 块顶层(上面示例)更简洁高效。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台