You may have noticed that this site is a bit different in the past few days. It is simpler, faster, and overall nicer!

As I’ve published few days ago, I have decided to make some changes to my existing website and have decided to set it up as a statically generated website powered by Hugo, using amazing PaperMod theme with addition of Commento; for the only dynamic thing on this site; comments.

It is hard for me to decide from where to start, so, I guess from the beginning?

Reasons for switching

I’ve been flirting with this idea of having the static site for some time now. The appeal of having statically generated website, which can be scaled via any CDN easily has been great to me.

There are certainly some upsides to that kind of hosting. For example, you don’t have to care about how the site will be processed, if you’ll have enough CPU performance, one less thing to troubleshoot when hitting bottlenecks, etc.

With plain HTML website, the only real thing you have to care about is how to distribute those static HTML files to the visitors.

And depending on the hosting route you choose, you have far less of a server maintenance. You also don’t have any databases to manage and not to mention, far less services that can fail.

Going way off-topic, but to be clear, managing servers never presented an issue to me. Au contraire, reason for starting this blog was basically to play with those technologies a bit more, to learn, explore, share and document my learning’s along the way. To this day I prefer this way of learning, trying out things “in production” - even if the “production” is my personal website. There are numerous reasons on why you might have blog of your own, learn in public etc. But that’s perhaps a topic for some other article in the future.

Abandoning Wordpress

Don’t get me wrong, I don’t have anything against Wordpress. It is not my intention to bash it or whatever. I really like the system, and its world wide web domination has shown that many others do like it very much as well.

Switching away from Wordpress was not a lighthearted decision to make. I really like its way of editing articles, and having something to scratch my blog notes on, even when I’m “on the road” ♫.

It has been my faithful accomplice from the start of this blog, well, hell, for more than 7-8 years.

Before you mention, I’m aware there are ways to make Wordpress static, but all those solutions seem somewhat hacky to me.

Website setup and tweaks

Infrastructure and webiste setup

With Hugo, site is statically generated into the public/ folder and to serve it, you basically have to drop the contents of that folder onto some web server and your job is done.

The route I decided to go with though, is to host all sites on the Amazon’s S3, distribute files via CloudFront service and to do some custom logic with Lambda@Edge. So pretty much centered around AWS.

S3

There’s nothing much to say about this to be honest. Hugo has a native support for deploying to the S3 and it was a matter of configuring my local AWS-CLI with account that has sufficient rights to write objects into the destination bucket and setting configuration to the following:

deployment:
  targets:
    name: "tomica-website"
    url: "s3://MYBUCKETNAME?region=SOMETHIn"
    cloudFrontDistributionID: "CLOUDFRONT_DISTRIBUTION_ID"

Then it was only a matter of running:

hugo
hugo deploy

And be done with it. Hugo took care of the rest. With the last line it even creates CloudFront invalidation to propagate changes to the Edge locations. Of course, for that, your user has to have sufficient rights to do the invalidation part as well.

CloudFront

Amazon’s CloudFront service is a CDN service, much like CloudFlare, minus the web application firewall things.

To set it up, I created a new distribution, pointed it to the S3 bucket for Origin and assigned ACM certificate for SSL termination. I created it with “index.html” as a Default Root Object and that was pretty much it (except for some issues, but more on that later).

Since my S3 bucket is set to block any public access, I also had to generate access policy which would allow CloudFront to connect to the S3. This was helpfully exposed to me as a simple check-box in the creation wizard.

After deploying the site I’ve initially observed that while the main site worked fine, all sub pages would return an error. Error was “Access denied”, where in fact, underlying issue was that CloudFront was trying to access pretty url such as “/about-me” as an object within the bucket. That object, naturally, did not exist.

Hugo’s way of generating site is to create that “/about-me/” as a folder on the filesystem and create index.html inside it.

You might ask now, how’s that CloudFront did not request index.html then? But you have to remember that CloudFront is only a CDN, it caches things and forwards requests to bucket basically. That index.html as “Default Root Object” is just that, default object which is served if you don’t specify anything.

If I opted to use plain S3 setup, there’s an option to basically have something like “Directory Index”, but this is not the option on the CloudFront. That seemed like a huge issue to me, but luckily it was easily solved.

Lambda@Edge

One pretty neat thing Amazon offers is to run a small piece of code, a function if you wish, at the edge. It is something like “Workers” by CloudFlare. Basically, each edge location can execute simple Lambda function (a piece of code) on each request that hits your CloudFlare distribution. You get some Input as LambdaInput and you need to output some LambdaContents. More on this in official Customizing Content at the Edge with Lambda@Edge AWS Docs article.

Using and running that Lambda is pretty cheap, and pretty fast (I’ve seen no noticeable slow-down).

So, what’s the logic, or piece of code we need to run inside that Lambda you might ask? Well, perhaps something that would take the request, and append /index.html to it? :-)

This is exactly what I did, and there was even a ready-made function for me to deploy in a single click called standard-redirects-for-cloudfront

To be honest though, this is an JavaScript function, written for older runtime, so I might just rewrite it into GO Lang or Python or whatever I decide to learn down the road. :-) “For the science”, just to be clear about it.

Commento for comments

Many static sites opt-out from using comments on their sites. And although I don’t get plenty of them, I still like getting the feedback that way, so I wanted to keep them while transitioning to Hugo.

This somewhat goes against the static website mindset, but in the end I’ve decided to go with an embeded Javascript for loading comments from the Commento system.

Commento system is really neat piece of software, which is basically “Open-Source Disqus”. It is not so polished as Disqus, but hey, it is really nice never the less, and it is quite easy to set-up and self-host.

For now I’ve decided to deploy it on a single VPS, and embed it into the each article page at the bottom. In the future I will most likely deploy that setup to be ran on the Kubernetes, but for now, this is more than enough. And besides, even if that system goes down website will continue working just fine.

For now, Commento is the best thing I could find. I’ve also seen Isso which might be worth trying, but as I see it uses sqlite which is not so scaleable or highly-available backend, considering it resides on a single file on-disk. This might be a viable alternative for you though, so, just putting it out there.

Do I really need scalability for comments? Not really, up until now Wordpress worked just fine for me on a single small VPS, so all of this is overkill and unnecessary flexing :-)

BTW, all of the previous comments were imported into the new system. What I had to do was basically:

  • Export all comments from the Wordpress
  • Create Disqus site, and import all of the comments there
  • Export comments from Disqus
  • Import them into the Commento

I wish there was the simpler way, but what can you do…

There was one more thing I wanted to do before calling it a day, and that was to assign all of my comments to my Commento account so it is clearly visible where I gave my response.

This was somewhat tedious job in updating all of the rows with my new commenterhex ID :-) A bit of PostgreSQL magic… Perhaps better explained some other time.

Results

In the end, I’m pretty happy with the results. Site is quite nice thanks to the excellent theme, it was easy to set up and tweak to my liking, it has dark and light theme which is automatically chosen by the browser and can even be toggled manually, so what’s there more to ask…

Response time for the site has gone down considerably, immediately after the switch:

And what’s even better, those results are pretty much consistent across the world, no matter where you’re reading this from. That’s the beauty of distributed setup like CloudFront.