一次域名配置引發的 Nginx 配置問題:HTTPS 與 server_name 的踩坑記錄
在最近的項目維護中,我新增了一個域名 bugfix.wiki,計劃將其解析到現有的網站上,與之前使用的 bugshare.cn 一樣,通過 Nginx 實現完整的 HTTP/HTTPS 跳轉邏輯。
域名備案、DNS、SSL 證書均已配置完畢,本以為只需複製一份現有配置即可。結果上線後卻發現:bugfix.wiki 無法正常訪問,而 bugshare.cn 卻完全正常。
問題的根源最終被定位在一個非常細微但關鍵的 Nginx 配置點上。這裏記錄整個過程,供日後參考,也供遇到相同問題的同學排查。
1. 預期目標
對兩個域名(bugshare.cn、bugfix.wiki)都希望實現如下行為:
| 輸入 URL | 預期跳轉 |
|---|---|
| http://domain | https://www.domain |
| http://www.domain | https://www.domain |
| https://domain | https://www.domain |
| https://www.domain | 內容正常訪問 |
即:
- 全站 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;
}
}
訪問現象:
- http://bugfix.wiki → 正常跳到 https://www.bugfix.wiki
- https://bugfix.wiki → 正常跳到 https://www.bugfix.wiki
- https://www.bugfix.wiki → 報錯「該網頁無法正常運作」
表面上跳轉邏輯沒問題,但最終 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 塊。檢查、檢查、再檢查。