2026年11月9日
2026年11月9日
NginxでのHTTPSリダイレクトループ修正
はじめに
NginxでHTTPS化を行ったあとに「リダイレクトが多すぎます(ERR_TOO_MANY_REDIRECTS)」というエラーで表示できなくなるトラブルは、特にCloudflare・AWS ALB・ロードバランサ配下でNginxを動かしている構成で頻発します。ほぼ全ての原因は「Nginxが受信したリクエストをHTTPだと判定し続け、httpsへ無限に301を返し続ける」点にあります。
本記事では、Nginxの return 301 / rewrite を使ったHTTP→HTTPSリダイレクトの典型的な書き方とそのループ要因、フロントプロキシの X-Forwarded-Proto ヘッダを正しく扱うための設定例を紹介します。
map ディレクティブを使った条件分岐や、WordPressアプリ側で必要な追加対応もまとめています。
症状・背景
- Cloudflare経由で「リダイレクトが多すぎます」が出る
curl -ILでLocationが何度も繰り返される- AWS ALB配下のNginxでログイン後にループする
- 単独Nginxでは正常だがALB/CloudFront経由でループする
手順・設定方法
ステップ1: 状況を可視化
リダイレクトの連鎖を確認します。
# リダイレクトを最大10回まで追跡
curl -sIL --max-redirs 10 https://example.com/ | grep -E '^(HTTP|Location)'
# Nginxアクセスログをリアルタイム監視
sudo tail -f /var/log/nginx/access.log
# X-Forwarded-Protoが届いているか確認用に変数を出力
curl -sv https://example.com/ 2>&1 | head -n 30
ステップ2: X-Forwarded-Protoを判定する設定に修正
$scheme ではなく $http_x_forwarded_proto を見るようにします。
# 悪い例: 必ずループする
# server {
# listen 80;
# return 301 https://$host$request_uri; # ALB経由だと到達しない
# }
# 良い例: map で実効スキームを判定
sudo tee /etc/nginx/conf.d/real-scheme.conf > /dev/null <<'EOF'
map $http_x_forwarded_proto $real_scheme {
default $scheme;
https https;
}
EOF
# 構文チェック
sudo nginx -t
ステップ3: リダイレクト処理を書き換える
ループしないHTTP→HTTPS転送を設定します。
# /etc/nginx/sites-available/example.com
sudo tee /etc/nginx/sites-available/example.com > /dev/null <<'EOF'
server {
listen 80;
server_name example.com;
# 既にhttpsで届いていればリダイレクトしない
if ($real_scheme != "https") {
return 301 https://$host$request_uri;
}
root /var/www/html;
index index.php index.html;
}
EOF
sudo ln -sf /etc/nginx/sites-available/example.com \
/etc/nginx/sites-enabled/example.com
sudo systemctl reload nginx
ステップ4: アップストリームへの転送設定とWordPress対応
FastCGI/proxy_pass で正しいスキームを渡します。
# fastcgi_params に追記してPHPに正しい値を渡す
sudo tee -a /etc/nginx/fastcgi_params > /dev/null <<'EOF'
fastcgi_param HTTPS $real_scheme;
fastcgi_param HTTP_X_FORWARDED_PROTO $real_scheme;
EOF
# WordPressのwp-config.php側の補助
sudo tee -a /var/www/html/wp-config.php > /dev/null <<'EOF'
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
EOF
sudo systemctl reload nginx
注意事項
- Cloudflareの「Flexible SSL」モードはオリジン通信がHTTPになるため、Nginx側でHTTPSへリダイレクトすると必ずループします。最低限「Full」モードを使ってください
set_real_ip_fromで信頼するプロキシIPを指定しないと、不正なヘッダで偽装される恐れがあります- WordPressの
siteurl/homeが http のままだとページ内の内部リンクでループします - AWS ALB配下では
listen 80 proxy_protocolが必要なケースもあります(target groupで設定)
まとめ
1. 可視化が最初: curl -sIL で何回ループしているか測る
2. $schemeを信用しない: プロキシ配下では $http_x_forwarded_proto を見る
3. mapで真のスキーム: map $http_x_forwarded_proto $real_scheme パターンが鉄板
4. fastcgi_paramも更新: PHPに正しい HTTPS を渡さないとアプリ側もループ要因に
5. CloudflareはFull以上: Flexibleは絶対に使わない
関連記事: