Booting the blog
$ ./boot.sh
[ ok ] mounting markdown...
[ ok ] rendering static html...
[ ok ] syncing to s3...
[ ok ] invalidating cloudfront...
ready.
Welcome to the first post. This blog is intentionally boring infrastructure: markdown files in a git repo, compiled to static HTML by a small Node script, served from S3 behind CloudFront. No servers, no database, no runtime.
How a post becomes a page
- I write a
.mdfile incontent/posts/. build.jsparses the frontmatter and renders the body to HTML.- The output lands in
dist/posts/<slug>/index.html. - A push to
maintriggers GitHub Actions, which syncsdist/to S3 and invalidates the CDN cache.
Private S3, public site
The old way to host a static site on AWS was to flip an S3 bucket to “static website hosting”, make it public, and point a CNAME at it. It works, but the bucket is wide open and you can’t easily add HTTPS or security headers.
This blog does it the modern way:
- The S3 bucket stays fully private (Block Public Access on).
- CloudFront Origin Access Control (OAC) signs requests from the CDN to S3.
- The bucket policy only trusts that one distribution.
The payoff:
- No public bucket to misconfigure.
- Real HTTPS via ACM, terminated at the edge.
- Response headers policy adds HSTS,
X-Content-Type-Options, and a CSP. - A tiny CloudFront Function rewrites
/posts/foo/to/posts/foo/index.htmlso clean URLs work without server logic.
It’s a few more lines of Terraform, but the result is a site that’s private at rest and locked down at the edge.
Why serverless
- Costs cents per month.
- Scales to zero when nobody’s reading.
- Nothing to patch at 3am.
The best server is the one you don’t run.
More soon.