I’ve been meaning to get off Medium for a while so decided to self-host these posts. Things have changed quite a lot since the last time I did this, which is probably approaching twenty years ago.

The page you’re seeing is coming from nginx image hosted on Google Cloud Run, which contains a site generated by Hugo. Google Cloud Build is used to build this image and deploy it to Google Cloud Run.


Add markdown files to the posts directory and edit with any editor or in a browser through GitHub. Manage changes with git branches, collaborate through PRs. Content as code. Couldn’t be much simpler.

Deployment steps

When a change is pushed to master, Google Cloud Build receives a notification from GitHub. It then:

  • Clones the blog repo
  • Runs hugo via a custom Cloud Build builder (basically just a Docker image containing the hugo binary. The build process assumes that this image has already been built and is available.)
  • Copies the built site from public/ to an image extending nginx and pushes it to the gcr.io registry
  • It replaces the running container in Cloud Build with the new one

See cloudbuild.yaml to see how it all fits together.

One thing I’d like to improve is the removal of old builds I’ll never want to run again. Cloud Run keeps these to allow for easy rollback, among other things. As this is just my blog, I don’t really have a particular SLA to uphold, but it’s good to know it’s there.

Why Cloud Run?

I really liked using Cloud Run for another project and it seemed a simple way of getting off Medium. It has good monitoring, simple support for custom domains and automatic certificate provisioning. Cloud Run is astonishingly good.