'); background-size: 60px 60px;">
🐸
Lab — Tech Blog

AWS / Static Hosting / 2026-03

S3 Website Hosting をやめて
CloudFront + OAC に移行した話

個人サイト imai.me の AWS 構成を見直し、 より安全で説明しやすい静的サイト構成に改善した記録です。

このサイトについて

imai.me は自分のポートフォリオとして運用している静的サイトです。 AWS 上に構築しており、使っているサービスは以下の 6 つ。

Route 53 CloudFront ACM S3 CodeCommit CodePipeline

ローカルで git push すれば CodePipeline 経由で S3 に自動デプロイされ、 CloudFront で HTTPS 配信される、という構成です。 大量アクセスがない限り、主なコストは Route 53 のホストゾーン維持費($0.50/月)+ドメイン更新費くらい。 S3・CloudFront・CodePipeline は無料利用枠内に収まるため、ほぼゼロコストで運用できています。

ただ、中身をよく見ると「やや古い」やり方が残っていました。 今回、そこを改善した話を書きます。

以前の構成:何が問題だったか

もともとの構成は、CloudFront の Origin に S3 の Website Endpoint を指定するパターンでした。

Browser
↓ HTTPS
Route 53CloudFront
↓ HTTP(!)
S3 Website Endpoint ← ここが問題

この方式は動作としては問題なく、AWS の初期チュートリアルでもよく紹介される形です。 でも実際には、いくつかの制約がありました。

OAC が使えない — S3 Website Endpoint を Origin にすると、CloudFront の Origin Access Control(OAC)を設定できない。つまり S3 バケットをパブリックにしておく必要がある。

CloudFront → S3 が HTTP only — Website Endpoint は HTTPS に対応しておらず、Origin との通信が暗号化されない。

静的サイトの挙動を S3 に依存/index.html を返す、エラー時に 404.html を返す、といった処理がすべて S3 Website Hosting の機能頼みだった。

HTTP → HTTPS のリダイレクトなしhttp://imai.me でもアクセスできてしまう状態だった。

動くことは動く。でも「なんでこの構成にしたの?」と聞かれたとき、胸を張って説明できる設計ではなかった。 ポートフォリオとして見せるなら、ここは直しておきたいと思いました。

やったこと

作業は大きく 4 つ。順番に書きます。

1 CloudFront の Origin を切り替え

CloudFront の Origin を s3-website-...(Website Endpoint)から、 通常の S3 バケット Origin に変更しました。 バケット自体は同じ www.imai.me のまま。参照の仕方だけが変わります。

2 OAC を設定

CloudFront に Origin Access Control(OAC)を設定。 S3 バケットポリシーも更新し、CloudFront 経由のアクセスだけを許可する形にしました。 これで S3 を「公開 Web サーバー」から「CloudFront 専用のストレージ」に役割変更できました。

3 静的サイトの挙動を CloudFront 側に移譲

S3 Website Hosting をやめると、/index.html を返す処理が消えます。 代わりに CloudFront 側で対応しました。

Default root object: index.html
Custom error response: 404.html

4 HTTP → HTTPS リダイレクトを有効化

CloudFront Behavior の Viewer Protocol Policy を Redirect HTTP to HTTPS に変更。 http://imai.me へのアクセスは自動的に HTTPS にリダイレクトされるようになりました。

既存の CodePipeline デプロイはそのまま動作しています。 デプロイ先の S3 バケットを変えていないので、CI/CD パイプラインには一切手を入れずに済みました。

改善後の構成

現在の構成を図にすると、こうなります。

User
https://imai.me/
↓ DNS resolution
DNS
Route 53 A Alias → CloudFront
↓ HTTPS
Edge
CloudFront + ACM
HTTPS 終端 / HTTP→HTTPS / CDN / index.html / 404
↓ OAC (認証付き)
Storage
S3 www.imai.me 非公開
CI/CD
CodeCommit CodePipeline S3 deploy

各サービスの責務を整理すると、こうなります。

Route 53

DNS 管理。CloudFront に名前解決。

CloudFront

公開フロント。HTTPS 終端、リダイレクト、CDN、OAC によるアクセス制御。

ACM

SSL/TLS 証明書。HTTPS を成立させる。

S3

コンテンツ置き場。CloudFront の配信元ストレージ。非公開。

CodeCommit + CodePipeline

ソース管理とデプロイ自動化。git push で S3 に直接同期。

Before / After

Before

  • Origin = S3 Website Endpoint
  • S3 Website Hosting に依存
  • OAC なし(S3 が公開状態)
  • CF → S3 が HTTP only
  • HTTP → HTTPS リダイレクトなし

After (Current)

  • Origin = 通常の S3 bucket origin
  • CloudFront 側で静的サイト挙動を管理
  • OAC で CloudFront 経由のみ許可
  • S3 は非公開ストレージ
  • HTTP → HTTPS リダイレクト有効

この構成の良いところ

責務が明確

DNS、HTTPS、CDN、ストレージ、デプロイ——それぞれの役割がはっきり分かれています。 「なぜこのサービスを使っているのか」を一つずつ説明できるので、 採用面接でも副業の技術紹介でも話しやすい構成です。

S3 を直接公開しない

公開経路を CloudFront に集約し、S3 はあくまで裏側のストレージとして使っています。 「誰がアクセスできるか」の制御を CloudFront 側に寄せたことで、設計として締まりました。

HTTPS 運用が自然

ACM 証明書 + HTTP → HTTPS リダイレクトで、公開サイトとして当たり前の HTTPS 運用になっています。 以前のように HTTP でもアクセスできてしまう状態は解消しました。

既存パイプラインをそのまま活かせた

デプロイ先の S3 バケットを変えていないので、CodePipeline には手を入れずに済みました。 構成改善のコスパとしてはかなり良い部類だと思います。

ほぼゼロコストで運用できる

大量アクセスがない限り、S3 のストレージ・転送量、CloudFront のリクエスト数、CodePipeline の実行回数はいずれも無料利用枠の範囲に収まります。 実質的にかかるのは Route 53 のホストゾーン維持費($0.50/月)とドメインの年間更新費くらいです。 個人サイトの維持費としては非常に軽い構成です。

残っている課題

キャッシュの即時反映 — デプロイ後に CloudFront キャッシュが残る場合があります。Pipeline 後段に create-invalidation を追加すれば解決できますが、まだ入れていません。

CodeCommit について — 2024年7月に一度は段階的廃止が発表されましたが、顧客フィードバックを受けて 2025年11月に撤回され、完全な一般提供(GA)に復帰しています。新規アカウントでもリポジトリ作成が可能です。今後は Git LFS 対応やリージョン追加も予定されているため、このまま使い続けて問題ありません。

関連する読み物

まとめ

S3 Website Hosting 依存の構成を見直し、CloudFront + OAC を正面に据えた構成に移行しました。

やったことを一言でまとめると——

S3 を「公開 Web サーバー」から
「CloudFront 専用のストレージ」に変えた。

結果として、より安全で、責務が明確で、説明しやすい静的サイト構成になっています。 個人サイトとしては十分な構成ですが、CodeCommit の移行やキャッシュ制御など、 次にやれることも見えています。