CloudFront + WordPress 構成の必須設定 1月 3, 2021 2月 10, 2021 AWS , CloudFront , Web製作 & 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 にリダイレクトを行います。
参考資料