CloudFront のキャッシュ・セキュリティヘッダ・SPA 設定
CloudFront の Distribution は設定項目が多く、初心者は何から手を付けて良いか迷います。本記事では、本シリーズで採用した マネージドポリシーの組み合わせ と、SPA 用の カスタムエラーレスポンス、その他のおすすめ設定をまとめます。
AWS マネージド Cache Policy
CloudFront には AWS が用意した Cache Policy が複数あり、自分で書かなくてもまずこれを使えば 7 割の用途で十分です:
| ポリシー名 | ID | 用途 |
|---|---|---|
CachingOptimized | 658327ea-f89d-4fab-a63d-7e88639e58f6 | 静的サイト(HTML/CSS/JS/画像)。最大 24h キャッシュ |
CachingDisabled | 4135ea2d-6df8-44a3-9df3-4b5a84be39ad | API・動的レスポンス。キャッシュしない |
CachingOptimizedForUncompressedObjects | b2884449-e4de-46a7-ac36-70bc7f1ddd6d | 圧縮済 (gzip 等) ファイル向け |
本シリーズでは default_cache_behavior に CachingOptimized、/api/* behavior に CachingDisabled を割り当てました。
マネージド Origin Request Policy
「オリジンに何を転送するか」のポリシー:
| ポリシー名 | ID | 用途 |
|---|---|---|
AllViewer | 216adef6-5c7f-47e4-b989-5492eafa07d3 | 全ヘッダ・クエリ・cookie を転送 |
AllViewerExceptHostHeader | b689b0a8-53d0-40ab-baf2-68738e2966ac | Host 以外を転送(API GW など Host 上書きが要らない時) |
UserAgentRefererHeaders | acba4595-bd28-49b8-b9fe-13317c0390fa | UA + Referer のみ |
API Gateway を origin にする時は AllViewerExceptHostHeader を使います。Host を上書きされると API GW がリクエストを正しくルーティングできない問題を回避するため。
マネージド Response Headers Policy(セキュリティヘッダ)
AWS マネージドの SecurityHeadersPolicy(ID: 67f7725c-6f97-4210-82d7-5512b31e9d03)を割り当てるだけで、以下の主要セキュリティヘッダが すべてのレスポンスに自動付与 されます:
X-Frame-Options: DENY(クリックジャッキング対策)X-Content-Type-Options: nosniff(MIME sniffing 対策)Strict-Transport-Security(HTTPS 強制 / HSTS)Referrer-Policy: strict-origin-when-cross-originX-XSS-Protection: 0(モダンブラウザでは廃止された機能を明示無効化)
これを 1 行で全付与できるのは強い。手動で書くと環境ごとにブレるので、マネージド推奨。
本シリーズの default_cache_behavior
default_cache_behavior {
target_origin_id = "s3-${var.bucket_name}"
viewer_protocol_policy = "redirect-to-https" # HTTP → HTTPS リダイレクト
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
compress = true # gzip/brotli 自動圧縮
cache_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6" # CachingOptimized
response_headers_policy_id = "67f7725c-6f97-4210-82d7-5512b31e9d03" # SecurityHeadersPolicy
}
SPA 用カスタムエラーレスポンス
SPA(Single Page Application)でクライアントサイドルーティングを使うと、/about 等は S3 に存在しない URL にアクセスする場合があり、403 や 404 が返ります。これを 200 + index.html に書き換え ると、JavaScript ルーティングが動くようになります:
custom_error_response {
error_code = 403
response_code = 200
response_page_path = "/index.html"
}
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
Next.js の static export や Astro / Vue Router 等の SPA で必須の設定です。
HTTP/3 (QUIC) の有効化
http_version = "http2and3"
HTTP/3 はモバイルや不安定回線で速度向上が見込める。CloudFront のデフォルトは http2 ですが、最新 Chrome / Safari は HTTP/3 対応なので有効化すべき。コスト変動なし。
Geo Restriction
本シリーズでは個人サイトなので地理制限なし:
restrictions {
geo_restriction {
restriction_type = "none"
}
}
クライアント案件で「日本国内のみ」要件があれば whitelist + locations = ["JP"] を指定。法令対応で必要になることがあります。
TLS 設定
viewer_certificate {
acm_certificate_arn = var.certificate_arn
ssl_support_method = "sni-only" # SNI で複数ドメイン同居
minimum_protocol_version = "TLSv1.2_2021" # TLS 1.2+ 必須
}
| 項目 | 値 | 意味 |
|---|---|---|
| ssl_support_method | sni-only | 標準。月 0 円。vip にすると月 $600 だが、SNI 非対応の古いクライアント (IE6 等) も繋がる |
| minimum_protocol_version | TLSv1.2_2021 | TLS 1.2 以上を必須に。古いクライアント(PCI-DSS 準拠で SSLv3 / TLS 1.0 が NG)を切り捨て |
Price Class の選び方
| クラス | 範囲 | 料金(無風時) | 用途 |
|---|---|---|---|
PriceClass_100 | 北米・欧州のみ | 最安 | 北米欧州ターゲットなら |
PriceClass_200 | 上 + アジア・中東・アフリカ | 中 | 日本ターゲットならこれ |
PriceClass_All | 全世界 | 最高 | 南米・オセアニアもカバーしたい時 |
本シリーズは日本訪問者がメインなので PriceClass_200。All との性能差は日本国内ではほぼない(同じ東京 Edge から配信される)のでコスト最適。
キャッシュ無効化(Invalidation)
新しい index.html を S3 にアップロードしても、CloudFront のキャッシュが残っていると古いまま。明示的に無効化が必要:
# 特定パスのみ
aws cloudfront create-invalidation \
--distribution-id EXXXXXXXXXXXXX \
--paths "/index.html"
# 全部
aws cloudfront create-invalidation \
--distribution-id EXXXXXXXXXXXXX \
--paths "/*"
料金は 月 1,000 paths まで無料、超過分は path あたり約 $0.005。/* は wildcard で 1 path カウント。リリース毎に /* 1 個なら無料枠で余裕。
キャッシュ無効化のハマり
本シリーズの GitHub Actions ワークフローは当初 --paths "/index.html" "/" と書いていましたが、新しく追加した learn.html や blog/ は無効化されない ため反映が遅れる事故がありました。/* に変えて解決。
動作確認の見方
curl -sI https://lab.iigtn.com/
# 主要ヘッダ
Strict-Transport-Security: max-age=31536000 # ← SecurityHeadersPolicy
X-Frame-Options: DENY # ← 同上
X-Content-Type-Options: nosniff # ← 同上
Referrer-Policy: strict-origin-when-cross-origin
Server: AmazonS3
Via: 1.1 ...cloudfront.net (CloudFront)
X-Cache: Hit from cloudfront # ← 2 回目以降は Hit
X-Amz-Cf-Pop: NRT12-P4
次の記事
静的サイトが安定して配信できるようになったら、次は 「ローカル PC からの手動アップロードを自動化する」 ステップへ。git push したら GitHub Actions が自動デプロイする CI/CD を組みます。次の記事ではその要となる GitHub Actions OIDC の仕組みを解説します。
📚 用語集
- Cache Policy (CloudFront)
- 「何をキーにキャッシュ、TTL いくつ、圧縮するか」を定義するポリシー。AWS マネージドの定番ポリシーがある。
- CachingOptimized
- 静的コンテンツ向け AWS マネージド Cache Policy。最大 24h キャッシュ・gzip/brotli 受け入れ・Accept-Encoding ベースの分離キャッシュ。
- CachingDisabled
- キャッシュしない AWS マネージド Cache Policy。動的 API レスポンス向け。
- Origin Request Policy
- 「オリジンに何を転送するか」を定義するポリシー。ヘッダ / クエリストリング / cookie の転送可否を制御。
- AllViewerExceptHostHeader
- AWS マネージドの Origin Request Policy。Host 以外すべてオリジンへ転送。API Gateway 等は Host を上書きされると混乱するので、これを使う。
- Response Headers Policy
- 「レスポンスにどのヘッダを付けるか」を定義するポリシー。セキュリティヘッダの自動付与に便利。
- SecurityHeadersPolicy
- AWS マネージドの Response Headers Policy。X-Frame-Options / X-Content-Type-Options / Strict-Transport-Security 等を自動付与。
- SPA (Single Page Application)
- JavaScript で画面遷移する Web アプリ。React / Vue / Astro などが該当。CloudFront 配信時は 403/404 → /index.html のフォールバックが必要。
- クライアントサイドルーティング
- ブラウザの JavaScript で URL と表示内容を切替える方式。
/aboutへのアクセスでもサーバには/index.htmlを返してもらう必要がある。 - custom_error_response (CloudFront)
- オリジンが特定のエラーコードを返した時の挙動を上書きする設定。SPA フォールバックで
403/404 → 200 + /index.htmlによく使う。 - HTTP/3 (QUIC)
- HTTP の最新版。UDP ベースで接続確立が速く、不安定回線でも切れにくい。Chrome / Safari 最新版が対応。
- SNI (Server Name Indication)
- 1 つの IP アドレスで複数ドメインの TLS 証明書を出し分ける TLS 拡張。CloudFront
sni-onlyはこれが前提。 - HSTS (HTTP Strict Transport Security)
- 「このサイトは HTTPS のみ」をブラウザに記憶させるレスポンスヘッダ。中間者攻撃で HTTP に降格させられる事故を防ぐ。
- X-Frame-Options: DENY
- このページを iframe 内に表示することを禁止するヘッダ。クリックジャッキング攻撃の対策。
- Geo Restriction
- CloudFront の地理制限機能。国コード(ISO 3166-1 alpha-2)で whitelist / blacklist を指定。
- Invalidation
- CloudFront の Edge キャッシュを無効化する操作。新しいバージョンを即時反映させたい時に必要。月 1,000 paths まで無料。
- wildcard path (
/*) - Invalidation での全パス無効化。1 path カウントで全 path をクリアできるので、リリース毎に 1 回叩けば無料枠内に収まる。