In the last post on Hugo, we quickly built a simple website with a minimalist Hugo theme. But what if we decide to switch our blog to a different theme? Is it really as simple as changing the name of the theme? Let’s find out!

Why change the theme at all?

After using the Hermit theme for a bit, I realized that the light grey text on a darker grey background is a bit hard to read due to low contract, and I wanted something with more contrast: darker text and a lighter background, which is more readable especially for longer content.

One option could have been to modify the theme’s colors and keep the theme, but I decided instead to look for other themes that might have a simple, minimalist look, but with the opposite color scheme. I finally found the Nuo theme and decided to adopt it.

Using the Nuo theme

As before, I added the theme to my Git repo as a submodule:

git submodule add themes/nuo

and modified the config.toml accordingly:

-theme = "hermit"
+theme = "nuo"

Let’s try it out and see how it works!

Using the new theme

Let’s create a new page:

$ hugo new
ERROR [...] NUO theme does not support Hugo version 0.47.1. Minimum version required is 0.50

$ hugo version
Hugo Static Site Generator v0.47.1/extended linux/amd64 BuildDate: 2018-09-25T03:41:10Z

OK, we need to upgrade Hugo. I downloaded the latest version at the time (v0.55.5) and tried again:

$ ~/hugo/0.55.5/hugo new
[...]/content/ created

After updating the new page, let’s see what it looks like in our browser:

$ ~/hugo/0.55.5/hugo serve --verbose --disableFastRender

Looks good, let’s ship it!

Commit and build on GitLab

Creating a new branch for this change, pushing it to GitLab, and creating a pull request causes a new build to happen via GitLab Pipelines, and if successful, I merge into master and it is published to the live site. Here, however, it errored out with:

error: failed to transform resource: TOCSS: failed to transform
"styles/main-rendered.scss" (text/x-scss): this feature is not available in
your current Hugo version, see for more information

What does this mean? The URL in the error points to a help page on the Hugo website which says:

I get “TOCSS … this feature is not available in your current Hugo version”

If you process SCSS or SASS to CSS in your Hugo project, you need the Hugo extended version, or else you may see this error message:
error: failed to transform resource: TOCSS: failed to transform
“scss/main.scss” (text/x-scss): this feature is not available in your current
Hugo version

We release two set of binaries for technical reasons. The extended is what you get by default, as an example, when you run brew install hugo on macOS. On the release page, look for archives with extended in the name.

To confirm, run hugo version and look for the word extended.

Turns out, someone ran into the same issue as I did, and filed an issue with GitHub 2 weeks ago, but it hasn’t been fixed yet.

That said, I was really set on using the new higher-contrast theme, so what do we do in the meantime while this is not fixed?

Let’s build a custom container!

Let’s recall from our earlier post that GitLab Pipelines simply runs the hugo binary from a Docker container, so why don’t we build a custom Docker container and specify that for GitLab to use?

First, let’s look at our Dockerfile:

FROM alpine:${ALPINE_VERSION:-3.9}


ENV HUGO_EXT "tar.gz"



RUN mkdir -p "/tmp/${HUGO_DIR}" \
    && tar zxf "/tmp/${HUGO_ARCHIVE}" -C "/tmp/${HUGO_DIR}" \
    && rm -f "/tmp/${HUGO_ARCHIVE}" \
    && mv "/tmp/${HUGO_DIR}/${HUGO_BINARY}" "/usr/bin/${HUGO_BINARY}" \
    && rm -rf "/tmp/${HUGO_DIR}"

Pretty straight-forward, and nicely parameterized in case we want to build contains with other Hugo versions in the future.

Let’s build the container:

$ docker build . -t hugo-extended:0.55.5
Sending build context to Docker daemon  15.36kB
Step 1/10 : FROM alpine:${ALPINE_VERSION:-3.9}
 ---> cdf98d1859c1
Step 2/10 : ENV HUGO_VERSION "0.55.5"
 ---> Using cache
 ---> 04f45fa179c2
Step 3/10 : ENV HUGO_OS "Linux"
 ---> Using cache
 ---> 6aad8739bcf0
Step 4/10 : ENV HUGO_ARCH "64bit"
 ---> Using cache
 ---> b9764c6e3560
Step 5/10 : ENV HUGO_ARTIFACT "hugo_extended_${HUGO_VERSION}_${HUGO_OS}-${HUGO_ARCH}"
 ---> Using cache
 ---> f08e8d56e807
Step 6/10 : ENV HUGO_EXT "tar.gz"
 ---> Using cache
 ---> 2a3b40de11e4
 ---> Using cache
 ---> 42f067ac272b
Step 8/10 : ADD "${HUGO_VERSION}/${HUGO_ARCHIVE}" /tmp
Downloading  9.409MB/9.409MB
 ---> Using cache
 ---> fa131c87c0f7
 ---> Using cache
 ---> c59ed67f72d0
Step 10/10 : RUN mkdir -p "/tmp/${HUGO_DIR}"     && tar zxf "/tmp/${HUGO_ARCHIVE}" -C "/tmp/${HUGO_DIR}"     && rm -f "/tmp/${HUGO_ARCHIVE}"     && mv "/tmp/${HUGO_DIR}/hugo" /usr/bin/hugo     && rm -rf "/tmp/${HUGO_DIR}"
 ---> Using cache
 ---> d1d9f1120318
Successfully built d1d9f1120318
Successfully tagged hugo-extended:0.55.5

Great! Looks like the build succeeded; let’s run it:

$ docker run hugo-extended:0.55.5 /usr/bin/hugo
standard_init_linux.go:207: exec user process caused "no such file or directory"

Wait, does this mean the binary doesn’t actually exist where we thought we put it? Let’s check:

$ docker run hugo-extended:0.55.5 ls /usr/bin/hugo

So yes, it does, in fact, exist, and it’s in the expected location. So what could be causing the error?

$ docker run hugo-extended:0.55.5 ldd /usr/bin/hugo

	/lib64/ (0x7f323d638000) => /lib64/ (0x7f323d638000)
Error loading shared library No such file or directory (needed by /usr/bin/hugo)
Error loading shared library No such file or directory (needed by /usr/bin/hugo)
Error relocating /usr/bin/hugo: _Znam: symbol not found
Error relocating /usr/bin/hugo: _ZNSo3putEc: symbol not found
[...] => /lib64/ (0x7f323d638000) => /lib64/ (0x7f323d638000) => /lib64/ (0x7f323d638000)

Thus, looks like we’re missing shared libraries such as libstdc++ and libgcc_s from our image! But why?

After doing some research, we find other folks have run into the same issue, e.g., see

At this point, I realized that I could spend quite a bit more time on this, either extending my own Dockerfile, or using someone else’s, but then I realized that my goal was to write a blog, not hack on Dockerfiles! I also remembered that there’s a service called Netlify (highlighted by most Hugo themes) which provides very easy personal website hosting, and most importantly, it also claims to address one of my personal pet peeves with GitLab Pipelines and GitLab Pages: there’s no live preview of the site, simply a success/failure on the build run.

What if I want to see exactly what the site will look like when built?

GitLab Pages with a custom domain doesn’t support automatic certificate creation and renewal with Let’s Encrypt, so until recently, you may have noticed that my website was serving over HTTP, not HTTPS. GitLab does support you providing SSL certificates manually, but unlike GitHub, doesn’t automatically refresh them for you, and I don’t need to have another job of running a cron job to renew my certificates every 90 days (and if you don’t, your site stops working).

So now I had 2 strong reasons to consider an alternative to GitLab for hosting my site.

Enter the … Netlify

Turns out, Netlify also has a great integration with GitLab and can automatically build a preview of a branch from a merge request! And it trivially integrates with Let’s Encrypt and auto-renews! Sold.

I’ve since switched my hosting to Netlify, and now I can easily get a preview of each change before it goes live. And the site is now hosted on HTTPS. Win/win!

What’s the moral of the story? Sometimes, the solution to a technical problem is not an ever more complex Rube Goldberg machine in the form of an intricate Dockerfile with a custom build pipeline, but simply a change of approach, which brings with it additional benefits, with just a little up-front setup, and no ongoing work.