CloudFront + WordPress 構成の必須設定
概要
はじめに
- 本日は、AWS CloudFront + WordPress 構成を構築する上でハマった落とし穴をいくつかご紹介します。CloudFront + WordPress 構成を採用される方は、参考にして下さい。
システム構成
- Amazon Lightsailに、WordPress環境を起動しています。WordPressのバージョンは、5.6です。WordPressのフロントにCloudFrontを設置し、CloudFrontでSSLの終端を行っています。
- なお、今回ご紹介する落とし穴は、通常のWordPress環境およびWordPress Multisite環境の両方で発生することを確認しております。
siteurl がオリジン側のURLを向いてしまう
説明
- Amazon LightsailにWordPressのインスタンスを起動し、CloudFront のオリジンに設定してディストリビューションを作成、CNAME設定を行います。以下の通り、CNAMEに設定したCDN側 URL にてアクセスが可能になりました。
- しかし、CDN側 URLでアクセスできたのはトップページのみで、画面を遷移するとオリジン側URL を向いてしまいます。
- これは、CloudFrontをWordPressのフロントに配置した構成における特有の症状です。WordPressのwp-config.php(/opt/bitnami/apps/wordpress/htdocs/wp-config.php)に下記のエントリがあり、siteurl がオリジン側 URLに変わります。
- 理由は、CloudFrontのデフォルトのキャッシュ動作設定では、CloudFrontがHOSTヘッダを置き換えるために起こります。
define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/');
define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] . '/');
- また、WordPressの管理画面からも Site Address がオリジン側 URL となっていることが分かります。
- 一方、CloudFrontのキャッシュ動作の設定がデフォルトであり、かつwp-config.php に以下のようにダイレクトにCDN側 URLを記載している場合は、WordPressのホスト名(siteurl)とリクエストされたHOSTヘッダが一致せず、"403 Forbidden“のエラーで管理画面にアクセスができなくなります。
define('WP_HOME','http://niikawa-wp.example.net');
define('WP_SITEURL','http://niikawa-wp.example.net');
対処方法
- WordPressの動作にはドメイン名(siteurl)が必要となります。しかし、CloudFront のキャッシュ動作において、CloudFrontはリクエストのHOSTヘッダをオリジンのドメイン名に置き換えるため、期待通りにアクセスができません。
- 対策は、CloudFrontのキャッシュ動作の設定を変更します。Cache Based on Selected Request Headers(選択されたリクエストヘッダーに基づいたキャッシュ)の設定を “Whitelist"に変更し、Whitelist Headersに"Host"を追加します。あるいは、"All" に変更を行います。
デフォルトのキャッシュ設定はWordPressの管理画面を使用できない
説明
- WordPressの管理画面が正しく機能せず、Cookieのエラーでログインができなかったり、コンテンツのサイト表示が崩れたりします。これは、CloudFrontをWordPressのフロントに配置した構成における特有の症状です。
- 以下は、Cookieのエラーが表示されログインができない画面になります。
- 以下は、サイト表示が崩れたWordPress管理画面になります。
対処方法
- WordPressの管理画面を使用するために、CloudFront の下記キャッシュ設定を変更します。
- Allowed HTTP Methods をデフォルトの"GET, HEAD" → “GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE"
- Forward Cookiesをデフォルトの"None (Improves Caching)" → “All"
- Query String Forwarding and Cachingをデフォルトの"None (Improves Caching)" → “Forward all, cache based on all"
siteurlをhttps化できない or リダイレクト ループ
説明
- httpでアクセスするとコンテンツが正しく表示されますが、httpsでアクセスするとコンテンツのサイト表示が崩れます。
- また、WordPressの管理画面から Site Address を確認すると、URLがhttp となっていることが分かります。
対処方法
- Really Simple SSLのプラグインをインストール、SSLを有効化しましたが、 ERR_TOO_MANY_REDIRECTSのエラーとなり、redirect loopが発生してしまいました。Really Simple SSLのプラグインは、CloudFront構成が考慮されておらず、代替の手段が必要であることが分かりました。
- 代わりに、SSL Insecure Content Fixerのプラグインを使用しました。以下に対処の手順を説明します。先ず、SSL Insecure Content Fixerのプラグインをインストールします。
- 次に、WordPress のSettings から"SSL Insecure Content"を開きます。"HTTPS detection"の設定値が"standard WordPress function" となっているため、“HTTP_CLOUDFRONT_FORWARDED_PROTO (Amazon CloudFront HTTPS cached content)" に変更、保存します。
- 今回、siteurlがhttps化されなかった理由は、CloudFrontをWordPressのフロントに配置した構成における特有の症状です。CloudFront はリクエスト元の X-Forwarded-Protoヘッダを削除するためクライアントのプロトコルを特定できず、WordPress が制御できませんでした。
- CloudFront のキャッシュ動作の設定を変更し、CLOUDFRONT_FORWARDED_PROTOヘッダを追加します。Cache Based on Selected Request Headers(選択されたリクエストヘッダーに基づいたキャッシュ)の設定を “Whitelist"に変更し、Whitelist Headersに"CloudFront-Forwarded-Proto"を追加します。あるいは、"All" に変更を行います。
- 確認のため、再度、WordPress のSettings から"SSL Insecure Content"を開きます。無事に、httpsプロトコルが検出できたようです。
- WordPressの管理画面の Site Addressは自動で修正されなかったため、wp-config.phpを手動で修正します。(WP_SITEURL, WP_HOMEのhttpをhttpsに書き替え)
- wp-config.phpを手動で変更する以外に、wp option update コマンドを利用する方法もあります。
bitnami@ip-xx-xx-xx-xx:~$ sudo cp -p /opt/bitnami/apps/wordpress/htdocs/wp-config.php /opt/bitnami/apps/wordpress/htdocs/wp-config.php_orig
bitnami@ip-xx-xx-xx-xx:~$ sudo vi /opt/bitnami/apps/wordpress/htdocs/wp-config.php
bitnami@ip-xx-xx-xx-xx:~$ sudo diff /opt/bitnami/apps/wordpress/htdocs/wp-config.php_orig /opt/bitnami/apps/wordpress/htdocs/wp-config.php
98,99c98,99
< define('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/');
< define('WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] . '/');
> define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST'] . '/');
> define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST'] . '/');
- WordPressの管理画面から Site Address を確認すると、URLがhttps に変わったことが確認できました。
- 最後に、httpsでアクセスしても、コンテンツが正しく表示されることが確認できました。
WordPressブロックエディターが使えない
- WordPressで記事を投稿する際に、ブロックエディター(Gutenberg)でブロックの追加ができない、クラシックエディターはテキストモードしか使えない(ビジュアルモードに切り替えができない)問題に遭遇しました。詳細は、下記の記事にまとめておりますが、WordPress はUser-Agentヘッダを判別して、ビジュアルエディターを起動することが理由でした。対処として、CloudFrontでUser-Agentヘッダを置き換えせず、User-Agentヘッダをオリジンに転送するように変更を行います。
WordPress管理画面の警告 “もっと高いレベルの権限が必要です。"
- WordPress管理画面から[サイトのカスタマイズ] を押すと再ログインを求められ、再度管理者権限のユーザーにてログインすると、「もっと高いレベルの権限が必要です。」と警告が表示されます。
- この問題は、CloudFront からオリジンへ Cokkie が転送されていない場合に起こります。また、[サイトのカスタマイズ] では右ペインにサイトコンテンツが表示されるため、管理画面(*.php、/wp-admin/*)ではなく、サイトにCokkie が転送されなければいけません。
- 以下、対処方法です。
- Forward Cookiesをデフォルトの"None (Improves Caching)" → “All"
- あるいは、Forward Cookiesをデフォルトの"None (Improves Caching)" → “Whitelist"に変更し、下記を指定
- comment_author
- wp-*
- wordpress_*
CloudFront キャッシュ設定のまとめ
- ここまでご紹介した対処方法をCloudFront のDefaultパスに設定すると、コンテンツのキャッシュが活かせないため、私の場合CloudFrontのキャッシュ設定にてパスパターンを追加し、WordPressの管理画面(*.php、/wp-admin/*)とその他のコンテンツ(Default)でキャッシュ設定を区別して設定しています。WordPressの管理画面の方には、こちらで紹介した設定が必要になります。
- 個人的には無用なトラブルに遭遇することを避けるため、CloudFrontのCache Based on Selected Request Headers(選択されたリクエストヘッダーに基づいたキャッシュ)の設定は"Whitelist"ではなく、“All" を設定しています。
- また、"Viewer Protocol Policy"をデフォルトの"HTTP and HTTPS" から “Redirect HTTP to HTTPS" に変更します。設定変更後は、クライアントからhttp でアクセスがあった場合でも、自動的にhttps にリダイレクトを行います。