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
| Acronym | Full name | What it is / why it matters (CLF-C02) |
|---|---|---|
| OAC | Origin Access Control | Current, recommended way to let only CloudFront read a private S3 bucket. Signs origin requests with SigV4. Supports SSE-KMS, all regions, more HTTP methods. |
| OAI | Origin Access Identity | Legacy predecessor of OAC. Still works but AWS recommends OAC for new setups. If the exam shows OAI, know it’s the old way. |
| CDN | Content Delivery Network | CloudFront itself — caches content at edge locations near users to cut latency and origin load. |
| ACM | AWS Certificate Manager | Issues/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]]). |
| SigV4 | Signature Version 4 | AWS request-signing algorithm. OAC uses it to prove an origin request really came from your distribution. |
| TTL | Time To Live | How long CloudFront caches an object before re-checking the origin. Invalidation forces an early refresh. |
| PoP | Point of Presence | An edge location (e.g. FRA56 = Frankfurt). Shown in the x-amz-cf-pop response header. |
| SSE | Server-Side Encryption | Encryption at rest for S3 objects (e.g. SSE-S3/AES256). OAC works with encrypted objects; OAI struggles with SSE-KMS. |
| BPA | Block Public Access | S3 safety switch (4 settings) that keeps a bucket private even if a policy/ACL would expose it. Kept ON here. |
| ARN | Amazon Resource Name | Unique ID for an AWS resource. The bucket policy scopes read access to the distribution’s ARN. |
| CDK | Cloud Development Kit | Infrastructure-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 + OAC | Public S3 website endpoint | |
|---|---|---|
| Public exposure | None — bucket stays private | Bucket readable by anyone |
| HTTPS | Yes (CloudFront) | No (S3 website endpoint is HTTP only) |
| Caching / CDN | Yes | No |
| Cost on reads | Cheaper (cached egress) | Direct S3 GET per request |
| Extras (WAF, geo) | Available | Not available |
Quick Reference — CLI commands used
| Command | Description |
|---|---|
aws sts get-caller-identity | Who am I / which account (verify auth) |
aws configure get region | Show configured default region |
aws s3api create-bucket | Create the bucket (low-level API) |
aws s3api put-public-access-block | Enforce Block Public Access (keep private) |
aws s3api put-bucket-policy | Attach policy allowing only the distribution |
aws cloudfront create-origin-access-control | Create the OAC |
aws cloudfront create-distribution-with-tags | Create the distribution (+ tags) |
aws cloudfront get-distribution | Read status / domain name |
aws cloudfront wait distribution-deployed | Block until Deployed (built-in waiter) |
aws s3 sync ... --delete | Upload content, mirror deletions |
aws cloudfront create-invalidation --paths "/*" | Clear the edge cache |
aws cloudfront get-invalidation | Check 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-1for CloudFront: distributions are global, but ACM certs for CloudFront must live inus-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 passLocationConstraintforus-east-1(it errors); it IS required for every other region.- Delete order: a distribution must be disabled AND
Deployedbefore it can be deleted — the destroy script waits for you. s3 sync --deletemirrors 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-1only. - Default
*.cloudfront.netURL already has free managed HTTPS — no ACM needed. A custom domain needs an ACM cert inus-east-1+ an alternate domain name + a DNS record (done formimifasol.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]]