/ #personal #automation 

My Wordpress to Hugo Migration #1 — Why?

TL;DR — I migrated my self-hosted Wordpress in June 2019 to a static site generator (Hugo) hosted using AWS services. I only finalized my hosting and publication workflows in April 2020. In this series of 4 articles, I will describe the motivation to change, the challenges, but also how I’m hosting my blog and what my publication workflow looks like.

Articles in the series:

  1. Why switching from Wordpress to Hugo? < this article! \o/
  2. Hosting a static website
  3. Switching to Hugo
  4. Publication workflow

You will find below the list of tools I’m using:

  • Framework: Hugo
  • Editor: whatever supports Markdown :)
  • Source Control: Git / GitHub
  • Publication: GitHub Actions
  • Hosting
    • DNS: AWS Route53
    • SSL: AWS Certificate Manager
    • Storage: AWS S3
    • CDN (Content Delivery Network): AWS CloudFront
    • URL rewrite: Lambda@Edge
  • Hosting Deployment: Terraform Cloud

I will not lie; it’s a complex migration! It has to be also said that once the migration is done, writing in markdown is very different from writing in Wordpress with a WYSIWYG editor.

What is sure, is that you’ll learn a lot in the process!

Why Leaving Wordpress Behind?

You may ask (or not) why not continuing to use Wordpress? I started blogging in 2004 (on a different blog), and although a small detour by Dotclear, I have formed my opinion below on 13 years of Wordpress usage.

  • Security: Wordpress itself has some vulnerabilities, and my blog was hacked twice, both times because of some Wordpress plugins vulnerabilities.
  • Performance: I have a background in web hosting and “some” skills in that domain. Although my blog was super optimized (Memcached, Varnish, etc.), I never achieved the performance I expected.
  • Maintenance: Wordpress is “free” to use, but maintaining it is time consuming (between the Wordpress updates, plugins updates, OS updates, etc.). You can, of course, opt for a hosted version (such as wordpress.com), but that wasn’t the direction I wanted to take. You also need to leverage quite a few plugins to get to an acceptable state, each of those plugins coming with their lifecycle, security, and performance challenges.
Wordpress Updates
  • Portability: let’s face it, dynamic websites are not very portable. Between the PHP (or other) version and dependencies, dump/restore of the DB, etc., it is not straightforward to migrate a website from one system to another. It also impacts your capability to efficiently backup and restore your website/blog.
  • Miscellaneous: I didn’t like some of the latest changes in Wordpress (such as the Gutenberg editor).

That said, Wordpress is still good for a majority of people, so don’t change if you don’t have a good reason.

Static Site Generators

Based on all the challenges I had, I knew I was looking for a static site generator…but which one to pick?

A static site generator takes a different approach and generates all the pages of the website once at build time. This means there are no moving parts in the deployed website. Compared to dynamic websites (such as Wordpress), caching gets much easier, performance goes up, and static sites are far more secure (no PHP nor SQL injection).

I started to randomly test different systems (Jekyll, Ghost, and others) based on feedback I was given, but it was StaticGen that helped me to make the final decision. StaticGen highlights the top open-source projects you can not only filter them based on the language used, the license but also sort them by the number of GitHub stars or followers.

A List of Static Site Generators

Meet Hugo


When I was making my decision, Hugo stood out. With almost 43k stars on GitHub at the time of this writing, Hugo is a static HTML and CSS website generator written in Go. It is optimized for speed, ease of use, and configurability. Hugo takes a directory with content and templates and generates plain HTML pages that are served directly to the client (rule of thumb is that each piece of content renders in around 1 millisecond).

Hugo relies on Markdown files with front matter for metadata, and you can run Hugo from any directory. This works well for shared hosts and other systems where you don’t have a privileged account.

Another reason for me to select Hugo was that it is a single binary, making it very portable: they provide pre-built binaries for Windows, Linux, macOS, FreeBSD, NetBSD, and so on.

I can also take my content and host it anywhere in a snap: it’s only static files after all! This is also true for my source files: I can technically switch to any static site generator that supports Markdown.

I’m very happy about my move to Hugo, but I’m still facing a few challenges that I need to address:

  • I didn’t find a theme that jumped out at me, and I’m always looking for one. My current theme is based on Casper Two.
  • The blog is missing a search function: solutions exist, but I haven’t look at them in detail yet.
  • Comments: although Hugo ships with an internal Disqus template, it isn’t the only compatible commenting system. I activated Disqus for now, but I don’t like it much: I’ll switch to a different system later, or maybe just disable the commenting feature.

One more thing: Hugo’s behavior can change quite drastically from one version to another. With the release pace they currently have (multiple releases a month), it’s hard to keep up. The good thing is that Hugo is a single binary: it’s elementary to test by using a specific version.

A couple of months ago, I blindly changed my Hugo version in my publication pipeline, and it broke everything in my blog. Now, I’m testing the new versions locally before committing anything to my source control.

cloudmaniac.net homepage - circa April 2020

High-level Workflows

Rather than managing my blog manually, I decided to automate the various actions. I’m currently using 2 completely separated workflows:

  • One to manage my hosting environment (I’m using Terraform to manage my AWS infrastructure)
  • One to publish my blog posts

Hosting Workflow

I decided quite quickly to use AWS to host my blog. I know it was not free and maybe more complex than other solutions (such as GitHub Pages), but I wanted to get a better understanding and learn more about some AWS services I didn’t know (such as CloudFront).

I ended up writing a Terraform module that provision required AWS resources required to host a performant and secured static website: it’s a mix of Route 53, ACM, S3, CloudFront, and Lambda.

I published this module on Terraform Registry: AWS Static Website Terraform Module. It’s quite easy to use if you want to give it a try. ;)

Terraform Module to provision an AWS static website using Route53, S3, and CloudFront

I will come back in detail on how everything is done in AWS in the 2nd article of this series.

Article Publication Workflow

Using markdown as a blogging mechanism is very interesting. With Wordpress, I had to login to my blog admin area (usually wp-admin) and use the embedded editor to create and update my articles. Now, I can be offline and use any Markdown editor (sometimes even vim). Hugo comes with a hugo server command which provides a local server to render your content locally (supports live reloading). It’s worth noting that the content is rendered and served from memory (no content is written to disk). This feature is great to review your draft, tweak your CSS, and so on.

Add the -D parameter to generates draft content: hugo server -D.

Once I’m happy with the result, I commit my new content (or my changes) to a private GitHub repository. The commit will trigger a GitHub Actions workflow that will create a container, install Hugo with a specific version, clone my repository, build the content using the hugo CLI, sync the generated HTML / CSS / images to AWS S3 and invalidate my CloudFront distribution.

Hugo publication workflow using GitHub Actions

I created my own GitHub Actions that meet my needs: gohugo-action.

That’s only a high-level overview of my publication workflow: I’ll come back in detail on that topic in the 4th article of this series. Stay tuned!



Staff II Technical Product Manager, technologist with 18+ years of Networking and Security experience in Data Center, Public Cloud & Virtualization (VMs and Containers). He is a double VCDX (DCV and NV, #120), VCDX panelist, frequent VMUG/VMworld speaker and contributor to the community via this blog or social media (follow him on Twitter @woueb).