Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


title: “CloudFront + S3 Deployment” created: 2026-10-26 updated: 2026-10-28 type: cheat-sheet tags:

  • aws
  • certification
  • cheat-sheet
  • cloudfront
  • s3
  • oac
  • cli
  • clf-c02

CloudFront + S3 Deployment — Cheat Sheet

Quick reference for the S3 + CloudFront + OAC static-site pattern and the AWS CLI commands used to deploy it. Built from the real Phase 1 deployment (see runbook [[deploy-static-site-s3-cloudfront-oac]]).

Acronyms

AcronymFull nameWhat it is / why it matters (CLF-C02)
OACOrigin Access ControlCurrent, recommended way to let only CloudFront read a private S3 bucket. Signs origin requests with SigV4. Supports SSE-KMS, all regions, more HTTP methods.
OAIOrigin Access IdentityLegacy predecessor of OAC. Still works but AWS recommends OAC for new setups. If the exam shows OAI, know it’s the old way.
CDNContent Delivery NetworkCloudFront itself — caches content at edge locations near users to cut latency and origin load.
ACMAWS Certificate ManagerIssues/manages free public TLS certs. For CloudFront, the cert must be in us-east-1. Not needed for the default *.cloudfront.net URL; required once a custom domain is added (Phase 2, now done — see [[deploy-custom-domain-route53-acm-cloudfront]]).
SigV4Signature Version 4AWS request-signing algorithm. OAC uses it to prove an origin request really came from your distribution.
TTLTime To LiveHow long CloudFront caches an object before re-checking the origin. Invalidation forces an early refresh.
PoPPoint of PresenceAn edge location (e.g. FRA56 = Frankfurt). Shown in the x-amz-cf-pop response header.
SSEServer-Side EncryptionEncryption at rest for S3 objects (e.g. SSE-S3/AES256). OAC works with encrypted objects; OAI struggles with SSE-KMS.
BPABlock Public AccessS3 safety switch (4 settings) that keeps a bucket private even if a policy/ACL would expose it. Kept ON here.
ARNAmazon Resource NameUnique ID for an AWS resource. The bucket policy scopes read access to the distribution’s ARN.
CDKCloud Development KitInfrastructure-as-code in a real language. Candidate for a later IaC rewrite (Phase 1 deploy is CLI; Phase 2 custom domain was done via the console).

Why a private bucket (not S3 static website hosting)?

Private bucket + CloudFront + OACPublic S3 website endpoint
Public exposureNone — bucket stays privateBucket readable by anyone
HTTPSYes (CloudFront)No (S3 website endpoint is HTTP only)
Caching / CDNYesNo
Cost on readsCheaper (cached egress)Direct S3 GET per request
Extras (WAF, geo)AvailableNot available

Quick Reference — CLI commands used

CommandDescription
aws sts get-caller-identityWho am I / which account (verify auth)
aws configure get regionShow configured default region
aws s3api create-bucketCreate the bucket (low-level API)
aws s3api put-public-access-blockEnforce Block Public Access (keep private)
aws s3api put-bucket-policyAttach policy allowing only the distribution
aws cloudfront create-origin-access-controlCreate the OAC
aws cloudfront create-distribution-with-tagsCreate the distribution (+ tags)
aws cloudfront get-distributionRead status / domain name
aws cloudfront wait distribution-deployedBlock until Deployed (built-in waiter)
aws s3 sync ... --deleteUpload content, mirror deletions
aws cloudfront create-invalidation --paths "/*"Clear the edge cache
aws cloudfront get-invalidationCheck invalidation InProgress/Completed

Common Patterns

Check deployment status / progress

DIST_ID=<your-dist-id>

# Status: InProgress -> Deployed
aws cloudfront get-distribution --id "$DIST_ID" \
  --query 'Distribution.{Status:Status,Domain:DomainName}' --output table

# Block until live
aws cloudfront wait distribution-deployed --id "$DIST_ID"

Test the live site

DOMAIN=<id>.cloudfront.net
curl -sI "http://$DOMAIN"  | head -n1   # expect 301 -> HTTPS
curl -sI "https://$DOMAIN" | head -n1   # expect 200

Useful response headers to read:

  • x-cache: Hit from cloudfront → served from edge cache (not origin)
  • x-amz-cf-pop: FRA56-P5 → edge location (Frankfurt)
  • x-amz-server-side-encryption: AES256 → objects encrypted at rest

Upload only changed files + refresh cache

aws s3 sync ./public/book/ s3://my-bucket/ --delete
aws cloudfront create-invalidation --distribution-id "$DIST_ID" --paths "/*"

Minimal private-bucket policy (OAC)

{
  "Effect": "Allow",
  "Principal": { "Service": "cloudfront.amazonaws.com" },
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::<acct>:distribution/<DIST_ID>" } }
}

Tips & Tricks

  • us-east-1 for CloudFront: distributions are global, but ACM certs for CloudFront must live in us-east-1. Keep everything there to avoid surprises.
  • New distribution ≈ 5–10 min to deploy; the domain may not resolve until then — expected, not a failure.
  • Invalidations: first 1,000 paths/month are free; /* counts as one path.
  • create-bucket + us-east-1: do NOT pass LocationConstraint for us-east-1 (it errors); it IS required for every other region.
  • Delete order: a distribution must be disabled AND Deployed before it can be deleted — the destroy script waits for you.
  • s3 sync --delete mirrors deletions to the bucket — safe here (bucket is dedicated to the site), dangerous on shared buckets.

Exam Gotchas (CLF-C02)

  • OAC = modern, OAI = legacy → prefer OAC.
  • CloudFront cert → us-east-1 only.
  • Default *.cloudfront.net URL already has free managed HTTPS — no ACM needed. A custom domain needs an ACM cert in us-east-1 + an alternate domain name + a DNS record (done for mimifasol.com — see [[deploy-custom-domain-route53-acm-cloudfront]]).
  • Private bucket + CloudFront is the recommended secure static-site pattern, not the public S3 website endpoint.
  • Block Public Access is defense in depth — keep it on even with a scoped policy.

See Also

  • [[deploy-static-site-s3-cloudfront-oac]]
  • [[deploy-custom-domain-route53-acm-cloudfront]]
  • [[route53-acm-cloudfront-custom-domain-cheat-sheet]]
  • [[cloudfront-custom-domain-vs-default-url]]
  • [[adr-001-s3-cloudfront-personal-site-hosting]]
  • [[aws-cli-s3-commands]]
  • [[s3-access-without-public]]
  • [[s3-block-public-access]]