核心是单独配置监听80端口的server块,用return 301 https://$host$request_uri跳转至HTTPS,同时必须独立配置启用SSL证书的443端口server块。

在 Nginx 的 Virtual Host(虚拟主机)中实现 HTTP 强制跳转 HTTPS,核心是单独配置一个监听 80 端口的 server 块,用 301 重定向把所有请求发往对应的 HTTPS 地址。这不是在 HTTPS 的 server 块里加逻辑,而是另起一个纯 HTTP 入口做“守门人”。
只监听 80 端口 + return 301(推荐)
这是最简洁、高效、无歧义的方式:
- 新建或编辑
/etc/nginx/conf.d/your-site.conf(或对应虚拟主机配置文件) - 添加一个仅监听 80 端口的 server 块,不启用 SSL
- 使用
return 301直接构造目标 HTTPS URL
示例配置:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}说明:
$host 自动取请求头中的域名(如 www.example.com),保持原域名不变;
$request_uri 完整保留路径和查询参数(如 /login?next=/admin);
301 是永久重定向,对 SEO 友好,浏览器和搜索引擎会缓存该跳转。
HTTPS server 块必须独立存在
跳转本身不依赖 HTTPS server 是否已配置,但用户最终要能访问到 HTTPS 站点,所以还需配一个监听 443 端口的 server:
server {
listen 443 ssl;
server_name example.com www.example.com;
<pre class='brush:php;toolbar:false;'>ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# 其他 location、root、PHP 处理等配置...
location / {
root /var/www/example;
index index.html;
}}
注意:
✅ 两个 server 块必须共用相同的 server_name,否则跳转后可能因 SNI 或证书不匹配失败;
✅ 443 块中 ssl_certificate 和 ssl_certificate_key 路径必须真实存在且权限正确(如 nginx 用户可读);
❌ 不要在 443 块里写 if ($scheme = http) { ... } —— 这种写法无效,因为 443 块根本收不到 HTTP 请求。
避免常见错误
以下做法容易出问题,不建议采用:
-
用 rewrite 替代 return:如
rewrite ^(.*)$ https://$host$1 permanent;功能等价但多一次正则匹配,无必要 -
在同一个 server 块里混用 80 和 443 并靠 if 判断端口跳转:如
if ($server_port = 80) { return 301 ... }—— Nginx 官方明确不推荐在 server 级别用 if,易引发意外行为 -
漏掉 $request_uri:写成
return 301 https://$host/;会导致所有请求都跳首页,丢失原始路径 - 防火墙未放行 443 端口:跳转能触发,但后续 HTTPS 请求会被拦截,表现为“连接被拒绝”或超时
验证与生效
配置完成后务必执行:
-
sudo nginx -t检查语法是否正确 -
sudo systemctl reload nginx(或nginx -s reload)平滑重载 - 用
curl -I http://example.com确认返回HTTP/1.1 301 Moved Permanently及正确的Location头 - 浏览器访问
http://example.com/test?x=1,确认跳转后 URL 为https://example.com/test?x=1


















