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:

  1. Clone repo from private Github repository to whatever computer i’m working on this time (there are too many).
  2. Using Hugo CLI, create a new post as a markdown file
  3. Write, write, write
  4. Preview locally, hugo serve is pretty useful.
  5. Periodically commit the post to the repo so i don’t lose it!
  6. When i’m ready to ship, modify the post attributes so ‘draft: false’ and push to upstream.
  7. Github actions kick in, deploying a container to a build runner which runs Hugo to build the site.
  8. Once the site is built, another action kicks in to sync the output to my S3 bucket
  9. 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.