This post is describing how I set up a blog using Hugo and Gitlab’s static site support. I wanted a place to post some of my own code in addition to my public git repositories. Somewhere I can also expand on my train-of-thought versus just posting straight code with a comment or two peppered in between. I used to host a static site on a RPi3 locally; however, I recently decided I wanted to use off-site storage as a form of redundancy with extra reliability. I still host a git server locally using Gitea, but the blog portion has been removed. If interested, Gitlab also offers a way to host a repository locally; however, I went with a lightweight alternative to save on resources.

Gitlab is a web-based DevOps tool built around git that also provides issue-tracking and continuous integration/continuous deployment pipelines. There’s a free tier which includes all stages of the DevOps lifecycle and 2000 CI/CD minutes. It also gives you the ability to bring your own CI runners and production environments. Likewise, you can also locally host a Gitlab server under a similar hierarchy. Free gets you the base open-source core. Anything more will cost you. Git is a free and open-source distributed version control system used to coordinate work between programmers. It was designed by Linus Torvalds to help with another of his projects, the Linux kernel.

Hugo is a static site generator, meaning everything has fixed content versus dynamic (i.e. can change depending on user input). There are alternatives, like Jekyll, that can serve up static sites; however, I’ve been set on Hugo for awhile now due to its simplicity and speed. I will say that more people seem to lean towards Jekyll, which is important to note when considering support and features. Hugo builds the .html files with a theme you select, including css and javascript, and it will wither host it from memory using the built-in server or dump the .html files into a directory you can link to your own web sever.

Install Hugo

First thing to do is install Hugo. I’m running an Arch system where the default package manager is pacman. These instructions were taken from Hugo’s instructions on how to install and how to get started.

$ sudo pacman -Syu hugo

That’s it. Hugo should now be installed. Next, you’re going to want and get a site going, which you’ll then push to Gitlab. These instructions are taken from another page from Hugo that specifically addresses using Gitlab as a host. Create a project using one of Hugo’s commands. After that your going to find a theme and create a submodule, edit some configurations, commit, and push. For this example and this blog, I’m using the theme bento. In the following example, replace blog with the name of your project. Hugo will create a directory with that name with the necessary parts.

$ hugo new site blog
$ cd blog
$ git init
$ git submodule add themes/bento
$ echo 'theme="bento"' >> config.toml
$ hugo server -D

The last command $ hugo server -D will use Hugo’s internal web server to host your page locally. I should also note even Hugo does not recommend you use this server for production, only for development. You can normally access your page at https://localhost:1313.

It was at this point, however, that I ran into my first set of problems.

It kept giving me errors about not finding any layouts for the site I was tying to build. From what I read, this came from an issue that prevented the creation of your CSS files.

It kept giving me errors about not finding any layouts for the site I was tying to build. From what I read, this came from an issue that prevented the creation of your CSS files.

This was resolved by reinstalling nodejs, npm, and the relevant dependencies.

$ sudo pacman -S nodejs-lts-erbium
$ sudo pacman -S npm
$ sudo npm install postcss-import tailwindcss postcss-reporter @tailwind.ui

When I ran $ hugo server -D again, it followed through; however, another issue popped up where my images weren’t being displayed. The solution didn’t really warrant the amount of time I spent on it. I don’t really know how Hugo handles absolute and relative paths, but the link in my images were wrong. I compared the image for the home page, which was working, and that of my post. The home page had the path https://localhost:1313/blog/images/san_diego_city_view.jpg; whereas, the image in my post had the path https://localhost:1313/images/hugo_and_gitlab_1.png. For image pathways, adding the /blog fixed everything. If for some reason, you’re having trouble getting things to show up, pay attention to the paths. If there are no errors to go off of, that will help you figure things out.


Hugo is up and running. Now, the goal is push this project to Gitlab and have them host your static site.

$ vim .gitlab-ci.yml

vim is the text editor I prefer; however, use whatever editor you prefer to edit .gitlab-ci.yml.This is a small docker script that tells Gitlab on how to process your page in a pod.

# .gitlab-ci.yml

image: monachus/hugo

	- hugo
		- public
	- master

After that, take a second to edit your config.toml file as well. The following is the default config.toml file that Hugo creates in your main site directory. The only difference is the line you added above specifying the theme. More parameters can be added if needed. Refer to your theme’s documentation or website. Their live version usually has posts summarizing how to use their theme. Make sure you change the baseURL to point to your actual blog. Gitlab places your repo under the url; however, your page will be located under the link

# config.toml

baseURL = ""  # change your site's url
languageCode = "en-us"
title = "Excercies in Programming and Analytics"
theme = "bento"

Last file you’re going to create is a .gitignore file, which is self-explanatory. It tells which files git will ignore when adding to a commit.

$ vim .gitignore
# .gitignore


/public is the directory Hugo creates to :house the .html files for your site when you use $ hugo -D. You don’t need this since Gitlab will produce its own .html files through the docker script you wrote up above. /node_modules and package-lock.json were both created npm when I reinstalled the dependencies to deal with the issue above. If you didn’t have any problems, you could omit those lines.

Then that’s it. Double check you’re in the top-level directory of your project, make a commit, add the origin, and push your project to Gitlab. Notice this is the url of your project, which ends in a .git extension, and not your website.

$ git add .
$ git commit -m 'Initial commit'
$ git remote add origin
$ git push -u origin master

Give it a minute or two. Gitlab will open a docker pod to process your script.

You can check the status if you go to CI/CD > Pipelines under your project.

You can check the status if you go to CI/CD > Pipelines under your project.

Once it reads ‘passed’, you should now have a Gitlab hosted static site.


Another edit for those that want to use Bokeh with Hugo. The instructions I followed are found on their user guide Embedding Bokeh Content. Make sure the following elements are included somewhere in your script alongside all the other Bokeh code:

from bokeh.resources import CDN
from bokeh.embed import file_html

html = file_html(plot, CDN, "some title")

You can also use the html file Bokeh spits out when using output_file and show/save. Both default into using CDN for the BokehJS. file_html is meant to be used with custom templates.

Just stick the source in an iframe similar to the image up top:

<iframe src="/blog/bots_and_bokeh/histogram.html" width=100% height=500></iframe>

If everything works correctly, you should see your plot.