Making this blog

How is this blog made?

As the first post on my new shiny blog, I found it fitting to explain how I make this blog, and how I host it. Spoiler alert: it involves all the latest trendy things in IT :-)

Go, Hugo!

Contemplating the prospect of hosting yet another Wordpress blog did not fill me with joy. Oh, the pain: choosing the right plugins, keeping it up-to-date or risking to be hacked… Wordpress is too complex for my needs and too time-consuming for me.

So I looked elsewhere and (re)discovered the fabulous world of Static Site Generators (SSGs) thanks to Gitlab (and their excellent blog posts about SSGs: Part 1, Part 2 and Part 3) and Jessie Frazelle’s blog. Her blog is generated with Hugo, a SSG written in Go that met all my requirements:

  • a simple syntax for writing (i.e Markdown),
  • some nice themes from which I can start,
  • a simple installation process.

SSGs, and in particular Hugo, are awesome:

  • No painful WYSIWYG interfaces,
  • No execution server-side, which means a lightning-fast website and no risk of hacking,
  • The whole blog is just a bunch of text files so Git is, once again, my friend!
  • Hugo is light (a single binary of 16MB), and very fast (less than 200ms to generate this blog from scratch on a very slow machine).

To give you an example, all I had to write to begin this article was:

+++
date = "2016-07-06T20:23:24Z"
draft = true
title = "Making this blog"
image = "making-this-blog/hugo-logo.png"
tags = ["docker","aws","s3","serverless","hugo"]
+++

# How is this blog made?

As first post on my new *shiny* blog, I found it fitting to explain how I make this blog, and how I host it. Spoiler: it involves all the latest trendy things in IT :-)

To get started with Hugo, just follow the Quickstart guide. For reference, I used the Academic theme.

Building with Docker

This blog is also the occasion for me to play a little, so I decided to run the actual building of the blog in a Docker container that only has the few things I need (i.e Hugo and Pygments for syntax highlighting).

My Hugo Container

You can use it directly: download it from the Docker Hub: mrtrustor/hugo:0.15. It is very lightweight (only 24MB) because it uses Alpine as base image. The Dockerfile is available on my Github.

Building in Docker

The trick here is that, by default, Hugo will run as root in the container, but you want to be able to manipulate the generated files outside Docker. So, to fix this problem, and to get the generated files outside the container, you can run this command:

docker run --user $(id -u) -v $(pwd):/var/tmp/site mrtrustor/hugo:0.15

Assuming you are at the root of your Hugo codebase, this will mount the codebase in the container and run Hugo with your uid. At the end of the run, the generated files will be in the public folder, as they would have been if you had run Hugo normally.

Hugo is so simple to install that using Docker does not have that many benefits, but it still nice to be able to just type docker run mrtrustor/hugo:0.15 anywhere and not to worry if Hugo or Pygments are installed. Updating Hugo will also be very convenient: just change the VERSION variable and voilà.

Serverless hosting

Last but not least, as this blog is fully static, no PHP or Ruby or anything is needed server-side. This means that I can use AWS S3 to host this blog! By using S3, I do not need to worry about managing my server, uptime or almost anything. If one day performance is an issue, I’ll just add Cloudfront as CDN before S3.

AWS S3 has this neat feature called Static Website Hosting that does just what it says. It is easy to use: enable it for your S3 bucket and add a CNAME pointing on the given endpoint.

aws console

Security

To allow public traffic on the website, you must set a bucket policy as follow:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "PublicReadGetObject",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::blog.mrtrustor.net/*"
		}
	]
}

This allows anyone to read the objects in the bucket (i.e the website), but only you, as owner of the bucket, can update them.

Tying it all together

I am a huge fan of good old Makefiles, so here it is:

HUGO_VER = 0.15

all: build upload

build:
	@cd blog && \
         docker run --name hugo --user $(shell id -u) \
                    -v $(shell pwd)/blog:/var/tmp/site -p 1313:1313 \
                    mrtrustor/hugo:$(HUGO_VER)

upload:
	aws s3 sync --delete --region eu-west-1 blog/public/ s3://blog.mrtrustor.net/
	$(MAKE) clean

clean:
	@docker rm hugo >/dev/null
	@rm -r blog/public

Conclusion

This is really the ideal setup for a simple, low-maintenance blog and I am very happy with it. I can only advize you to try Hugo out! It works very well with S3 as a low-cost hosting solution.

This is all for my first post, I hope you liked it. I will continue to post technical articles on various subjects so stay tuned!