Meta Hello World
It has been a long time since I authored a blog, and even longer attempted to maintain it on a semi-regular basis. The last post in my old blogger.com hosted tome dates to June 2010. What’s 10 years between friends?
I have an intention to use this blog as a forcing function for my hobby interests. I spend a lot of time on projects and producing content in my day job, which leaves me weary and reluctant to do the similar things in my own time. Annoyingly, i actually quite like building and writing about things, so the intention of re-starting a blog is to give me an outlet for discoveries, thoughts, projects, that just don’t fit in elsewhere. Maybe, i’ll even finish some things as a consequence of wanting to write about them. Maybe.
I thought as a first post, it might be interesting to document how I’ve built this little project. Much like code should be self-documenting, perhaps this blog should be, so that i can manage to maintain it when i go 3 months without posting and forget all the tooling i devops’d (read: copypaste’d from stack overflow) together.
Basic Components
I use and endorse Serverless approaches to work as much as possible these days, so I have approached this project with this in mind. The blog engine itself is Hugo. Probably a conservative choice, but I use this also for some functions in my day job, so it’s relatively familiar, and I tend to like my software to be a little battle hardened anyway.
Publishing wise, i’ve built out a deployment pipeline via GitHub Actions using S3 and CloudFront as hosting services. My workflow goes something like:
- Clone repo from private Github repository to whatever computer i’m working on this time (there are too many).
- Using Hugo CLI, create a new post as a markdown file
- Write, write, write
- Preview locally, hugo serve is pretty useful.
- Periodically commit the post to the repo so i don’t lose it!
- When i’m ready to ship, modify the post attributes so ‘draft: false’ and push to upstream.
- Github actions kick in, deploying a container to a build runner which runs Hugo to build the site.
- Once the site is built, another action kicks in to sync the output to my S3 bucket
- You read this post and hopefully everything goes smoothly.
This workflow ticks a few boxes for me: it’s very cheap, it involved learning something new (Github Actions), and it’s ultimately backed by something I spend most of my time with (S3/CloudFront).
For doing the deployment, I merged together two useful Github actions that I found with very minimal research:
My deployment action looks something like this:
name: publish
on:
push:
branches: [ mainline ]
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.75.1'
# extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: jakejarvis/s3-sync-action@master
with:
args: --follow-symlinks --delete
env:
AWS_S3_BUCKET: 'mybucketnamehere'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'ap-southeast-2' # optional: defaults to us-east-1
SOURCE_DIR: 'public' # optional: defaults to entire repository
Experimenting with Github actions was really intuitive and the overall copy-pasta journey I went on got me to results within half a dozen failures due to simple errors, which is a pretty good user-experience in my book.
Once I had the publishing pipeline built, I needed a hosting platform also. In order to get a Hugo blog to work with a S3 bucket, I found I needed to use the Static Website feature of S3, and point CloudFront at this endpoint (rather than the S3-Origin integration that CloudFront makes very straightforward). I needed the Static Website feature in order to configure a redirect policy as Hugo creates links to content without the trailing ‘/index.html’ in the path, assuming you’re on an Apache or similar webserver that just infers this for you. S3 doesn’t do that out of the box, so the trick was to add a rewrite rule to the S3 Website configuration as follows:
[
{
"Condition": {
"KeyPrefixEquals": "/"
},
"Redirect": {
"ReplaceKeyWith": "index.html"
}
}
]
Once configured, everything seems to be functioning as it should be, hooray for technology.
Wrap up
It’s funny, looking back at those old blog posts, in 2010 I was talking about needing a reliable/easy DNS host (Route53 has solved that one for me) and cost effective hosting and storing where I was willing to spend something like $20-40/month. I’m pretty sure the budget for this blog will come in well below $0.10/mo once i take into account all the moving parts.