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は絶対に使わない

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲