写点什么

粗心大意必酿大祸,记录 nginx 配置文件的一次闹剧

作者:BugShare
  • 2025-12-04
    山东
  • 本文字数:2203 字

    阅读完需:约 7 分钟

粗心大意必酿大祸,记录nginx配置文件的一次闹剧

一次域名配置引发的 Nginx 配置问题:HTTPS 与 server_name 的踩坑记录

在最近的项目维护中,我新增了一个域名 bugfix.wiki,计划将其解析到现有的网站上,与之前使用的 bugshare.cn 一样,通过 Nginx 实现完整的 HTTP/HTTPS 跳转逻辑。


域名备案、DNS、SSL 证书均已配置完毕,本以为只需复制一份现有配置即可。结果上线后却发现:bugfix.wiki 无法正常访问,而 bugshare.cn 却完全正常


问题的根源最终被定位在一个非常细微但关键的 Nginx 配置点上。这里记录整个过程,供日后参考,也供遇到相同问题的同学排查。



1. 预期目标

对两个域名(bugshare.cnbugfix.wiki)都希望实现如下行为:



即:


  • 全站 HTTPS

  • 全站强制“带 WWW”

  • 所有 HTTP 统一跳转到 HTTPS



2. 初始配置(bugshare.cn)——正常工作

bugshare.cn 的配置如下,可以正常运行:


server {    listen 80;    listen [::]:80;    server_name bugshare.cn www.bugshare.cn;    return 301 https://www.bugshare.cn$request_uri;}
server { listen 443 ssl; server_name bugshare.cn;
ssl_certificate /etc/nginx/conf.d/cert/bugshare.cn.pem; ssl_certificate_key /etc/nginx/conf.d/cert/bugshare.cn.key;
if ($host = 'bugshare.cn') { return 301 https://www.bugshare.cn$request_uri; }
location / { root /usr/local/nginx/html/dist; if ($uri = '/index.html') { add_header Cache-Control "no-cache, no-store, must-revalidate"; } try_files $uri $uri/ /index.html; }}
复制代码


注意:该配置虽然也存在优化空间,但在实际场景中运行完全正常。



3. 为 bugfix.wiki 复制一份配置后 —— 访问异常

为新域名复制后:


server {    listen 80;    listen [::]:80;    server_name bugfix.wiki www.bugfix.wiki;    return 301 https://www.bugfix.wiki$request_uri;}
server { listen 443 ssl; server_name bugfix.wiki; # ← 问题所在
ssl_certificate /etc/nginx/conf.d/cert/bugfix.wiki.pem; ssl_certificate_key /etc/nginx/conf.d/cert/bugfix.wiki.key;
if ($host = 'bugfix.wiki') { return 301 https://www.bugfix.wiki$request_uri; }
location / { root /usr/local/nginx/html/dist; if ($uri = '/index.html') { add_header Cache-Control "no-cache, no-store, must-revalidate"; } try_files $uri $uri/ /index.html; }}
复制代码


访问现象:



表面上跳转逻辑没问题,但最终 HTTPS 访问失败。



4. 问题定位:未将 www.bugfix.wiki 写入 HTTPS server_name

导致报错的关键配置问题:


server_name bugfix.wiki;
复制代码


缺少了:


www.bugfix.wiki
复制代码

为什么这是致命错误?

Nginx 在处理 HTTPS 时,会根据 SNI(Server Name Indication) 判断应该使用哪个 server 块及对应的 SSL 证书。


当访问 https://www.bugfix.wiki 时:


  • 浏览器会发送 TLS ClientHello,附带 SNI:www.bugfix.wiki

  • Nginx 根据 server_name 匹配 server 块

  • 此时配置中没有匹配 www.bugfix.wiki 的 443 server

  • Nginx fallback 到默认的 443 server(通常是第一个匹配到的)

  • 返回了不匹配的 SSL 证书 → 浏览器报错


现象表现为“网页无法正常运作”,实际是 SSL 证书不匹配导致连接被拒绝。



5. 修复后的正确配置

server {    listen 443 ssl;    server_name bugfix.wiki www.bugfix.wiki;
ssl_certificate /etc/nginx/conf.d/cert/bugfix.wiki.pem; ssl_certificate_key /etc/nginx/conf.d/cert/bugfix.wiki.key;
if ($host = 'bugfix.wiki') { return 301 https://www.bugfix.wiki$request_uri; }
location / { root /usr/local/nginx/html/dist; if ($uri = '/index.html') { add_header Cache-Control "no-cache, no-store, must-revalidate"; } try_files $uri $uri/ /index.html; }}
复制代码


重启 Nginx:


nginx -s reload
复制代码


问题即刻解决,所有访问路径完全正常。



6. 技术总结(关键要点)

✔ 1. server_name 必须覆盖 HTTPS 下的所有访问域名

尤其是:


  • 主域名(Apex domain)

  • 带 www

  • 子域名(如有)


否则 SNI 匹配失败,证书无法正确绑定。



✔ 2. Nginx 的域名匹配与“回源域名”无关

即使使用了 Cloudflare 等代理平台,只要请求最终到达 Nginx,SNI 匹配仍完全依赖 Nginx 的 server_name



✔ 3. HTTPS 的 server 块一定比 HTTP 更严格

HTTP 没有 SNI,匹配宽松得多;HTTPS 要求精确匹配 server_name,否则证书直接错乱。



✔ 4. 强烈建议使用统一跳转逻辑的最佳实践:

server_name bugfix.wiki www.bugfix.wiki;
复制代码


避免遗漏。


甚至可以进一步做:


server_name .bugfix.wiki;
复制代码


但需要根据实际情况决定。



7. 后记

整个问题看似隐蔽,其实本质是:


HTTPS server_name 少写了一个域名,导致 SNI 匹配失败。


属于 Nginx 配置中非常常见但又不容易第一时间想到的坑。


像这种“复制配置”场景,非常容易疏忽,提醒自己与大家:


复制配置永远不能无脑复制,尤其是 SSL 相关的 server 块。检查、检查、再检查。

发布于: 刚刚阅读数: 3
用户头像

BugShare

关注

BugShare,解决问题,快乐摸鱼 2025-10-18 加入

领先的bug分享,致力于愉快开发,快乐摸鱼,决绝996。

评论

发布
暂无评论
粗心大意必酿大祸,记录nginx配置文件的一次闹剧_nginx_BugShare_InfoQ写作社区