Creating a Hugo site from scratch, when knowing nothing about Hugo can be a pain. Here we will go through the steps needed, and try to explain everything we do.
Intro
Aim
At the end of this article, we will have a static Hugo website, with a nice theme, and with Continuous Integration enabled, for automatic publishing of new contents through sFTP.
This documentation was first written to share the knowledge between authors of this blog. I think it can also be useful for other people but you will have to adapt it to your needs.
Requirements
- A place to host a static website
- A GitLab account on any GitLab instance (we use https://0xacab.org)
- Terminal skills
- Basic Git and GitLab knowledge
Environment
We will work on Debian GNU/Linux, version 12 (Bookworm).
We need to install hugo (not from APT) and git (from APT).
We will also use a Gitlab instance to store our source code and automatically
publish content we push to the repo.
Getting hugo using Podman or Docker
Depending on the theme you choose, you might need a more recent version of
Hugo than the one available in Debian. As I’ve chosen PaperMod, I always
need a modern Hugo version, which Debian doesn’t provide, so I take hugo from
a docker image.
- Install
podman:sudo apt install podman - Add a shell alias to use hugo from podman: in ~/.bashrc, add:
alias hugo="podman run --rm -it -p 1313:1313 -v ./:/src docker.io/hugomods/hugo:std-base"
After closing and reopening the terminal, run hugo and see if it works.
Navigate to a hugo source and try to build.
To update hugo, run podman pull docker.io/hugomods/hugo:std-base.
Let’s do it
Create a new site and have it tracked by Git
- This will create a folder called ‘mysite’ with default Hugo files:
hugo new site mysite - Initialize the website repo:
cd mysite git init # Let's call the branch "main" instead of "master" git branch -m main git add . git commit -m "New hugo site" - Add a remote, use it by default and push to it:
git remote add origin ssh://mygitlabinstance/mysite/mysite git push --set-upstream origin main
Theme stuff
First thing will be choosing a theme. Pretty dramatic thing to do. I’ve chosen PaperMod because it doesn’t call make external calls, it supports multiple authors (but no author box), and is multi-language.
- Once we’re settled with a theme, lets add it as a submodule of our
Git repo. I recommend reading about submodules, seems like they
can be picky to use.
(adapt the link to your need)
git submodule add https://github.com/adityatelange/hugo-PaperMod/ themes/papermod - Index the new folder containing our submodule. From the git website repo
point of view, this folder is actually a file. See
git status,git difforgit log -p. This file contains a reference to the HEAD commit of the submodule. When pulling the website repo, git will checkout the submodule to this commit. So we have to commit changes to that file when the submodule changes.git add themes/papermod - Index the .gitmodule file, which holds submodules config:
git add .gitmodules - Commit!
git commit
Make changes to the theme
Layout changes
If one wants to make changes only to the files in the layout/ theme
directory, best solution is to copy these files to the layout/ directory of
the website and change things there.
All kind of changes
To make broader changes to a Hugo theme, we must set up the submodule so that we can make changes to it, and push these changes to a repo we own.
Prepare the repo
- First thing will be to rename the remote
originof the submodule repo toupstream, and add our own new repo asorigin. This new repo will only contain the theme and modifications we made to it. This repo must be public if you want others to clone your main repo.cd themes/papermod git remote rename origin upstream git remote add origin ssh://gitprovider.net/me/papermod - And let’s set our repo as default, and push the theme to our repo:
git push --set-upstream origin - Now we have to change the submodule URL in our main repo.
First thing is going back to our repo’s root, then we tell git to change the
submodule URL to our new repo.
Note: the “themes/papermod” part must exactly match what’s in
cd ../.. git submodule set-url themes/papermod ssh://gitprovider.net/me/papermod.gitmodules. - Now that we’ve changed the submodule’s URL, we have to commit that.
git add .gitmodules git commit
Do the modifications and push them
This part wont be detailed, but:
- make your modifications
- commit them locally
- push them to the theme-dedicated repo created before
- commit the main repo submodule change (so that the main repo knows what commit of the submodule to use, when cloning the main repo for example)
- push main repo
Update theme
When using the theme upstream repo as submodule URL
Updating the theme should be pretty easy.
- Go to the theme directory, and have git apply updates:
cd themes/papermod git pull --ff-only - If you have files in the website
layout/folder, you may check they are still compatible with the theme new version. - Commit changes on the main repo
cd - git add themes/papermod layouts/ git commit
When using our own repo to store the theme
- Go to the theme directory, pull changes, and replay our local commits (if
any) on top:
cd themes/papermod git pull --rebase upstream master - Merge conflicts if any
- Fix local changes in the main repo’s
layout/if needed - Push changes to our repo of the theme:
git push - Update the website repo with the up-to-date commit reference:
cd ../.. git add themes/papermod git commit - Push our main repo
git push
Publish content
- Read Hugo documentation! I recommend starting with https://gohugo.io/getting-started/directory-structure/ and follow the links.
- Read your theme documentation!
- Hugo uses Sections, meaning folders in
content/. In the config file we can setmainSections, these will be the sections displayed when listing posts on the frontpage for example. - To create a new article or page in the
postssection, we can use the hugo command:Hugo will createhugo new posts/new-article.mdcontent/posts/new-article.mdbased on a template. It will decide which template to use using the section of our new article (ie.posts). Templates can be found in thearchetypes/directories of the website and the theme. In this example, Hugo will try to findposts.mdand use it as the template, and default to_default.mdor Hugo default’s template. - Commit and push!
Use Gitlab CI/CD to automatically push changes to the website
In our case, we use sFTP to transfer file to our website host.
Configure GitLab
- In our Gitlab project we have to enable
CI/CD. Follow GitLab’s documentation. - In the project Settings, CI/CD, Variables: add variables you don’t want to
publish in your repo, such as
sftp_host,sftp_port,sftp_user, andsftp_pass.
Configure CI/CD actions in our repo
- All the config happens in
.gitlab-ci.yml:image: alpine:latest deploy: variables: # Have git fetch the theme submodule GIT_SUBMODULE_STRATEGY: recursive # we don't use stages but GitLab CI/CD wants a stage so let's use anything stage: deploy # Only fetch the 'main' branch only: - main # Commands to execute in the container script: # Install lftp for sFTP transfers, hugo for building the website, # ca-certificates to be able to verify our hosts' cert. - apk add lftp hugo ca-certificates # Build the website - hugo # Transfer changed files - lftp -c "set ftp:ssl-allow on; open -u $sftp_user,$sftp_pass $sftp_host; mirror -Rev public/ ./www --parallel=10 --exclude-glob .git* --exclude .git/"
Push changes!
- Using
git pushwill now trigger a job on the GitLab instance that will automatically publish changes to the website!