CloudFront + WordPress 構成の必須設定

1月 3, 2021AWS,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 にリダイレクトを行います。

 

 

参考資料