nginx中一个server块可同时响应http和https请求,核心是listen 80与listen 443 ssl共存于同一server块,ssl仅作用于443端口,证书配置不影响80端口,且ssl on;已废弃;协议不可混用单端口,双端口监听是最常用方案。

在 Nginx 中让一个 server 块同时响应 HTTP 和 HTTPS 请求,核心在于:**监听两个端口,并只对 443 端口启用 SSL**。不能在一个端口上自动“混用”协议,但可以通过单个 server 块统一管理逻辑,避免重复配置。
基础写法:listen 80 + listen 443 ssl
这是最常用、最清晰的方式。关键点有三个:
-
显式监听 80 和 443 两个端口:
listen 80;处理明文请求,listen 443 ssl;处理加密请求 -
去掉
ssl on;:该指令已废弃,Nginx 1.15.0+ 不再支持;SSL 启用由listen 443 ssl决定 -
证书配置仅作用于 443 流量:
ssl_certificate和ssl_certificate_key只在 TLS 握手时生效,对 80 端口无影响
示例配置:
server {
listen 80;
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
注意域名与资源加载一致性
虽然协议共存可行,但浏览器策略会影响实际体验:
- 如果用户通过
https://example.com访问,页面中所有资源(CSS、JS、图片)必须也走 HTTPS,否则会触发混合内容警告,部分资源被拦截 - 若需保留部分接口或静态资源走 HTTP(如内网调试、旧设备兼容),建议用不同子域(如
http://api.example.com)或路径前缀区分,避免同域混用引发安全限制 - 不推荐在 HTTPS 页面里硬编码
http://链接,可用协议相对链接(//example.com/js/app.js)或后端动态注入 scheme
进阶方案:stream 模块实现单端口分流
若受限于防火墙或负载均衡策略,只能开放一个端口(比如 443),又想让 HTTP 和 HTTPS 都能进,可借助 stream 模块做协议识别转发:
- 在
stream{}块中监听 443,用ssl_preread on判断客户端是否发起 TLS 握手 - 根据
$ssl_preread_protocol变量,把纯 HTTP 流量转发到本地 8080(HTTP 后端),TLS 流量转发到 8443(HTTPS 后端) - 此时真正的 HTTP/HTTPS 服务分别运行在 8080 和 8443,对外只暴露 443 端口
该方式更复杂,适用于特殊网络环境,日常部署推荐直接监听双端口。
常见错误排查要点
配置后访问异常,优先检查这几项:
- 确认
nginx -t配置语法通过,且重启服务生效:nginx -s reload - 确保系统防火墙(如 ufw、firewalld)放行了 80 和 443 端口
- 检查证书路径是否正确、文件权限是否允许 nginx 工作进程读取(通常为
root:www-data或root:nginx) - 避免多个
server块的server_name冲突或未匹配,默认 server 容易误接管请求











