EC2のWordPressにCloudFrontを適用する

AWSのEC2で構築しているWordPressにCloudFrontを適用して、CDNを利用できるようにしました。

WordPressのインストールに関しては、以下の記事をご覧ください。

オリジン用のDNSレコードを設定する

CloudFrontを利用する場合
クライアント→CloudFront→EC2(WordPress)
という流れになり、EC2の部分をオリジンと呼びます。

CloudFrontからEC2を参照するために、オリジン(EC2)用のDNSレコードを予め設定しておきます。
レコード名は任意で、EC2に向けたAレコードを作成します。

※本記事ではRoute53で設定する例を記載します。

オリジン用のDNSレコード

DNSレコードの作成が反映されたら、オリジンのURLで使用するSSL証明書を発行します。
SSL証明書については、「Let’s Encrypt」を利用しています。
発行方法については、以下の記事をご覧ください。

ACMでSSL証明書を発行する

CloudFrontでSSLを利用するためにACMでSSL証明書を発行します。
CloudFrontで使用する場合は、「バージニア北部」のリージョンで発行する必要があります。

ACM

CloudFrontのディストリビューションを作成する

CloudFrontでDistribution(ディストリビューション)を作成します。

以下を指定します。

  • Origin domain:上記で設定したDNSレコードを指定したサブドメイン
  • Protocol:HTTPS only
ディストリビューションを作成

デフォルトのキャッシュ設定です。
以下のように指定します。

  • Viewer protocol policy:Redirect HTTP to HTTPS
  • Allowed HTTP methods:GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
キャッシュのデフォルトの動作を設定

ディストリビューションの設定です。
以下のように指定します。

  • Alternate domain name (CNAME) :WordPressサイトを公開しているドメイン
  • Custom SSL certificate:対象ドメインのSSL証明書
ディストリビューションの設定

ここまでの指定をして、ディストリビューションを作成します。
作成すると、以下のようにデプロイ中のステータスになります。

デプロイが完了して反映されるまでには、10分程度時間が掛かると思います。
デプロイ中の間に後続のキャッシュをしない設定を行っておきます。

ディストリビューションの作成が完了

一部をキャッシュしないように設定

サイトの一部をキャッシュしないように設定します。
WordPressの場合は、管理画面全般はキャッシュさせないようにします。

まず、ログインページの設定です。
新たにBehaviorを作成し、以下のように入力します。

  • Path pattern:/wp-login.php
  • Origin and origin groups:ディストリビューション作成時に指定したOrigin domain
  • Viewer protocol policy:Redirect HTTP to HTTPS
  • Allowed HTTP methods:GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
ビヘイビアを作成

「Cache key and origin requests」のところで、キャッシュ動作とリクエストについて設定します。
キャッシュしないように設定するのと、リクエスト時にヘッダー、クッキー、クエリパラメータを全て引き継ぐように設定します。

  • Cache policy:CachingDisabled
  • Origin request policy:AllViewer
キャッシュとリクエストの設定

作成できたら、同様の指定で以下のようにPath patternに「/wp-admin/*」「/wp-json/*」を指定して作成し、最終的には以下のようになります。

全てのビヘイビア

以上の設定ができていないと、以下のようにCookieがブロックされている、というエラーが発生して、管理画面にログインできない状態となります。

WordPressのクッキーがブロックされている

DNS設定の切り替え

ここまで完了したら、最終的にDNS設定を切り替えて、CloudFrontを介して処理を行うようにします。

クライアント→EC2(WordPress)

クライアント→CloudFront→EC2(WordPress)
というように、間にCloudFrontを挟むので、公開しているサイトのDNS設定を変更します。

※本記事ではRoute53で設定する例を記載します。

公開しているサイトのDNSレコードを編集します。
Route53の場合、CloudFrontを指定する場合はエイリアスが使用できます。
エイリアスを使用すると、CloudFrontのディストリビューションが選択できます。

DNSレコードを変更

NginxのSSL設定を変更

CloudFrontからEC2を参照する時には、オリジン用のサブドメインで参照するように変更したので、NginxのSSL設定も変更します。

SSL証明書のパスの部分を変更します。

server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    server_name  _;
    root         /usr/share/nginx/html/wordpress;

    ssl_certificate "/etc/letsencrypt/live/[ドメイン名]/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/[ドメイン名]/privkey.pem";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_prefer_server_ciphers on;
    (以下略)
}

設定ファイルを変更したら、Nginxを再起動します。

オリジンドメイン名に指定したドメイン名と、SSL証明書のドメイン名が一致していないと、「The request could not be satisfied」という502エラーが発生します。

The request could not be satisfied

プレビュー時にキャッシュが適用されてしまい、確認ができない

WordPressのプレビュー時は「preview=true」というパラメータが付き、
https://specially198.com/?p=1&preview=true
のようなURLとなります。

しかし、CloudFrontではクエリパラメータによるBehavior設定ができないので、これだとプレビュー時にもキャッシュが適用されてしまいます。

プレビュー時のURLを変更することで対応できそうですが、プレビュー時のURLとサイトURLが異なると404エラーが発生してしまったりします。

また、プレビュー時のURL変更は、Gutenbergエディタだと効かず、以下のようにfunctions.phpを修正したりする必要もありそうです。

https://wordpress.org/support/topic/how-to-change-url-of-preview-in-new-tab-in-gutenberg-editor/

何れにしても、ちょっと微妙なので、別途良いやり方が分かったら別途書きたいと思います。