直接用return 301最稳妥,不走正则、不开销、不冲突;http→https、域名统一、单页跳转等均应在独立server块中用return实现,禁用$host防开放重定向,http与https必须分端口部署并reload生效。

直接用 return 301 最稳妥
绝大多数场景下,别碰 rewrite,直接在 server 块里写 return 301。它不走正则匹配、不进 location 匹配流程,开销小,行为确定,不会和其它规则冲突。
常见错误是把重定向写在 location 里却忘了加 = 精确匹配,导致跳转被覆盖或循环;或者用 rewrite 却漏了 permanent,结果返回的是 302(临时跳转),搜索引擎不传递权重。
- HTTP → HTTPS 全站跳转:在监听 80 的
server块中加return 301 https://$host$request_uri; - 域名统一(如
example.com→www.example.com):单独起一个server块,server_name example.com;,然后return 301 https://www.example.com$request_uri; - 单页面跳转(如
/old.html→/new.html):用location = /old.html { return 301 /new.html; },注意=表示精确匹配,避免误伤其他路径
error_page 404 跳转必须配合命名 location
想把 404 页面自动 301 跳到首页或新地址,不能直接在 error_page 后写 return —— Nginx 不允许这样用。必须通过命名 location 中转。
典型配置长这样:
error_page 404 = @notfound;
location @notfound {
return 301 https://example.com$request_uri;
}
漏掉 = 或写成 error_page 404 /404.html 就只是返回静态页,不是跳转;如果 @notfound 里用了 rewrite,还可能触发内部重定向循环,日志里会看到 rewrite or internal redirection cycle 错误。
多个域名共用一个配置时,server_name 和 $host 别混用
比如你设了 server_name a.com b.com;,然后写 return 301 https://$host$request_uri;,看起来没问题 —— 但当用户用 IP 直连或 Host 头异常时,$host 可能为空或不可信,导致跳转到 https:///xxx 这种非法 URL。
更安全的做法是分拆 server 块,或显式判断:
- 只对已知域名跳转:
if ($host ~ ^(a\.com|b\.com)$) { return 301 https://$host$request_uri; } - 强制指定目标域名:
return 301 https://www.a.com$request_uri;,不依赖$host - 禁止 IP 直接访问:在默认
server块里return 444;(关闭连接)或return 403;
HTTPS 配置后,HTTP 的 301 必须独立监听 80 端口
很多人以为只要在 HTTPS 的 server 块里加个 listen 80; 就能同时处理 HTTP 跳转,这是错的。Nginx 要求每个 server 块的 listen 指令协议必须一致:要么全为 listen 80(HTTP),要么全为 listen 443 ssl(HTTPS)。
所以标准结构一定是两个分离的 server 块:
- 一个只
listen 80,负责所有 301 跳转(包括 HTTP→HTTPS) - 另一个只
listen 443 ssl,加载证书,处理真实 HTTPS 请求 - 两者
server_name必须完全一致,否则某些请求可能落到默认 server,跳转失效
配置改完后,务必运行 nginx -t 校验语法,再 systemctl reload nginx —— 直接 restart 可能因配置错误导致服务中断。











