AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

フロントエンドを CloudFront (S3) で配信する

React とか Vue あたりで作って、 npm run build で出力したやつをフロントエンドと呼んでいます、雑ゥ!

とにかくこれを S3 にぶっこみつつ、CloudFront で配信します。 最近のウェブ系はだいたいこんな感じですよねというヤツのふりかえり。

事前にやっておくと良いこと

やらなくてもいいけど、必要な要件ならやっておく方が楽です。 CloudFront 設定変更するのめっちゃ時間かかるので。

ACMSSL 証明書の準備

もし CloudFront で配信するドメイン独自ドメインを利用するなら、 ヴァージニア北部リージョン (us-east-1) の AWS Certificate Manager で SSL 証明書を発行するか、外部からインポートしておいてください。

CloudFront 作成中に「あっやべえ! 忘れてた!」となった場合、一度作成してから設定変更するか、最初から作り直しするしかなく、デプロイ時間が長いのでとても面倒。

ログ用の S3 バケット

いわゆるアクセスログ的なものを取得したい場合、保管先として S3 バケットが必要です。 とりあえず無しでも (いわゆる API アクセスするバックエンドなどがいてそっちでログ見るとかなら) 大丈夫。

ただバックエンドで、フレームワークやロガーがアクセス ID 付与する環境でなかったりする場合は有効化して、 AWS 側から一意なアクセス ID 付与する、とか色々やったほうが丸いかも。 今回はこのあたりは触れません。

S3 の準備

まず S3 バケットを作成して、パブリック設定で公開します。

以下バケットを作成した所から。

静的ウェブサイトホスティングの有効化

静的ウェブサイトホスティングを有効することで、S3 にアップロードしたファイルをウェブに公開します。 以下のように標準だと無効化されているので、編集ボタンから

標準で無効

有効にするを選択します。

色々でる

上記の通り色々出てきますが基本変更は必要ありません。 必須項目のインデックスドキュメントindex.html (Apache で言う所の DirectoryIndex) を設定しておきましょう。

有効化されると、以下のように http://バケット名.s3-website-ap-northeast-1.amazonaws.com/ の形で URL が払い出されます。 これが CloudFront から配信する際の実体 (オリジン) となります。

静的ホスティングしたところ

CloudFront の準備

CloudFront 側の設定をします。 CloudFront は

などと訳のわからない内容をお出ししてきますが、おおざっぱにそれぞれ

  • CloudFront の単位
    • Apache でいうところの VirtualHost
  • 配信する実体
    • VirtualHostDocumentRoot
  • 動作設定
    • VirtualHost の中で設定できるログや受け付ける HTTP メソッドなどの設定

という感じに対応していると (個人的に) 思えます。 上記を踏まえて、一度作成まで触ってみるとわかりやすいと思われる。

CloudFront のメニュー

このメニューが、ワイを惑わせるんやな……!

ディストリビューションを作成

では実際にディストリビューションを作成してみます。

オリジン

CloudFront で配信される実体ですね。 今回は S3 の準備で用意した静的ウェブサイトを利用します。

オリジンドメイン名前のそれぞれに、そのまま静的ウェブサイトホスティングの URL をシュッと設定します。 同じアカウント ID 内であれば補完してくれた気がする。

S3を指定している

S3 バケットアクセス・カスタムヘッダーを追加・オリジンシールドを有効にする・追加設定 ...

このあたりは画像の通り、デフォルトなりでほぼ利用しない感じです。

変更するトコあるとしたら、API などで通信するバックエンドが存在する場合、カスタムヘッダーを追加する必要があるくらいでしょうか。 各々の環境で動かして足りなければ、後々追加してみてください。

あまり気にしてないやつ

デフォルトのキャッシュビヘイビア

ようはキャッシュ設定ですね、オシャレな言い方するじゃん……!

パスパターン

デフォルトで良いでしょう。 これを弄るのはどういう状況だろうか……。

オブジェクトを自動的に圧縮

いわゆる通信の gzip 圧縮的なヤツに相当するんですかね? という理解でYesにしています。 不具合が出たらNoにするくらいの認識で良いでしょう。

キャッシュの設定

ビューワー

実際にブラウザ表示するときのアレソレの類です、とはいっても CDN やし複雑ではない。

ビューワープロトコルポリシー

これは理由 (HTTPS だと不具合出るなど) があって HTTP 配信をしないといけない、みたいな場合を除いて、Redirect HTTP to HTTPS で良いです。

HTTPS only だと HSTS 等でフォローされない場合、 http:// でアクセスしてきたユーザが表示されなくなります。

これまじでしょーもないと思うじゃろうけど、実際サポートデスクの兄貴がこの手の問い合わせを一日に十件単位で処理してたので、特に職場で従わされて使ってるみたいな人がクレーマーになりがちなんですよね。 設定で解決できてかつ初期設定でもあるので、クレーマーもいるんだなあくらいの気持ちでこのあたり防いでおきましょう。

許可された HTTP メソッド

CDN は基本キャッシュしたもの (つまり静的なコンテンツ) を配信するので、 GET, HEAD だけでいいと思うんですがどうでしょう。 フロントエンド自体やバックエンドの動作がわからなければ OPTION も入れておくといいかなァ、くらい。

PUT, POST, PATCH, DELETE は必要ないと思うんですが、どういうユースケースだと利用するんだろう……。

ビューワーのアクセスを制限する

オリジンを S3 の presignedURL とかで運用するときに使うんですかねー? 使ったこと無いので何もわからない。

ビューワーの設定

キャッシュキーとオリジンリクエス

Cache policy and origin request policy (recommended) を選択したらそれで良い気がする。 追加設定の項目も得に有効にしなくてよさそう (用途がわかってない)。

よくわからない設定たち

関数の関連付け

CloudFront Function というヤツです。 例えば Basic 認証をとか追加したい場合はこの層で対応するのがスマートらしい。 今は Lmanda@edge とかで処理しなくていいんだ……。

シュッと配信するパターンなおで、今回は特に設定する必要はないです。

設定

最後! これで最後だから頑張って! といってもそう多くはない。

料金クラス

これは基本的にすべてのエッジロケーションを使用する (最高のパフォーマンス)を選択しておけば良いです。 というか CDN なんてそんなもんや。

その他の選択肢、北米・欧州と北米・欧州・中東・アジア・アフリカ、についてですが、これは多分配信する国の法律にコンテンツの内容が縛られるとかそういうのを気にする人向けのアレソレな気がします。 そこまでやるなら自分でリージョン選択させてくれよ、という気持ちあるけど。

どことは言いませんが、特に厳しい所だと「国内法! 適用されるのは国内法じゃないとダメなの!」と言う所があります。

AWS WAF ウェブ ACL

WAF 使うならここで設定、かな? とりあえず設定しなくても良いと思います。

WAF 通すときにパケットをドロップする否か、みたいなのは運用ルールによるので気をつけてという感じです。

金! に直接関わる部分だったりする

代替ドメイン

独自ドメインを設定したい場合は、ここで設定を行います。 ただしこれ、 Listen できるようになるだけっぽいので、レジストラなり運用しているネームサーバに CNAME 設定を別途行ってください。

設定しなくても cloudfront.net ドメインが払い出されるのと、後ほど変更できるのであとまわしでも大丈夫です。

カスタム SSL 証明書

代替ドメインに指定したドメインと対応する証明書を、AWS Certificate Manager から選択します。 ヴァージニア北部 (us-east-1) しか参照できないので、東京リージョンとかにある証明書はエクスポート→インポートで持ち込むとかしてください。

これ地味に改善してほしいトコなんだよなあ。

レガシークライアントサポート

使ったこと無いんだけど、多分 SSLv2/v3 とかでしか通信できない環境向けじゃないすかね? IE7 だか 8 ですら TLS 使えたはずなので、本当に太古の環境をサポートしないといけないとき向けっぽそう。 けどこれやるくらいなら自分で Squid とかでプロキシ兼キャッシュサーバ作ったほうがよさそう。

セキュリティポリシー

TLSv1.2_2021 (推奨)でよござんす。

上記のレガシークライアントサポートほどじゃないですが、 TLSv1.1 あたりが分水嶺な感じありますね。 そこらへん気にする (直近だと Android4 とか iOS9 あたりですかね?) のであれば、TLSv1 あたりを選んで貰えれば。

サポートされている HTTPバージョン

HTTP/2 をチェックしておけば大丈夫です。強制的に HTTP/1 系で読ませたい事情があるならチェック外すくらいの気持ちで。

CloudFront は一種のプロキシみたいなトコがあり、オリジンとは (実質) 分離していると考えても差し障りなさそうなので、なんなら HTTP/3 もチェック入れても問題なさそうまである。

デフォルトルートオブジェクト

S3 の項目でも設定したインデックスドキュメントの CloudFront 版に相当するはずです。 index.html なり設定する必要ある場合はこちらにも設定しましょう。

注意すること

設定したドメインや CloudFront から払い出されたドメイン直下でアクセスすると、(S3 の静的ウェブサイトホスティングでは閲覧できるにも関わらず) AccessDenied が出る場合があります。

これはデフォルトルートオブジェクトの指定がないため、 S3 的に「バケットそのものを見ようとしている?」みたいな判断になって見えなくなっているんだと思われます。

なので、 S3 インデックスドキュメントで設定した値とおなじものを指定してください。 それで解決するはずです。 だめなら index.html など指定した上でダミーファイル置いてみてください。 見えたらコレが原因です。 (一日ハマった)

ドメイン周りの設定

標準ログ記録

オフにした場合は設定しなくていので楽です。 出来ればオンにしましょう、いわゆるアクセスログです。

S3 バケット

空の S3 バケットを作成しておき ACL 有効化した上で、以下のようなバケットポリシーを設定しておけば大丈夫だと思う。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::アカウント ID:root"
            },
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::バケットポリシーを設定するこのバケット名/*",
                "arn:aws:s3:::バケットポリシーを設定するこのバケット名"
            ]
        }
    ]
}
ログプレフィクス

独自ドメインの場合はサブドメイン部なりドメイン部を指定しておくとよさそう。 そうしてる。

オフにしてるけど、記録したいならオンで。

いま確認したらログなにも生成されていなかった、どうして……。

IPv6

オンにしておくと、 Route53 で設定するとき dualstack っていうヤツが設定できるようになるはず。 IPv4IPv6 どちらでも Listen できるらしい。

説明

説明以外の何者でもない、なんか書いとけ。

ログ周りの設定

以上だ……

画像だけ見ると一瞬なんだけど、いざ解説するとめっちゃ大変だな、という感じでした。

これで最低限、というか CDN なんでこれ以上もクソもなさそうな雰囲気ですが、これで React やら Vue やらで作られたアプリケーションが CDNブイブイ配信できます。 それ実行環境含めて Amplify でよくね?って言われたら泣いてしまう。

おまけ:Route53 で CloudFront ディストリビューションがサジェストされない

おま環なのかわからんのですが、同一アカウント ID 内で作成したディストリビューションを Route53 でエイリアスとして関連付けようとすると、 CloudFront リソースを選択してもサジェストされないんですよね。

しかし cloudfront.net ドメインで払い出された URL を指定するとちゃんと動くので、なんだろなあ……まあ動いてるからいいか、という感じ。