GCPにWordPressを立ててAWS CloudFrontでキャッシュしてみた

やってみた

 Qiitaの記事(1時間で出来る!最強のWordPress環境構築(永久無料))を見て、Amazon LightSailで動かしていたWordPressをGCPの無料枠VMに移して500円/月を節約してみようかと思ってやってみた。

構成

CDNとしてCloudFront、ドメインの管理にRoute53、SNIなSSL証明書管理にCertificate Manager、WordPressサーバーにGoogle Cloud Platformの無料枠VMを使用する。
 以下の説明では、ユーザーがアクセスするのに使用するドメインをexample.com、CloudFrontがWordPressサーバーへ問い合わせを行うドメインをorigin.example.comとする。

導入手順

 基本的にはQiitaの記事と同じだが、CDNにCloudflareを使わないでCloudFrontを使用しているところが異なる。(設定はCloudflareのほうが楽かも?)

WordPressサーバーの構築

 まず、Qiitaの記事の手順でWordPressサーバーを構築する。構築できたら、払い出された静的IPアドレスをorigin.example.comのAレコードとしてRoute 53でDNS登録する。

Let’s Encryptでorigin.example.comのSSL証明書作成

 CloudFrontとWordPressサーバー間の通信をhttps化するためにLet’s Encryptでorigin.example.comの SSL証明書を作成する。のちの証明書更新なども考えてwebrootを使用した方法がおすすめ。

Let’s EncryptからはHTTPでアクセスが来るので 、Nginxの設定ファイルのHTTP(port 80)の部分にlocation設定を追加してNginxを再起動する。

$ sudo vi /opt/bitnami/nginx/conf/bitnami/bitnami.conf
(以下のように変更)
$ sudo /opt/bitnami/ctlscript.sh restart nginx
    # HTTP server

    server {
        listen       80;
        server_name  localhost;

        #include "/opt/bitnami/nginx/conf/bitnami/phpfastcgi.conf";

        location ^~ /.well-known/acme-challenge/ {
            default_type "text/plain";
            root         "/opt/bitnami/apps/wordpress/htdocs/";
        }

        include "/opt/bitnami/nginx/conf/bitnami/bitnami-apps-prefix.conf";
    }

certbot-autoコマンドをインストールして証明書を取得する。

$ sudo curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
$ sudo chmod 700 /usr/bin/certbot-auto
$ sudo /usr/bin/certbot-auto certonly -m メールアドレス --agree-tos --non-interactive --force-renewal --webroot -w /opt/bitnami/apps/wordpress/htdocs -d origin.example.com

Nginxの設定ファイルで証明書を変更して再起動する。

$ sudo  vi /opt/bitnami/nginx/conf/bitnami/bitnami.conf
(以下のように変更)
$ sudo /opt/bitnami/ctlscript.sh restart nginx
    # HTTPS server

    server {
       listen       443 ssl;
       server_name  localhost;

       ssl_certificate      "/etc/letsencrypt/live/origin.example.com/fullchain.pem";
       ssl_certificate_key  "/etc/letsencrypt/live/origin.example.com/privkey.pem";
       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;

       ssl_ciphers  HIGH:!aNULL:!MD5;
       ssl_prefer_server_ciphers  on;

       #include "/opt/bitnami/nginx/conf/bitnami/phpfastcgi.conf";

       include "/opt/bitnami/nginx/conf/bitnami/bitnami-apps-prefix.conf";
    }

最後に証明書が自動更新されるようにrootのcrontabに設定を追加しておく。

$ sudo -s
# crontab -e

0 4 1 * * /usr/bin/certbot-auto renew && /opt/bitnami/ctlscript.sh restart nginx

WordPressの設定変更

wp-config.phpに以下の設定を追加しておく。

$ sudo vi /opt/bitnami/apps/wordpress/htdocs/wp-config.php
if ( defined( 'WP_CLI' ) ) {
    $_SERVER['HTTP_HOST'] = 'localhost';
} else {
    $_SERVER['HTTP_HOST'] = 'example.com';
    $_SERVER['HTTPS'] = 'on';
    $_ENV['HTTPS'] = 'on';
    $_SERVER['HTTP_POST'] = 'example.com';
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

Certificate ManagerでSSL証明書の作成

 Certificate Managerでexample.comのSSL証明書を作成する。

CloudFrontの設定

 CloudFrontでDistributionとBehaviorを登録する。記載がないものはdefault値とする。

CategoryNameValue
Origin Settings Origin Domain Nameorigin.example.com
Origin Protocol PolicyMatch Viewer
Default Cache Behavior Settings Viewer Protocol PolicyRedirect HTTP to HTTPS
Allowed HTTP MethodsGET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cache Based on Selected Request Headers whitelist
Whitelist Headers X-Forwarded-For
Object Caching Customize
Maximum TTL 300(保持時間を長くしたいなら増やす)
Default TTL 300 (保持時間を長くしたいなら増やす)
Forward Cookies ALL
Query String Forwarding and Caching Forward all, cache based on all
Distribution SettingsAlternate Domain Names
(CNAMEs)
example.com
SSL Certificate Custom SSL Certificate(ACMで作成したexample.comの証明書を設定)

上記の登録が終わるとCloudFrontのエンドポイント(xxxxxxxx.cloudfront.net)が割り当てられるのでメモしておく。

Default以外のBehaviorとして「 /.well-known/acme-challenge/* 」「 /wp-admin/* 」「*.php」「/wp-json/*」の4つを追加する。

Cache Behavior Settings NameValue
/.well-known/acme-challenge/*Path Pattern/.well-known/acme-challenge/*
Viewer Protocol PolicyHTTP and HTTPS
Allowed HTTP MethodsGET, HEAD
Object Caching Customize
Minimum TTL 0
Maximum TTL 0
Default TTL 0
/wp-admin/*
*.php
/wp-json/*
の3つのパラメータは同じ設定で。
Path Pattern /wp-admin/*
*.php
/wp-json/*
Viewer Protocol Policy Redirect HTTP to HTTPS
Allowed HTTP Methods GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cache Based on Selected Request Headers whitelist
Whitelist Headers X-Forwarded-For
Object Caching Customize
Minimum TTL 0
Maximum TTL 0
Default TTL 0
Forward Cookies ALL
Query String Forwarding and Caching Forward all, cache based on all

Route 53でAlias登録

 CloudFrontでの作業が終わって15分ぐらいたつとDistoributionのステータスがDeployedに代わるので、DeployedにDeployedになっていることを確認したら、Route 53でexample.comのAliasとしてxxxxxxxx.cloudfront.netを登録する。

動作確認

 https://example.comで閲覧できること、dnsにexample.comを問い合わせたときにAレコードのIPアドレスがCloudFrontのものになっていること(WordPressサーバーのIPアドレスになっていないこと)、WordPressの管理画面関係が正常に動作していることを確認する。

dnsの確認はGCPのWordPressサーバーにログインしてdigコマンドで確認できる。

$ dig example.com ns

; <<>> DiG 9.10.3-P4-Debian <<>> machinanette.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20127
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;example.com.              IN      A

;; ANSWER SECTION:
example.com.       11      IN      A       99.84.254.61
example.com.       11      IN      A       99.84.254.78
example.com.       11      IN      A       99.84.254.90
example.com.       11      IN      A       99.84.254.117

;; Query time: 1 msec
;; SERVER: 169.254.169.254#53(169.254.169.254)
;; WHEN: Sat Jun 22 12:05:05 UTC 2019
;; MSG SIZE  rcvd: 109

追加作業

Nginxのアクセスログに正しいIPアドレスが記録されるようにする

何も設定をしないと記録されるアクセス元は全部CloudFrontのIPアドレスになってしまうため、Nginxのhttp_realip_moduleの設定を追加してアクセス元のIPアドレスが記録されるようにしておく。

Qiitaの手順でやれば http_realip_moduleが組み込まれたNginxが入っているはずだが、念のため以下のコマンドで確認する。 –with-http_realip_moduleが入っていれば問題ない。

$ nginx -V
nginx version: nginx/1.16.0
built with OpenSSL 1.0.2r  26 Feb 2019
TLS SNI support enabled
configure arguments: --prefix=/bitnami/lamp73stack-linux-x64/output/nginx --with-http_sub_module --with-http_ssl_module --with-http_stub_status_module --with-cc-opt=-I/bitnami/lamp73stack-linux-x64/output/common --with-ld-opt=-L/bitnami/lamp73stack-linux-x64/output/common/lib --with-http_gzip_static_module --with-mail --with-mail_ssl_module --with-http_realip_module --with-http_stub_status_module --with-http_v2_module

公開されているCloudFrontのIPアドレスリストをcurlで取得してNginxの設定ファイルの形式にして保存する。(jqコマンドがないときはインストールすること)

$ echo 'real_ip_header     X-Forwarded-For;' > realip.conf|curl -s https://ip-ranges.amazonaws.com/ip-ranges.json | jq  -r '.prefixes[] | select(.service=="CLOUDFRONT") | .ip_prefix' | awk '{print "set_real_ip_from " $1 ";"}' >> /opt/bitnami/nginx/conf/realip.conf 

nginx.confに作成したrealip.confを読み込む行を1行追加してnginxを再起動する。

$ sudo vi /opt/bitnami/nginx/conf/nginx.conf
http {
    include       mime.types;
    default_type  application/octet-stream;

(略)

    include "/opt/bitnami/nginx/conf/bitnami/bitnami.conf";
    include "/opt/bitnami/nginx/conf/realip.conf";

}

感想

おすすめ度:★★★☆☆

 Route53でNameServerをCloudflareのNameServerにしても認識してくれなかったのでCloudFrontを使用しましたが、設定などはCloudflareのほうが楽そうですし、使えるのであればCloudflareのほうがよさそうです。諸々の作業を考えると500円の価値があったか微妙かもしれませんが、AWSの設定やWordPressの仕組みについて色々と勉強になりました。
 勉強がてらやる分には難し過ぎることもないので丁度よいかもしれません。