2026年5月25日
2026年5月25日
WordPressのCloudFront設定:キャッシュ動作(ビヘイビア)とカスタムオリジンの組み立て方
WordPressの前にAmazon CloudFrontを置くときの要点は、「どのURLをキャッシュし、どのURLを素通しにするか」をキャッシュ動作(ビヘイビア)で分けることと、EC2やALBなどのカスタムオリジンに正しいHostヘッダーとHTTPS情報を届けることの2つです。この記事では、WordPress向けのビヘイビア構成、キャッシュポリシーとオリジンリクエストポリシーの選び方、ログイン中のページが他人に表示される事故を防ぐ設定、オリジンへの直接アクセスを閉じる方法を順に説明します。
CloudFrontの画面構成やマネージドポリシーの種類は更新されることがあり、この記事はその時点の構成で説明しています(2026年10月現在)。設定を変える前にWordPressのバックアップを取り、本番ドメインに切り替える前にCloudFrontのドメイン(xxxx.cloudfront.net)や検証用のサブドメインで動作を確認してください。
全体の構成を決める
典型的な構成は次のとおりです。
- 利用者 → CloudFront(
www.example.com)→ カスタムオリジン(EC2、ALB、または他社のサーバー) - 静的ファイル(
/wp-content/、/wp-includes/)は長くキャッシュ - 管理画面・ログイン・REST APIはキャッシュしない
- 一般の記事ページは短くキャッシュし、ログイン中の利用者には返さない
S3をオリジンにするのは静的ファイルを配信する場合で、PHPが動くWordPress本体はカスタムオリジン(S3以外のHTTPサーバー)として登録します。
カスタムオリジンの設定
オリジンを作成するときに見直す項目は次のとおりです。
- オリジンドメイン:ALBのDNS名や、
origin.example.comのようなオリジン専用のホスト名を指定します。 - プロトコル:「HTTPSのみ」にします。CloudFrontとオリジン間も暗号化され、WordPress側のHTTPS判定も素直になります。オリジンの証明書は、オリジンドメイン名(Hostヘッダーを転送する場合はそのHost名)と一致している必要があります。
- 最小のオリジンSSLプロトコル:TLSv1.2を選びます。
- 応答タイムアウト:既定値のままだと、管理画面での重い処理(プラグイン更新、大きなインポートなど)が途中で504になることがあります。必要に応じて延ばすか、重い作業はオリジンに直接つないだ経路で行います。
- カスタムヘッダー:
X-Origin-Verify: your-random-secretのような推測されにくいヘッダーを追加し、オリジン側でこのヘッダーがないリクエストを拒否すると、CloudFrontを経由しない直接アクセスを防げます(秘密の値は例です。自分で生成した値を使ってください)。
Hostヘッダーの扱い
WordPressは siteurl と home に設定したドメインでリンクやリダイレクトを生成します。オリジンにHostヘッダー www.example.com が届かないと、オリジン専用のホスト名へリダイレクトされたり、リンクがそちらのドメインになったりします。そのため、HTMLを返すビヘイビアでは、オリジンリクエストポリシーでビューワーのHostヘッダーを転送します(マネージドポリシーの「AllViewer」はHostを含むすべてのヘッダー・Cookie・クエリ文字列を転送します)。
逆にALBなど、オリジンの証明書がオリジンのホスト名でしか発行されていない場合は、Hostを転送すると証明書の名前が合わなくなります。この場合は、オリジン側にも www.example.com の証明書を用意するのが一般的です。
HTTPS判定と送信元IP
オリジンへの接続をHTTPSのみにしていれば、通常WordPressはHTTPSを認識できます。ALBでTLSを終端してEC2へHTTPで流している場合は、X-Forwarded-Proto を見てHTTPSと判定する処理を wp-config.php に追加します。
// wp-config.php(「編集が必要なのはここまで」の行より前)
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
$_SERVER['HTTPS'] = 'on';
}
利用者のIPアドレスは X-Forwarded-For に入ります。これらのヘッダーは偽装できるため、後述の方法でオリジンへの直接アクセスを閉じておくことが前提です。
キャッシュ動作(ビヘイビア)の構成
ビヘイビアはパスパターンごとに設定し、一覧の上から順に照合されます。最後のデフォルト(*)はどのパターンにも一致しなかったリクエストに使われます。WordPressでは次のような構成が基本になります。
| パスパターン | キャッシュポリシー | オリジンリクエストポリシー | 許可するメソッド |
|---|---|---|---|
/wp-admin/* |
CachingDisabled | AllViewer | すべて |
/wp-login.php |
CachingDisabled | AllViewer | すべて |
/wp-json/* |
CachingDisabled | AllViewer | すべて |
/wp-content/* |
静的ファイル用(自作) | なし | GET, HEAD |
/wp-includes/* |
静的ファイル用(自作) | なし | GET, HEAD |
デフォルト(*) |
HTML用(自作) | AllViewer | すべて |
/wp-admin/admin-ajax.php はフロント側の機能(検索の候補表示やフォームなど)からも呼ばれますが、/wp-admin/* のビヘイビアに含まれるのでキャッシュされません。コメント投稿(wp-comments-post.php)のPOSTは、デフォルトのビヘイビアでPOSTを許可しておけばオリジンに届きます。
静的ファイル用のキャッシュポリシー
マネージドポリシーの「CachingOptimized」は、クエリ文字列をキャッシュキーに含めません。WordPressはCSSやJavaScriptに ?ver=6.x のようなバージョン番号を付けて更新を反映させるので、クエリ文字列を無視すると、テーマやプラグインを更新しても古いファイルが配信され続けます。静的ファイル用には、次のような内容のキャッシュポリシーを自作すると安全です。
- TTL:最小0秒、既定は1日程度、最大1年程度
- クエリ文字列:
verを含める(または、すべて含める) - ヘッダー・Cookie:含めない
- Gzip・Brotliの圧縮:有効
オリジンリクエストポリシーを付けない場合、オリジンにはHostとしてオリジンドメイン名が届きます。Webサーバーのバーチャルホストがそのホスト名でも同じドキュメントルートを返すように設定しておくか、静的ファイル用にもHostを転送するポリシーを付けてください。
HTML用のキャッシュポリシーとログイン中の利用者
記事ページをキャッシュするときに最も注意すべきなのは、ログイン中の利用者やパスワード保護ページを閲覧した人の画面が、他の人にキャッシュとして返される事故です。これを防ぐには、WordPressのログインCookieをキャッシュキーに含め、同時にオリジンがそれらのリクエストに「キャッシュしない」ヘッダーを返すようにします。
WordPressのCookie名には、サイトURLから計算されるハッシュ(COOKIEHASH)が付きます。ブラウザの開発者ツールでログイン後のCookieを確認し、次の3つの正確な名前をキャッシュポリシーの「含めるCookie」に指定します。
wordpress_logged_in_(ハッシュ):ログイン状態comment_author_(ハッシュ):コメント投稿者の情報wp-postpass_(ハッシュ):パスワード保護ページの閲覧
TTLは最小0秒・既定0秒・最大1日程度とし、キャッシュする時間はオリジンが返す Cache-Control で決める形にします。CloudFrontは s-maxage があれば max-age より優先して使うため、ブラウザにはキャッシュさせずCloudFrontだけに数分キャッシュさせる、といった指定ができます。オリジン側の例として、テーマを直接編集せずmu-pluginに置くコードを示します。
<?php
// wp-content/mu-plugins/cdn-cache-headers.php
add_action( 'template_redirect', function () {
if ( is_user_logged_in() || is_preview() || is_search() || is_404()
|| ( is_singular() && post_password_required() ) ) {
nocache_headers();
return;
}
// ブラウザは毎回確認、CloudFrontには5分キャッシュさせる
header( 'Cache-Control: public, max-age=0, s-maxage=300' );
} );
キャッシュ系プラグインやサーバー側の設定が別の Cache-Control を出していると重複するので、導入後に curl -I https://www.example.com/ でヘッダーを確認してください。ECサイト(WooCommerceなど)では、カートやマイアカウント、決済のページを別のビヘイビアでキャッシュ無効にするなど、さらに個別の設計が必要です。
オリジンへの直接アクセスを閉じる
CloudFrontを経由しない直接アクセスが残っていると、キャッシュやWAFを迂回され、ヘッダーの偽装も可能になります。代表的な閉じ方は次のとおりです。
- セキュリティグループ:EC2やALBのセキュリティグループで、AWSが提供するCloudFront用のマネージドプレフィックスリスト(
com.amazonaws.global.cloudfront.origin-facing)からのHTTPSだけを許可します。 - カスタムヘッダーの検証:前述の
X-Origin-VerifyをALBのリスナールールやWebサーバーで検証し、一致しないリクエストを拒否します。 - VPCオリジン:オリジンをパブリックに公開せず、CloudFrontからプライベートサブネット内のALBやEC2に接続する方式もあります。対応するリソースの種類やリージョンは公式ドキュメントで確認してください。
記事を更新したときのキャッシュ削除
HTMLを数分しかキャッシュしない設計なら、更新は短時間で反映されます。すぐに反映したい場合はキャッシュの無効化(Invalidation)を実行します。
# 特定のURLを無効化(ディストリビューションIDは例)
aws cloudfront create-invalidation \
--distribution-id E1234567890ABC \
--paths "/sample-post/" "/"
無効化は一定のパス数までは無料で、それを超えると料金がかかります。投稿の公開や更新に合わせて自動で無効化するプラグイン(C3 Cloudfront Cache Controllerなど)もありますが、更新状況と対応バージョンを確認してから使ってください。
まとめ
- WordPress本体はカスタムオリジンとして登録し、プロトコルはHTTPSのみ、必要に応じてカスタムヘッダーで経由元を確認します。
- 管理画面・ログイン・REST APIはキャッシュ無効のビヘイビアに分け、AllViewerでHostやCookieを転送します。
- 静的ファイルは長くキャッシュしますが、
verクエリ文字列をキャッシュキーに含めます。 - HTMLはログイン系のCookieをキャッシュキーに含め、オリジンの
Cache-Control(s-maxage)でキャッシュ時間を制御します。 - セキュリティグループのプレフィックスリストなどで、オリジンへの直接アクセスを閉じます。