AWSでWordPressサイトを構築 第1回〜AWS構築〜

こんにちは、かっぺいです。
ブログサイトを作ろうと、ドメインを取得したけれど、全然行っていませんでした。
Bloggerで何となくやっていたけど、やっぱりWordPressでやり直そうと一念発起しました。

構成案

検索して、よく出てくるのはLightsailを使って、構築を自動化してくれるものばかり。
でも、程よくコストを抑えて、簡単にhttpsサイトをと思うと、自分で構築した方が良さそうでした。

よくある、プライベートサブネットにDBとWebSVを置いて、ELBでhttpsリスナーからプライベートのEC2へ転送という形ですが、プライベートサブネットにNATGWが無いとWordPressの更新とか使えないので、全然利用していなくてもコストがかかる。
個人利用なのでコストは抑えたい。

構成案1

全てシングルAZにして、DBサーバだけプライベートに、パブリックにWebSVを置いてセキュリティグループでALBだけアクセス可能に。

一見安くなりそうだが、ALBが時間課金なので、使っていなくてもコストが発生する。RDSも初期の規模が小さい時には無駄な気がします。

httpsをオフロードしてくれるサービスは、ELBかCloudFrontなのでCloudFrontで利用する案に変更することに。

最終構成

コストを抑えるために、以下の方針で構築

  1. EBSの汎用SSD (GP3)を使えばIOPS3000を確保できるので、初期はRDSを使わずにEC2のローカルにMariaDBを構築する
  2. EC2のEBSサイズを抑える目的で、コンテンツはプライベートサブネットのEFS配下に配置する
  3. WebSVはパッケージ更新などの目的で、インターネット接続が可能なパブリックサブネットに配置するが、インバウンド接続は、セキュリティグループ設定でCloudFrontからのアクセスのみに制限する
  4. パブリックサブネットにWebSVがいるので、念の為にCloudFrontにはWAFを設定する

WebSVへのリモート接続

パブリックサブネットに置いたWebSVには、通常は公開鍵SSHでログインするのが普通ですが、今回はインバウンド接続はCloudFrontのみに制限したいので、SSHでのログインは使えません。

代わりに、セッションマネージャーというサービスを使います。これ、ブラウザさえあればリモートログインできるようになるので、設定しておくと非常に便利です。

IAMでロールを作成し、以下をアタッチします。

  • AmazonEC2RolerforSSM
  • AmazonS3FullAccess
    ※ファイル送受信に、S3を使うので一緒にポリシーをアタッチする

このロールをWebSVのインスタンスにアタッチします。

EC2起動〜WordPressインストール

インスタンスタイプは、t4g.microでEBSは50GBのGP3、OSはAmazonLinux2で構築。
起動したら、セッションマネージャでログインします。

必要なパッケージをインストールして、最低限のパラメータ設定をしてWebSVとMariaDBを起動。
WordPressのtar.gzをwgetで取得して展開。
wp-config.phpを設定。以下を追加で記述。

/* Add any custom values between this line and the "stop editing" line. */
define( 'WP_HOME', 'https://独自ドメイン名' );
define( 'WP_SITEURL', 'https://独自ドメイン名' );

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_ENV['HTTPS'] = 'on';
        $_SERVER['HTTPS'] = 'on';
} elseif (isset( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) && $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] === 'https') {
        $_ENV['HTTPS'] = 'on';
        $_SERVER['HTTPS'] ='on';
}

インストール後、wp-contentsフォルダをEFSに移動して、シンボリックリンクでwp-contentsをEFS配下を向くように設定する

CloudFront用のセキュリティグループ設定

現在の、AWSが利用しているIPアドレスレンジというのが公開されています。ここから、CloudFrontとして利用されているレンジをセキュリティグループに設定します。

全部で、130個近くあるのでデフォルトではセキュリティグループの最大ルール設定数に抵触します。
なので、セキュリティグループを3個使って分割登録するphpを作成。そんなに頻繁に変わらないと思うので、定期的に実行すれば良いかなという感じで、作成。

WAFのルール

AWS WAFを選び、WebACLsを選びます
リージョンは、Global (CloudFront)を選んで、「Create web ACL」

ルールは、以下を選択

  • AWS-AWSManagedRulesKnownBadInputsRuleSet
  • AWS-AWSManagedRulesWordPressRuleSet
  • AWS-AWSManagedRulesSQLiRuleSet
  • AWS-AWSManagedRulesLinuxRuleSet
  • AWS-AWSManagedRulesAmazonIpReputationList
  • AWS-AWSManagedRulesAnonymousIpList

「Core rule set」を選びたい衝動に駆られるけれど、これを入れるとファイルアップロードがブロックされます。

CloudFront構築

CloudFrontのオリジンにEC2のサイトを指定する。しかし、インスタンスが再起動することによるIPアドレス変更があると面倒なので、EC2のネットワークをElasticIPに変更して、アドレス変動が起こらないようにする。

CloudFrontから、ディストリビューションの作成を実行する

  • オリジンドメインには、EC2のパブリックDNS名を指定する
  • プロトコルはhttpのみ
  • オリジンシールドを有効にし、EC2インスタンスと同じリージョンを選ぶ
  • キャッシュビヘイビアのビューワーは、RedirectHTTP to HTTPSを選ぶ
  • 許可されたHTTPメソッドは、PUT,POSTを含む全てを選ぶ
  • キャッシュキーは、Legacyを選び、ヘッダーに「CloudFront-Forwarded-Proto」「HOST」を選ぶ
  • クエリ文字と、Cookieは全てを選ぶ
  • WAFオプションは、予め作成したウェブACLを選択します
  • 代替ドメインは、SSL証明書のドメインを設定し、カスタムSSL証明書は予めACMで作成した証明書を選択します

ディストリビューション作成後、管理者サイト用のビヘイビアを作成します
作成された、ディストリビューションを選び、「ビヘイビアを作成」を選びます

  • パスパターンは、/wp-admin/*
  • ビューワーは、RedirectHTTP to HTTPSを選ぶ
  • 許可されたHTTPメソッドは、PUT,POSTを含む全てを選ぶ
  • キャッシュキーは、Legacyを選び、ヘッダーに「CloudFront-Forwarded-Proto」「HOST」を選んだのち、カスタムを追加で「User-agent」を追加
  • クエリ文字と、Cookieは全てを選ぶ
  • オブジェクトキャッシュは、Customizeを選んで全てのTTLに0を入力してキャッシュを無効にする

Route53設定

ブログのホストを、CloudFrontへ転送する設定を追加します。
ゾーン設定に移動し、レコードの追加を選びます。

  • シンプルルーティングを選び、レコード名にブログのホスト名を入力
  • レコードタイプにAを選ぶ
  • トラフィックルーティング先に、CloudFrontディストリビューションへのエイリアスを選び、対象のディストリビューションを選択する

アクセス確認

これで、独自ドメインでアクセスできるようになったので、ブラウザから
https://独自ドメイン/wp-admin/install.php
を開き、インストール画面が崩れなく表示されることを確認したのち、インストールを実行する。

キーポイント

ポイントは2個あります。

CloudFrontのヘッダーが正しくないと、管理者モードのグラフィカルエディタが起動できません。
WAFの設定で、Coreルールがセットされているとアップロード関連がブロックされてしまいます。