2026年6月6日
2026年6月6日
Caddy を WordPress の前に置くリバースプロキシ構成|実 IP・HTTPS 判定・リダイレクトループの対処
Caddy を WordPress のリバースプロキシとして使う(Caddy が HTTPS を受け、後ろの Apache や Nginx + PHP で動く WordPress へ HTTP で転送する)構成では、WordPress 側に「自分は HTTPS で公開されている」と教える設定が要ります。これを入れないと、ログイン画面がリダイレクトを繰り返す、画像や CSS が http:// で読まれて混在コンテンツになる、コメントやログイン試行の IP がすべて Caddy の IP になる、という 3 つの問題が起きます。
結論を先にまとめます。
- Caddy は既定で
X-Forwarded-ProtoとX-Forwarded-Forを付けて転送します。Caddy 側で特別な設定は要りません。 - WordPress 側の
wp-config.phpでHTTP_X_FORWARDED_PROTOを見て$_SERVER['HTTPS']をonにします(WordPress 公式の推奨手順)。 - サイト URL は
https://でWP_HOMEとWP_SITEURLに固定します。 - 実 IP が必要なら、後ろの Web サーバー(Apache の
mod_remoteip、Nginx のreal_ip_header)でX-Forwarded-Forから復元します。WordPress の中でREMOTE_ADDRを書き換える方法は最後の手段です。 - 1 台で完結するなら、プロキシではなく Caddy の
php_fastcgiで直接 PHP-FPM につなぐ構成のほうが問題が起きにくいです。
Caddy のリバースプロキシそのものの書き方(reverse_proxy、自動 HTTPS の条件、header_up、確認方法)は「Caddy でリバースプロキシを設定する方法」にまとめています。この記事はその続きで、WordPress 固有の問題だけを扱います。
2 つの構成の違い
| 構成 | 仕組み | 利点 | 起きやすい問題 |
|---|---|---|---|
| 直接構成 | Caddy → PHP-FPM(php_fastcgi) |
設定が少ない。WordPress は HTTPS を正しく認識する | テーマやプラグインが .htaccess に依存していると書き換えが要る |
| プロキシ構成 | Caddy → Apache / Nginx → PHP | 既存サーバーを残せる。複数サイトの入口を 1 つにできる | HTTPS 判定、実 IP、リダイレクトループ |
新しく WordPress を立てるなら直接構成が簡単です。Caddy 公式の Caddyfile のパターン集にも WordPress 向けの例があり、xmlrpc.php や wp-content/uploads 内の PHP を止める書き方が示されています。
example.com {
root * /var/www/wordpress
encode
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
@blocked path /xmlrpc.php *.sql /wp-content/uploads/*.php
rewrite @blocked /index.php
}
以下は、既存の Apache や Nginx を残してプロキシ構成にする場合の手順です。
手順 1: Caddy 側の設定を確認する
Caddyfile は最小構成で足ります。Caddy は転送時にクライアントの IP を X-Forwarded-For に追加し、X-Forwarded-Proto(https)と X-Forwarded-Host を設定します(reverse_proxy の公式ドキュメント)。Host ヘッダーはそのまま渡されるため、後ろの Web サーバーのバーチャルホストはそのまま一致します。
example.com {
reverse_proxy 127.0.0.1:8080
}
後ろの Web サーバーが同じホストの 8080 番で HTTP を待ち受けている前提です。Caddy の前に CDN(Cloudflare など)があるときは、グローバルオプションで servers { trusted_proxies static <CDN の IP 範囲> } を書かないと、X-Forwarded-For に入るのは CDN の IP になります。
手順 2: WordPress に HTTPS だと教える
WordPress は $_SERVER['HTTPS'] を見て自分が HTTPS かどうかを判断します。プロキシ構成では後ろのサーバーは HTTP で受けるので、この値が空になり、FORCE_SSL_ADMIN やサイト URL の https:// との間で転送が無限に続きます。WordPress 公式の Administration Over SSL が示す対処は、X-Forwarded-Proto を見て HTTPS を補うことです。
wp-config.php の /* That's all, stop editing! */ より前に追記します。
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) {
$_SERVER['HTTPS'] = 'on';
}
define( 'FORCE_SSL_ADMIN', true );
X-Forwarded-Proto がカンマ区切りで複数入る環境があるため、公式の例と同じく strpos で https を含むかどうかを見ています。
この設定は「転送ヘッダーを信頼する」設定です。後ろの Web サーバーが Caddy 以外からも直接アクセスできる状態だと、外部から X-Forwarded-Proto: https を付けたリクエストで偽装できます。後ろのサーバーは 127.0.0.1 だけで待ち受けるか、ファイアウォールで Caddy からの接続だけを許可してください。
手順 3: サイト URL を https で固定する
管理画面の「設定 → 一般」の WordPress アドレスとサイトアドレスを https://example.com にします。管理画面に入れない状態なら、wp-config.php で固定します。
define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );
既存の記事本文や画像の URL が http:// のままだと混在コンテンツになります。WP-CLI の wp search-replace 'http://example.com' 'https://example.com' --dry-run で件数を確認してから置き換えます(実行前にデータベースのバックアップを取ります。手順は「WordPress のデータベースを手動でバックアップする方法」)。
手順 4: 実 IP を復元する
プロキシ構成では、後ろのサーバーから見たアクセス元はすべて Caddy の IP です。そのままだと、コメントの投稿者 IP、ログイン試行の制限、Wordfence などのセキュリティプラグインの IP 判定が働きません。復元は Web サーバー側で行うのが基本です。
Apache(mod_remoteip):
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
Nginx(ngx_http_realip_module):
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from と RemoteIPTrustedProxy には Caddy の IP だけを書きます。これで REMOTE_ADDR が実 IP になり、WordPress 側の変更は要りません。Web サーバーの設定を変えられない場合に限り、wp-config.php で X-Forwarded-For の先頭を REMOTE_ADDR に入れる方法もありますが、ヘッダーが偽装できる環境では使わないでください。
手順 5: 確認する
# 転送が 1 回で止まるか(301 や 302 が繰り返されていないか)
curl -sIL https://example.com/wp-login.php | grep -i -E "^HTTP|^location"
# 管理画面の URL が https で返るか
curl -s https://example.com/wp-json/ | head -c 300
# 混在コンテンツの有無(http:// の参照)
curl -s https://example.com/ | grep -o 'http://example.com[^"]*' | head
ブラウザーの開発者ツールでもコンソールに Mixed Content の警告が出ていないかを見ます。実 IP は、テスト用のコメントを投稿して管理画面のコメント一覧の IP が自分の IP になっていれば復元できています。
WordPress の観点
このサイトに寄せられる相談で多いのは、「サーバー移転や HTTPS 化のあとでログイン画面が開かない(リダイレクトが繰り返される)」というものです。原因の多くはこの記事の手順 2 と 3 で、wp-config.php の数行で直ります。管理画面に入れない状態での作業になるため、FTP や SSH で wp-config.php を編集できるかどうかを先に確認してください。自分で直すか頼むかの判断は「WordPress の不具合を頼むか自分で直すかの判断基準」を参考にしてください。
よくある質問
Caddy の後ろの WordPress でログインがループします
後ろのサーバーが HTTP で受けているのに、サイト URL が https:// か FORCE_SSL_ADMIN が有効になっている状態です。wp-config.php に HTTP_X_FORWARDED_PROTO を見て $_SERVER['HTTPS'] = 'on' にする記述を入れます。Caddy は既定でこのヘッダーを付けるので、Caddy 側の変更は要りません。
Caddy でヘッダーを付け足す必要はありますか
X-Forwarded-For、X-Forwarded-Proto、X-Forwarded-Host は既定で付きます。X-Real-IP を期待する設定が後ろにあるときだけ header_up X-Real-IP {remote_host} を足します。
プロキシ構成と直接構成のどちらにすべきですか
1 台で完結し、.htaccess に依存するプラグインが無ければ、php_fastcgi の直接構成が簡単で、この記事の問題は起きません。既存の Apache や Nginx を残す理由(他のサイトが同居している、.htaccess の設定が多い)があるときにプロキシ構成を選びます。
Cloudflare と Caddy の両方を通すと IP はどうなりますか
Cloudflare → Caddy → Web サーバーの順に通るので、Caddy に trusted_proxies で Cloudflare の IP 範囲を信頼させないと、X-Forwarded-For に入るのは Cloudflare の IP です。Cloudflare 側の設定は「WordPress に Cloudflare を設定する方法」を参照してください。
まとめ
- Caddy のリバースプロキシの後ろに WordPress を置くときは、
wp-config.phpでHTTP_X_FORWARDED_PROTOを見てHTTPSをonにし、WP_HOME/WP_SITEURLをhttps://で固定します。 - 実 IP は Apache の
mod_remoteipか Nginx のreal_ip_headerで復元し、信頼するプロキシは Caddy の IP だけにします。 - 1 台で済むなら
php_fastcgiの直接構成を選ぶと、これらの問題は起きません。
関連記事
- Caddy でリバースプロキシを設定する方法|Caddyfile の reverse_proxy・自動 HTTPS・ヘッダー・確認手順
- WordPress に Cloudflare を設定する方法
- WordPress のデータベースを手動でバックアップする方法
- WordPress の不具合を頼むか自分で直すかの判断基準
参考: WordPress Developer Resources – Administration Over SSL(Using a Reverse Proxy)、Caddy – reverse_proxy、Caddy – Common Caddyfile Patterns
更新履歴: 2026-11-09 全面改訂(定型文を、Caddy の後ろで WordPress を動かすときの HTTPS 判定・実 IP・リダイレクトループの対処に書き換え、php_fastcgi の直接構成との使い分けを追加)。この記事はワードプレス博士(ライトセンド株式会社)が運営しています。