301 永久重導向是 SEO 優化、域名遷移、協定升級的核心手段。Nginx 透過 rewrite 或 return 指令即可高效實現各類重導向邏輯。本文系統整理 Nginx 301 配置最佳實踐,涵蓋 非 www 轉 www、多舊域名轉主域名、HTTP 強制 HTTPS、目錄/頁面級重導向、保留查詢字串 等實戰場景,並說明常見陷阱與除錯技巧。
| 指令 | 適用場景 | 效能 | 推薦度 |
|---|---|---|---|
return 301 URL | 簡單整站/整塊重導向 | 最高 (無正則解析) | ⭐⭐⭐⭐⭐ 首選 |
rewrite ^ regex URL permanent | 需正則捕獲/變數重組 | 稍低 (正則解析) | ⭐⭐⭐⭐ 靈活但慎用 |
if ($host != '...') | 條件式重導向 | 最低 (if 是邪惡的) | ⭐⭐ 盡量避免 |
server {
listen 80;
server_name example.com www.example.com;
# 方案 A:return 指令 (最高效、最清晰)
if ($host = 'example.com') {
return 301 https://www.example.com$request_uri;
}
# 方案 B:rewrite (舊版相容)
# if ($host != 'www.example.com') {
# rewrite ^/(.*)$ https://www.example.com/$1 permanent;
# }
# 正常站點配置...
root /var/www/example.com;
index index.html index.php;
}
注意: Nginx 官方文件建議避免在 location 區塊使用 if,但在 server 區塊僅做 return/rewrite 是安全的。
server {
listen 80;
server_name old.com www.old.com legacy.net www.legacy.net *.old.com;
return 301 https://www.newdomain.com$request_uri;
# 所有匹配 server_name 的請求,保留原 URI 路徑與查詢字串,301 導向新域名
}
server {
listen 80;
server_name example.com www.example.com;
# ACME 挑戰路徑排除 (Let's Encrypt 驗證需 HTTP)
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
allow all;
}
# 其餘全部 301 導向 HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# HSTS: 瀏覽器記住強制 HTTPS 一年,含子域名,預載入
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 正常站點配置...
root /var/www/example.com;
index index.html index.php;
}
server {
listen 80;
server_name example.com;
root /var/www/example.com;
# 舊文章路徑 /article/123.html → 新路徑 /blog/123
location = /article/123.html {
return 301 /blog/123;
}
# 舊目錄 /old-dir/ 整體導向 /new-dir/ (保留後續路徑)
location /old-dir/ {
rewrite ^/old-dir/(.*)$ /new-dir/$1 permanent;
}
# 檔案擴展名統一 .html → 無副檔名
location ~ ^(.+)\.html$ {
return 301 $1;
}
}
server {
listen 80;
server_name *.example.com;
# 子域名 blog.example.com → /var/www/example.com/subdomains/blog
set $subdomain '';
if ($host ~* ^(.+)\.example\.com$) {
set $subdomain $1;
}
# 排除 www
if ($subdomain = 'www') {
return 301 https://example.com$request_uri;
}
root /var/www/example.com/subdomains/$subdomain;
index index.html index.php;
# 目錄不存在時回 404 或導向主站
location / {
try_files $uri $uri/ =404;
}
}
$request_uri 是否包含導向目標路徑,導致無限 301。用 curl -I -L 追蹤。return 301 ...$request_uri 會自動保留查詢字串;rewrite 需額外加 ?$query_string (Nginx 1.1.1+ 自動保留)。curl -I 或開啟無痕模式,CDN 需清除快取或設 Cache-Control: no-cache。nginx -t && systemctl reload nginx,確認無語法錯誤。Nginx 301 重導向核心原則:**優先用 return、盡量避免 if、保留查詢字串、防止迴圈、配合 HSTS 強化 HTTPS**。掌握這幾個模板,即可應對 95% 的重導向需求。