A static website is a great choice for content that doesn’t change often, and isn’t dynamic or unique to the user. Blogs, documentation, and cooking recipe sites are examples of static website use cases.
A banking or social media app would require authentication, dynamic data, etc - better suited for a web application, or Single Page Application (SPA).
How I made this blog
I wanted to keep it simple and avoid heavy blog tools like WordPress.
Some research for blog platforms took me to the Hacker News thread Ask HN: Best Blogging Platform, where Hugo was recommended. Hugo is a static site generator with a great ecosystem of themes. I chose the harbor theme, which has an appealing minimalist style.
The output of Hugo is a static site, consisting of several html/css/js files, and other common website artifacts like font files, icons, and images. A great hosting option for a static website is AWS S3. This walkthrough from the AWS docs gives detailed steps to set up the AWS resources for static website hosting.
This second walkthrough from the AWS docs sets up CDN and https.
Several AWS resources are involved:
- S3 (storage for static files, configured to host a website)
- CloudFront (CDN)
- Route 53 (DNS, custom domains)
- Certificate Manager (SSL certificate)
Technical Details
While following the above walkthroughs, I ran into a few quirks or issues, detailed below.
Nameserver mismatch between Hosted Zone and Domain
When I created an SSL certificate in AWS Certificate Manager, I added some CNAME records to my Hosted Zone, to prove ownership. I noticed that the Certificate status didn’t update to “Issued” for several days. I realized that, when I had created a Hosted Zone for my Domain, managed in AWS Route 53, there was a mismatch of nameservers. The Hosted Zone referenced one set of Nameservers, and the Domain referenced a different set. I updated the Domain (which I had ignored for several years) to reference the same set of Nameservers as the Hosted Zone.
Here are some details from the AWS docs: Adding or changing name servers and glue records for a domain
CORS issue between www subdomain and domain
I noticed that, when visiting the site using the www subdomain (ie, www.bfostdev.net), some static files like CSS, served from the bfostdev.net domain, were blocked by a (lack of) CORS policy. I fixed this by updating the CORS policy on the domain (bfostdev.net) S3 bucket, allowing GET requests from the origin https://www.bfostdev.net, with the policy JSON shown below:
[
{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"https://www.bfostdev.net"
],
"ExposeHeaders": []
}
]
Deploying changes
For now, I’m pushing changes semi-manually to production. This involves 3 commands, which:
- generate a static website from the Hugo source code
- push the updated content to the AWS S3 bucket
- invalidate the CloudFront CDN distribution, allowing changes to propagate to the CDN edge sooner than the CDN cache policy would allow
hugo -D
aws s3 sync --delete ./public s3://$BUCKET_NAME
aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths /*
Reference Material
By the time I finished, I had accrued many open browser tabs - the sign of honest work! Here are some references that I didn’t mention above. This is for my benefit as much as anything else.
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring.html
https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-cloudfront-walkthrough.html
https://docs.aws.amazon.com/AmazonS3/latest/userguide/IndexDocumentSupport.html
https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-cloudfront-walkthrough.html
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring.html
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html