2026年5月22日
2026年5月22日
WordPressでNginxのプロキシキャッシュを設定する方法|ログイン中・管理画面を除外する設定例
Nginx のプロキシキャッシュ(proxy_cache)を使うと、Nginx の後ろで動いている WordPress(Apache や別のアプリケーションサーバー)が作ったページを Nginx が保存し、次の訪問者には保存したページを返せます。PHP とデータベースの処理が減るので、アクセスが多いサイトでサーバーの負担を下げられます。
この記事では、Nginx をリバースプロキシにして、ポート 8080 の Apache で動く WordPress の前に置く構成を例に、プロキシキャッシュの設定を説明します。設定は 2026年10月時点の Nginx 1.30(stable)で nginx -t による構文チェックと、キャッシュの HIT・BYPASS の動きを確認しています。
なお、Nginx から PHP-FPM を直接呼んでいる構成(fastcgi_pass を使う構成)では、プロキシキャッシュではなく fastcgi_cache を使います。考え方は同じですが、ディレクティブの名前が fastcgi_cache_path・fastcgi_cache_key のように変わります。
構成と前提
| 役割 | 待ち受け | 内容 |
|---|---|---|
| Nginx | 80(必要なら 443) | 訪問者からの接続を受け、キャッシュがあれば返す。なければ Apache に転送する |
| Apache + PHP(WordPress) | 127.0.0.1:8080 | WordPress のページを作る |
Nginx のプロキシ機能(ngx_http_proxy_module)は、標準でビルドに含まれています。ディストリビューションのパッケージや nginx.org のパッケージを使っていれば、Nginx を作り直す必要はありません(旧版の記事にあった --with-http_proxy_module という configure オプションはありません。外す場合のオプション --without-http_proxy_module があるだけです)。
ステップ1: Apacheを127.0.0.1:8080で待ち受けるようにする
Debian / Ubuntu の Apache では、/etc/apache2/ports.conf の Listen を変えます。
# /etc/apache2/ports.conf
Listen 127.0.0.1:8080
サイトの設定(例: /etc/apache2/sites-available/000-default.conf)の VirtualHost も合わせます。
<VirtualHost 127.0.0.1:8080>
ServerName example.com
DocumentRoot /var/www/html
</VirtualHost>
Apache のアクセスログに訪問者の IP アドレスを残したい場合は、mod_remoteip を有効にし、Nginx が送る X-Forwarded-For を読むようにします。
# /etc/apache2/conf-available/remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1
sudo a2enmod remoteip
sudo a2enconf remoteip
sudo apache2ctl -t && sudo systemctl restart apache2
ステップ2: Nginxにプロキシキャッシュを設定する
次の内容で、Nginx の設定ファイル(例: /etc/nginx/conf.d/wp-proxy-cache.conf)を作ります。Debian / Ubuntu のパッケージでも nginx.org のパッケージでも、/etc/nginx/conf.d/*.conf は http ブロックの中で読み込まれるので、proxy_cache_path や map をこのファイルに書けます。
# キャッシュの保存場所と大きさ
proxy_cache_path /var/cache/nginx/wp levels=1:2 keys_zone=wpcache:10m
max_size=1g inactive=60m use_temp_path=off;
# ログイン中・パスワード保護ページ閲覧中・コメント投稿者・カートに商品がある人はキャッシュしない
map $http_cookie $wp_skip_cookie {
default 0;
~*wordpress_logged_in_ 1;
~*wp-postpass_ 1;
~*comment_author_ 1;
~*woocommerce_items_in_cart 1;
}
# 管理画面・ログイン・WP-Cron・XML-RPC・REST API・プレビューはキャッシュしない
map $request_uri $wp_skip_uri {
default 0;
~*^/wp-admin/ 1;
~*^/wp-login\.php 1;
~*^/wp-cron\.php 1;
~*^/xmlrpc\.php 1;
~*^/wp-json/ 1;
~*preview=true 1;
}
server {
listen 80;
server_name example.com;
set $skip_cache 0;
if ($request_method = POST) { set $skip_cache 1; }
if ($wp_skip_cookie) { set $skip_cache 1; }
if ($wp_skip_uri) { set $skip_cache 1; }
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache wpcache;
proxy_cache_key $scheme$request_method$host$request_uri;
proxy_cache_valid 200 301 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status always;
}
}
主なディレクティブの意味
| ディレクティブ | 意味 |
|---|---|
proxy_cache_path |
キャッシュを置くフォルダーと設定。keys_zone=wpcache:10m はキャッシュの索引を置く共有メモリの名前と大きさ(Nginx の公式ドキュメントでは 1MB で約8千件)、max_size はディスク上の上限、inactive=60m は60分間使われなかったキャッシュを削除する指定、use_temp_path=off は一時ファイルを経由せずキャッシュのフォルダーに直接書く指定 |
proxy_cache |
使うキャッシュの名前(keys_zone で付けた名前) |
proxy_cache_key |
キャッシュを見分けるキー。既定値は $scheme$proxy_host$request_uri で、proxy_pass 先が同じだと複数のドメインが混ざるおそれがあるため、$host を入れている |
proxy_cache_valid |
ステータスコードごとの保存期間。ここでは 200・301・302 を10分、404 を1分 |
proxy_cache_bypass |
値が空でも 0 でもないとき、キャッシュを使わず Apache に転送する |
proxy_no_cache |
値が空でも 0 でもないとき、Apache からの応答をキャッシュに保存しない |
proxy_cache_use_stale |
Apache がエラーや応答なしのとき、期限切れのキャッシュを返す |
proxy_cache_background_update |
期限切れのキャッシュを返しながら、裏で新しいページを取りに行く(proxy_cache_use_stale に updating が必要) |
proxy_cache_lock |
同じページへの同時アクセスで、Apache への問い合わせを1つにまとめる |
proxy_cache_bypass と proxy_no_cache は両方指定します。proxy_cache_bypass だけだと、ログイン中のユーザーに作られたページがキャッシュに保存され、ほかの訪問者に表示されるおそれがあります。
また、Nginx は初期設定で、Set-Cookie ヘッダーが付いた応答や、Cache-Control: private・no-cache・no-store が付いた応答を保存しません。WordPress がログイン時などに送る Cookie 付きの応答は、この仕組みでも保存されません。キャッシュの対象になるリクエストの方法も、初期設定では GET と HEAD だけです。
ステップ3: 構文チェックと反映
キャッシュの親フォルダーがなければ作ってから、構文をチェックして反映します。Nginx は起動時に /var/cache/nginx/wp を作り、ワーカーのユーザーに所有者を変えます。
sudo mkdir -p /var/cache/nginx
sudo nginx -t
sudo systemctl reload nginx
nginx -t で syntax is ok と test is successful が出ることを確認してから reload します。
ステップ4: キャッシュが効いているか確認する
X-Cache-Status ヘッダーで、キャッシュの状態を確認できます。同じ URL に2回アクセスすると、1回目は MISS、2回目は HIT になります。
curl -s -o /dev/null -D - https://example.com/sample-page/ | grep -i x-cache-status
curl -s -o /dev/null -D - https://example.com/sample-page/ | grep -i x-cache-status
ログイン中の Cookie を付けたリクエストや、/wp-admin/ へのリクエストは BYPASS になります。
curl -s -o /dev/null -D - -H 'Cookie: wordpress_logged_in_test=1' https://example.com/sample-page/ | grep -i x-cache-status
$upstream_cache_status の主な値は次のとおりです。
| 値 | 意味 |
|---|---|
MISS |
キャッシュがなく、Apache から取得した |
HIT |
キャッシュから返した |
BYPASS |
proxy_cache_bypass の条件に当たり、キャッシュを使わなかった |
EXPIRED |
キャッシュの期限が切れていたため、Apache から取得した |
STALE |
proxy_cache_use_stale により、期限切れのキャッシュを返した |
UPDATING |
更新中のため、期限切れのキャッシュを返した |
Cookie を付けていないのに何度アクセスしても MISS のままのときは、WordPress のテーマやプラグインが Set-Cookie や Cache-Control: no-cache を送っている可能性があります。curl -I http://127.0.0.1:8080/ -H 'Host: example.com' で Apache の応答ヘッダーを直接確認してください。
X-Cache-Status ヘッダーは確認用です。外部に見せたくない場合は、確認が終わったら add_header の行を消します。
キャッシュを削除する
記事を更新しても、キャッシュの保存期間(この例では10分)が過ぎるまでは古いページが表示されます。無料版の Nginx には、特定の URL のキャッシュを消す proxy_cache_purge ディレクティブがありません(商用版の NGINX Plus の機能です)。
すぐに反映したい場合は、キャッシュのフォルダーの中身を削除します。削除した後のアクセスは MISS になり、新しいページが保存されます。
sudo find /var/cache/nginx/wp -type f -delete
更新をすぐに反映したいページが多い場合は、proxy_cache_valid の時間を短くする、またはキャッシュ削除に対応したサードパーティー製モジュールを組み込む方法があります。
HTTPSをNginxで終端する場合
Nginx で HTTPS を受け、Apache には HTTP で転送する構成では、WordPress が「HTTP で表示されている」と判断し、管理画面へのリダイレクトが繰り返されることがあります。WordPress の公式ドキュメント(Administration Over SSL)にあるとおり、wp-config.php の /* That's all, stop editing! */ より前に次の設定を書きます。
<?php
// Nginx で HTTPS を終端し、バックエンドへ HTTP で渡している場合
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
(wp-config.php にはすでに <?php があるので、追記するのは2行目以降です。)Nginx の設定には、ステップ2のとおり proxy_set_header X-Forwarded-Proto $scheme; が必要です。
注意点
- キャッシュを入れると、ページの表示ごとに動く処理(アクセス数のカウント、表示のたびに変わる内容など)は、キャッシュの保存期間の間は動かなくなります。会員サイトやネットショップでは、ログインや購入の流れで使う URL と Cookie をすべて除外条件に入れてから使ってください
- WordPress のキャッシュ系プラグインと同時に使うと、どちらのキャッシュが表示されているか分かりにくくなります。どちらか一方にし、
X-Cache-Statusで動きを確認します - Apache の 8080 番ポートは
127.0.0.1だけで待ち受け、外部から直接アクセスされないようにします - 設定を変えたら、
nginx -tで構文を確かめてからreloadします
まとめ
- Nginx の
proxy_cacheで、Apache などで動く WordPress のページを Nginx に保存して返せる - ログイン中の Cookie、管理画面・ログイン・REST API などの URL、POST を
proxy_cache_bypassとproxy_no_cacheの両方で除外する X-Cache-StatusヘッダーでMISS・HIT・BYPASSを確認する- 無料版の Nginx では、キャッシュの削除はフォルダーの中身を消すか、保存期間を短くして対応する
- HTTPS を Nginx で終端する場合は、
wp-config.phpでX-Forwarded-Protoを見て$_SERVER['HTTPS']を設定する
関連記事: