症状
ブラウザで「ERR_TOO_MANY_REDIRECTS」「このページは正しくリダイレクトされていません」と表示される
結論:まずこれを確認
curl -I -L URLでリダイレクト先を追跡し、ループしているか確認する- nginx設定で同じURLへのrewrite/returnが連鎖していないか確認する
- SSL終端がnginxより前(ロードバランサー等)にある場合、
X-Forwarded-Protoの処理を確認する
トラブルシューティングフロー
flowchart TD
A[リダイレクトループ発生] --> B{curlでループ確認}
B -->|ループあり| C{HTTPSリダイレクト関連?}
B -->|ループなし| D[ブラウザキャッシュクリア]
C -->|Yes| E[SSL終端位置を確認]
C -->|No| F{rewrite/returnルール}
E --> G[X-Forwarded-Proto確認]
F -->|ルールあり| H[条件式を確認]
F -->|ルールなし| I[upstreamの設定確認]
G --> J[プロキシヘッダー設定を修正]
H --> K[重複・矛盾するルールを修正]
I --> L[バックエンドのリダイレクトを確認]
よくある原因
- HTTPからHTTPSへのリダイレクト設定の重複 - nginx側とアプリ側の両方でリダイレクト設定があり、互いに転送し合う
- ロードバランサー配下でのHTTPSリダイレクト - SSL終端がLB側にあり、nginx側では常にHTTPに見えるため無限ループする
- rewriteルールの条件不備 - リダイレクト後のURLも同じルールにマッチしてしまう
- trailing slashの処理 -
/pathと/path/を相互にリダイレクトし続ける - www有無のリダイレクト設定の矛盾 - www付きと無しで互いにリダイレクトする設定になっている
- locationブロックの優先順位問題 - 意図しないlocationブロックにマッチしている
- proxyヘッダーの未設定 - バックエンドが自身のURLを正しく認識できていない
確認手順
ステップ1: リダイレクトチェーンを確認する
curl -I -L --max-redirs 10 https://example.com/path
🔍 チェックポイント: Locationヘッダーの遷移を確認し、同じURLが繰り返されていればループ確定
ステップ2: nginx設定のrewrite/returnルールを確認する
# 設定ファイルからrewrite/returnを抽出
grep -rn "rewrite\|return 30" /etc/nginx/sites-enabled/
🔍 チェックポイント: 同じパスに対して複数のリダイレクトルールが存在しないか確認する
ステップ3: HTTPSリダイレクトの設定を確認する
# HTTPからHTTPSへのリダイレクト設定を確認
grep -rn "return 301 https" /etc/nginx/sites-enabled/
grep -rn "rewrite.*https" /etc/nginx/sites-enabled/
🔍 チェックポイント: リダイレクト条件に$schemeや$httpsの判定が含まれているか確認する
ステップ4: ロードバランサー環境の場合はヘッダーを確認する
# リクエストヘッダーを確認するためのテスト設定
# nginx.confのlocationブロックに一時的に追加
add_header X-Debug-Scheme $scheme;
add_header X-Debug-Forwarded-Proto $http_x_forwarded_proto;
# curlで確認
curl -I https://example.com/path
🔍 チェックポイント: X-Forwarded-Protoが正しくhttpsになっているか確認する
ステップ5: 正しい条件式に修正する
ロードバランサー配下の場合の推奨設定:
# X-Forwarded-Protoを考慮したHTTPSリダイレクト
server {
listen 80;
server_name example.com;
# LB配下ではX-Forwarded-Protoを確認
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
# LBを使わない環境用
if ($scheme = "http") {
return 301 https://$host$request_uri;
}
}
🔍 チェックポイント: 設定変更後、nginx -tでシンタックスエラーがないことを確認する
ステップ6: 設定をリロードして動作確認する
# 設定テスト
sudo nginx -t
# リロード
sudo systemctl reload nginx
# 動作確認
curl -I -L --max-redirs 5 https://example.com/path
🔍 チェックポイント: リダイレクトが1回で終了し、最終的に200が返ることを確認する
NG行動(やってはいけないこと)
- ブラウザだけでテストする - キャッシュされた301リダイレクトが残り、正確な確認ができない
- rewriteルールを追加して回避しようとする - ルールが複雑化し、問題の特定が困難になる
- nginx -tを実行せずにreloadする - シンタックスエラーでnginxが停止するリスクがある
- 本番環境で直接設定を変更する - 検証環境で動作確認してから本番に適用する
- 設定変更前のバックアップを取らない - 切り戻しができなくなる
よくある質問(FAQ)
Q1: ブラウザで301リダイレクトがキャッシュされてしまった場合は?
A: ブラウザのキャッシュをクリアするか、シークレットモードでアクセスする。またはcurl -Iでサーバー側の動作を確認する
Q2: CloudflareなどのCDN配下でリダイレクトループが発生する場合は?
A: CDN側のSSL/TLS設定を「Full」または「Full (Strict)」に変更する。「Flexible」だとオリジンへの接続がHTTPになりループの原因となる
Q3: 特定のパスだけでリダイレクトループが発生する場合は?
A: locationブロックの優先順位を確認する。正規表現を使ったlocationブロックが意図しないパスにマッチしている可能性がある
関連するエラー・症状
- (関連記事準備中)
- (関連記事準備中)
- (関連記事準備中)
解決しない場合
- nginx公式ドキュメント - rewriteモジュール
- 確認すべきログ:
/var/log/nginx/error.log,/var/log/nginx/access.log - 次に調べるキーワード:
nginx rewrite flag last break,nginx location priority,nginx proxy_set_header X-Forwarded-Proto