Moving to a static website using zola and github pages

Static site generators create a website by converting human readable format files i.e markdown into a web page hierarchy.

We recently moved our website from being hosted on a Debian virtual machines using Wordpress to be a static site that we generate and push to github pages for hosting.

We are very happy with the outcome as now we can;

  • Keep the website content under version control
  • Forget about having to host or maintain virtual machines
  • Forget about having to keep updating Debian and Wordpress
  • Trivially update the web site with a single git push command.

To help others make the transition we have posted some brief notes below, along with our working configurations.

Install the required tools on your workstation

Tools used

zola is a web static site generator written in rust. tabi is a zola theme used to customize the look and layout of a zola generated website. github pages supports hosting web pages directly from a github repository.

Install zola and tabi

Instal zola and tabi using the tabi-start repository. If you will be hosting your static site on github pages then call your new github repository https://github.com/<username>/<username>.github.io (so we used https://github.com/flocknetworks/flocknetworks.github.io). This is a reserved name in github that indicates you want the output of this repository to be hosted on github pages as your main domain.

Create the website content

zola configuration file

You will find the main zola config file in the root of your repository. This config file also holds the config settings for the zola theme you have chosen, in our case tabi.

ncarter@zola:~/src/flocknetworks.github.io$ ls config.toml
config.toml

This configuration file was created when you ran zola init. Below are the settings you are most likely to want to edit.

# TODO: Change base_url once flocknetworks.com DNS points to the new site at github.io.
# base_url = "https://flocknetworks.com"
base_url = "https://flocknetworks.github.io"
title = "Flock Networks"
description = "Next Generation IP Routing Suite"
author = "Nick Carter"
theme = "tabi"
...
menu = [
    { name = "brochure", url = "brochure", trailing_slash = true },
    { name = "products", url = "products", trailing_slash = true },
    { name = "white papers", url = "whitepapers", trailing_slash = true },
    { name = "blog", url = "blog", trailing_slash = true },
    { name = "tags", url = "tags", trailing_slash = true },
    { name = "about", url = "about", trailing_slash = true },
]

Check website content is correctly generated

Run zola serve which will build and then serve your website on your development workstations loopback interface on port 1111.

ncarter@zola:~/src/flocknetworks.github.io$ zola serve
Building site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
-> Creating 7 pages (0 orphan) and 7 sections
Done in 99ms.

Listening for changes in /home/ncarter/src/flocknetworks.github.io/{config.toml,content,static,themes}
Press Ctrl+C to stop

Web server is available at http://127.0.0.1:1111 (bound to 127.0.0.1:1111)

Where to store your content

The content used to generated your website is held in the well named content directory. If you have content that you want to include that is already in its final form (i.e. PDF documents, PNG images, etc) they should be placed under the static directory.

ncarter@zola:~/src/flocknetworks.github.io$ ls content/
about  archive  blog  brochure  _index.md  privacypolicy  products  whitepapers
ncarter@zola:~/src/flocknetworks.github.io$ ls static
docs  img
ncarter@zola:~/src/flocknetworks.github.io$

content/_index.md is your websites homepage stored in markdown format.

ncarter@zola:~/src/flocknetworks.github.io$ head -n 6 content/_index.md
+++
[extra]
header = { title = "Next Generation IP Routing", img = "img/flock-favicon.jpg" }
+++

Flock Networks have upgraded the IP routing suite to match the demands of the modern network. Using 30 years of network architecture and network operations experience, we have created the [third generation](https://www.flocknetworks.com/docs/third-gen-routing-suite-2020-07-27.pdf) of IP routing suite.

Publish the website content to your custom domain

DNS changes

Change the DNS settings for your domain name to point at github pages

# Github pages IPv4 DNS servers
A @ 185.199.108.153
A @ 185.199.109.153
A @ 185.199.110.153
A @ 185.199.111.153
# Github pages IPv6 DNS servers
AAAA @ 2606:50c0:8000:0:0:0:0:153
AAAA @ 2606:50c0:8001:0:0:0:0:153
AAAA @ 2606:50c0:8002:0:0:0:0:153
AAAA @ 2606:50c0:8003:0:0:0:0:153
# map canonical subdomain name www.flocknetworks.com to flocknetworks.github.io
# Do not use an `A` or `AAAA` record to map subdomains or github pages will fail the subdomain DNS check
CNAME www flocknetworks.github.io

If you already have DNS settings registered with another hosting company then delete all those records.

Add CNAME file in the static dir in your main git branch

ncarter@zola:~/src/flocknetworks.github.io$ git status
On branch main
ncarter@zola:~/src/flocknetworks.github.io$ cat static/CNAME
flocknetworks.com

If you don’t have a CNAME file then github will create one (in the auto created gh-pages branch). But be warned github pages custom domain settings will be lost on every git push and your site will become unavailable until you manually reinstate the domain settings.

Update zola base_url to point at your domain name

diff --git a/config.toml b/config.toml
index 7c2819d..e17f9a1 100644
--- a/config.toml
+++ b/config.toml
@@ -1,5 +1,5 @@
-base_url = "https://flocknetworks.github.io"
+base_url = "https://flocknetworks.com"

Add github actions YAML file to build and publish your site

Note that the zola version specified should match the version of zola you are running on your workstation. You also need to give github actions write permissions https://github.com/<username>.github.io/<username>/settings/actions.

ncarter@zola:~/src/flocknetworks.github.io$ cat .github/workflows/build.yml
name: build.yml Deploy Zola site to Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Build and deploy
        # @v0.19.2 is the zola version to use, when running zola build.
        # So match the version we are using locally (zola --version)
        uses: shalzz/zola-deploy-action@v0.19.2
        env:
          PAGES_BRANCH: gh-pages
          TOKEN: ${{ secrets.GITHUB_TOKEN }}

Add a git pre-push hook

By running zola check we prevent pushing a branch that has broken links.

ncarter@zola:~/src/flocknetworks.github.io$ cat .git/hooks/pre-push
#!/bin/bash

# Verify what is about to be pushed.  Called by "git push" after it has
# checked the remote status, but before anything has been pushed.
# If this script exits with a non-zero status nothing will be pushed.

zola check
if [ $? -ne 0 ]; then
	exit 1
fi

exit 0

Publish your site

This is simply a case of git pushing your main branch.

ncarter@zola:~/src/flocknetworks.github.io$ git status
On branch main
ncarter@zola:~/src/flocknetworks.github.io$ git push
Checking site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
Checking 31 external link(s). Skipping 0 external link(s).
> Checked 31 external link(s): 0 error(s) found.
-> Site content: 7 pages (0 orphan), 7 sections
Done in 3.0s.

Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 3.55 KiB | 3.55 MiB/s, done.
Total 5 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To github.com:flocknetworks/flocknetworks.github.io.git
 + 3e5e868...646f631 main -> main

Your website content will be built in the gh-pages branch (as specified in build.yml)

ncarter@zola:~/src/flocknetworks.github.io$ git log origin/gh-pages
commit 32d4a17f463bbbcf84ea6d3cfed20ca701d93e73 (origin/gh-pages)
Author: GitHub Actions <github-actions-bot@users.noreply.github.com>
Date:   Wed Feb 26 10:47:17 2025 +0000

    Deploy flocknetworks/flocknetworks.github.io to flocknetworks/flocknetworks.github.io:gh-pages

Tell github pages to use your custom domain

Visit https://github.com/<username>/<username>.github.io/settings/pages and set the “Custom Domain” to your domain name.

If the “Custom Domain” DNS check is failing then check your DNS changes are correct and have come live (DNS records are widely cached so the old entries need time to go stale and expire).

ncarter@condor:~$ dig flocknetworks.com | grep flocknetworks.com
; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> flocknetworks.com
;flocknetworks.com.		IN	A
flocknetworks.com.	2954	IN	A	185.199.108.153
flocknetworks.com.	2954	IN	A	185.199.111.153
flocknetworks.com.	2954	IN	A	185.199.110.153
flocknetworks.com.	2954	IN	A	185.199.109.153

Enable SSL by clicking on the button. github pages will then get a certificate from the lovely folks at lets encrypt and github pages will automatically renew it for you before the certificate expires.

Your website should now be globally accessible at https://<your-domain-name>

Updating the website with new content

Now everything is set up, updating content on the web site is as simple as;

  • git commit
  • git push
ncarter@zola:~/src/flocknetworks.github.io$ git status
On branch main

ncarter@zola:~/src/flocknetworks.github.io$ git commit -a -m "my new content"
[main 8a3b1ab] my new content
 1 file changed, 7 insertions(+)

ncarter@zola:~/src/flocknetworks.github.io$ git push
Checking site...
Checking all internal links with anchors.
> Successfully checked 0 internal link(s) with anchors.
Checking 32 external link(s). Skipping 0 external link(s).
> Checked 32 external link(s): 0 error(s) found.
-> Site content: 7 pages (0 orphan), 7 sections
Done in 2.9s.

Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 570 bytes | 570.00 KiB/s, done.
Total 5 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
To github.com:flocknetworks/flocknetworks.github.io.git
   97b67e5..8a3b1ab  main -> main

References

https://thedataquarry.com/posts/static-site-zola/