Self-directed · this site
How this site is built
A static Astro build served from a private S3 bucket through CloudFront, with URL rewriting and security headers at the edge and every resource declared in Terraform.
- Discipline
- Cloud · IaC
- Origin
- Private S3
- Edge
- Lambda@Edge
- Astro
- AWS S3
- CloudFront
- ACM
- Lambda@Edge
- Route 53
- Terraform
Sheet B
Specification
The shape of it
Static files in a private S3 bucket, served through CloudFront over HTTP/2 and HTTP/3 with an ACM certificate and TLS 1.2 as the minimum (see note 1). DNS is in Route 53. Every resource, including the edge function, the certificate and its validation records, is declared in Terraform.
URLs at the edge
S3 serves objects, not routes. A request for /projects/capstone has no
matching object; the object is /projects/capstone/index.html.
A Lambda@Edge function on viewer-request rewrites directory-style and
extensionless paths to their index documents. The same function, on
viewer-response, sets HSTS, X-Content-Type-Options, X-Frame-Options,
Referrer-Policy, Permissions-Policy and a strict Content-Security-Policy
(see note 2).
Caching
Content-hashed assets are served with a one-year immutable cache and HTML
with max-age=0, must-revalidate, so a deploy shows on the next page load and
no unchanged asset is fetched twice.
Verifying what ships
The build fails on a CSP violation (see note 3). Fonts are self-hosted and subset to Latin and Latin Extended, so the policy allows no third-party origin at all.
Sheet C
Notes
3 items
Sheet D
Revisions
What I would change
- 01Move the Terraform state to S3 with locking. It is local today, which is fine for one operator and wrong for any number greater than one.