As I started transitioning my homelab to primarily using NixOS, I realized I needed to find a way to start documenting the work I was doing for my future self. In addition to this I realized how dependent I was on these types of blogs as a learning resource, so I decided to create a website where I can publish this documentation for others who are seeking to pursue similar endeavors. Which leads to the creation of Casual Compute!
Why Hugo?
I wanted to keep the documentation in a format that is easy to read, even from a basic text editor. This led to an obvious choice: Markdown.
I have used WordPress before and while it seemed so cool as someone who just got started with self hosting, I realized that it lacked a certain simplicity that I personally find important when working on these kinds of projects. Therefore I decided to look at a platform which allows me to create a website simply from my Markdown documentation, hence why I chose Hugo.
Hugo is an open-source static site generator, which is not only speedy but super simple to use. This video explains it way better than I can. Plus you can implement themes which allow a high degree of customization.
Getting started with Hugo
I initially dove into Hugo by just spinning up a debian VM and installing it using apt, although I quickly realized that it’s an older version and lacked some features needed for more modern themes. Which is why I would recommend downloading the packages from their latest release page if using Debian.
I then started to follow their quick start guide to get a test server running. This took a while on my end due to running an older version as mentioned above. You can verify your version using the command: hugo version. For this guide you want to make sure you’re at v0.112.4 or later.
Then the following set of commands can be used to quickly generate a test server:
hugo new site quickstart
cd quickstart
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml
hugo server
You can view the site at the URL displayed in your terminal, and press Ctrl + C to stop the Hugo development server.
Setting up a theme
The next step is finding a theme for your website, luckily the Hugo website has a page with plenty of themes freely available! These often also come along with helpful installation info. For my website I decided to go with PaperMod.
PaperMod works great for a simple blog, looks quite sleek, and has a dark mode that can be toggled. While those were the main criteria I was looking for, it has plenty more features that could come in handy later on.
I will explain the steps I followed to add PaperMod to my Hugo website, and if you choose a different theme the instructions may not be the same. I recommend following the instruction provided by your selected theme, but highly advise using Git submodules as it will be a bit cleaner along with the Nix integration coming up later.
To install my theme I used a Git submodule, which basically allows for a repository to exist within my repository. Adding a submodule is quite simple, for PaperMod I ran the following command:
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
Now that the theme has been added we need to configure Hugo to use it. The configuration file used will be hugo.yaml, and should have the following lines as a minimum:
baseURL: "https://casualcompute.com"
title: "Casual Compute"
theme: PaperMod
Before attempting to generate a website with this theme, the old config file should be removed: rm hugo.toml. You should now be able to use the hugo server command and see the theme applied to the website, although additional configuration can be done to improve its look!
How to remove a submodule
Since the Ananke theme was previously added as a submodule to get a test site running, it may be worth removing it to clean up your repository. All you need to do is run the commandgit rm themes/anankeand commit. This can be done for any theme added as a submodule by changing the path.
Customizing the theme
PaperMod allows for some pretty extensive configuration, which is why I highly recommended looking through the features documentation. If using another theme it should provide its own documentation for customization as well as sample configurations.
Here is a sample hugo.yaml for PaperMod that can be used to start your website:
baseURL: "https://examplesite.com/"
title: ExampleSite
theme: PaperMod
params:
title: ExampleSite
description: "ExampleSite description"
keywords: [Blog, Portfolio, PaperMod]
author: Me
# author: ["Me", "You"] # multiple authors
DateFormat: "January 2, 2006"
defaultTheme: auto # dark, light
disableThemeToggle: false
ShowReadingTime: true
ShowShareButtons: true
ShowPostNavLinks: true
ShowBreadCrumbs: true
ShowCodeCopyButtons: false
ShowWordCount: true
# home-info mode
homeInfoParams:
Title: "Hi there \U0001F44B"
Content: Welcome to my blog
socialIcons:
- name: x
url: "https://x.com/"
- name: stackoverflow
url: "https://stackoverflow.com"
- name: github
url: "https://github.com/"
menu:
main:
- identifier: posts
name: posts
url: /posts/
weight: 10
- identifier: tags
name: tags
url: /tags/
weight: 20
taxonomies:
tag: tags
TODO: Add the site sourcecode to GitHub
You can view thehugo.yamlused for this website here.
Creating a post
Now that a working hugo website has been created, it is time to produce content for it. All pages on Hugo are written using Markdown, a great markup language which is quite easy to learn. If unfamiliar with it you should give this a read.
To create a post all you need is to tell Hugo you want to create some new content with this command: hugo new content content/posts/my-first-post.md. This will generate a file in the content/posts directory. You should be able to open that generated file with your favorite editor and should see this:
---
title: 'My First Post'
date: 2024-01-14T07:07:07+01:00
draft: true
---
Notice the
draftvalue is set totrue, by default Hugo will not publish draft content. There is a way to preview draft content using a command which can come in handy, but if you feel like your post is ready to publish make sure to set it tofalse.
With a file generated for your post you can now add content to it using Markdown. This is an example that also adds a tag to the post which can be used to referenced certain topics:
---
title: 'My First Post'
date: 2024-01-14T07:07:07+01:00
tags: [example]
draft: true
---
## Introduction
This is **bold** text, and this is *emphasized* text.
Visit the [Casual Compute](https://casualcompute.com) website!
After the file is saved, you should be all set to host it locally using Hugo’s development server. Using this command you can start up the server, this will also include draft content: hugo server -D. A URL should be displayed in the terminal that you can use to view the site in your browser. The post should be accessible via the homepage.
You can then edit the post and the Hugo renderer should update the page live. Once satisfied with your new content you can set the draft value to false and publish the site using the hugo command. The static site will be generated in the public directory.
TODO: Add the site sourcecode to GitHub
You can view the file used for this post here.
Customizing your homepage
This section is mainly dependent on PaperMod, other themes may have different ways of handling the homepage for your site.
You may have noticed when using the Hugo renderer that you have a pretty underwhelming home page, thankfully that can be easily edited too!
There are a few options available with PaperMod, outlined here in the documentation. The three options are:
- regular mode
- home-info mode
- profile mode
I personally went with home-info mode, as it allows me to set up a simple homepage using the hugo.yaml file. To set this up a couple lines should be added under params: to the file:
homeInfoParams:
Title: "Welcome to Casual Compute!"
Content: >
This website is a self hosted blog that I use to document work done and lessons learned in my homelab.\
*It is currently a work in progress.*
socialIcons:
- name: github
url: "https://github.com/coutnoah"
Adding a
>to the content parameter allows you to fill out the info as multiline content beneath. This is convenient if you want to format the home page with Markdown.
There is also a socialIcons parameter which allows you to link to other websites. PaperMod handles a long list of platforms, which are outlined here. All you need is to put in the name of the platform under name:, and link to your profile page under url:.
The profile mode is a great option if looking to write up a personal blog, the instructions on how to set it up are available here. Regular mode is likely the most similar to what you would have to do if using a different theme than PaperMod. You just need to create a
_index.mdfile at the root of yourcontentdirectory (i.e.,content/_index.md), then fill out the file with Markdown.
Integrating Hugo into a Nix flake
For the following sections it is expected that you have some basic understanding of Nix in addition to having it installed.
I wanted to set up this website to integrate nicely with NixOS, as I have started heavily using it in my homelab. I wanted to be able to spend a minimum amount of time maintaining the website so I can focus on just the documentation, and Nix is the perfect tool for this. It keeps the website simple, easy to deploy, and low maintenance. I relied on a couple guides 1 to help me implement this.
To do this I turned the Hugo website repository into a flake, which I initialized using: nix flake init. This creates a flake.nix file, which can be edited. The flake can be set up so it allows for the theme to be updated through the flake, as well as indicating the use of Hugo in a development environment. It also provides some build steps which copies the built website to a /nix/store path, which will allow for easy updating through Nix.
To start we’ll look at the inputs of the flake:
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
utils.url = "github:numtide/flake-utils";
paper-mod = {
url = "github:adityatelange/hugo-PaperMod";
flake = false;
};
};
There are two important inputs used: nixpkgs which allows up to use the Hugo package, as well as utils which helps with writing Nix flakes. Then there is the paper-mod input, which is the repository of the Hugo theme used. This allows for Nix to use the theme when building the website.
Moving on to the outputs of the flake, the actual functionality is defined here:
outputs = inputs@{ self, nixpkgs, utils, paper-mod, ... }:
utils.lib.eachDefaultSystem (system:
let pkgs = import nixpkgs{ inherit system; }; in
rec {
packages.default = pkgs.stdenv.mkDerivation {
name = "casualcompute.com";
src = self;
buildPhase = ''
mkdir -p themes/PaperMod
cp -r ${inputs.paper-mod}/* themes/PaperMod/
${pkgs.hugo}/bin/hugo
'';
installPhase = "cp -r public $out";
};
apps.default = utils.lib.mkApp {
drv = pkgs.hugo;
};
devShells.default = pkgs.mkShell {
buildInputs = [ pkgs.hugo ];
};
}
);
To start, all the previously defined inputs are incorporated into the function. Then using utils.lib.eachDefaultSystem ensures that the flake will build on multiple systems. Next the package is created using a derivation which:
- provides instructions on how to build the package
- defines a development environment for the package
The build instructions can be boiled down to 3 simple steps:
- It copies the PaperMod theme defined in the inputs into the
themes/PaperModdirectory of the hugo project. - It runs Hugo to build the website.
- It copies the generated website store in the
publicfolder to the/nix/storepath of the flake.
The development shell just allows you to use Hugo by running the nix develop command.
With the flake ready all that is left is to update the flake.lock file. This can easily be done with the nix flake update command.
TODO: Add the site sourcecode to GitHub
You can view theflake.nixused for this website here.
I am still learning some more advanced concepts of Nix myself and realize that there may be flaws in my understanding here. I hope to revisit this in the future to give a clearer explanation and clean up the code as needed.
Implementing the website in NixOS
With the Hugo website created along with a Nix flake to help deploy it, all that is left is to include it in a NixOS configuration. I decided to create a new server named Newton that will handle serving this Hugo website using the Static Web Server service.
I include the flake for the website into the inputs of the flake.nix file used for my NixOS configuration:
casual-compute = {
url = "../packages/casualcompute.com";
inputs.nixpkgs.follows = "nixpkgs";
};
Then in the Newton configuration I include the package for my website, and add the Static Web Server service. It is also important to open up the port for your new website.
environment.systemPackages = with pkgs; [
inputs.casual-compute.packages."x86_64-linux".default
];
services = {
static-web-server = {
enable = true;
root = "${inputs.casual-compute.packages."x86_64-linux".default}";
listen = "[::]:8080";
};
};
# port 8080 used for Static Web Server (http)
networking.firewall.allowedTCPPorts = [ 8080 ];
It is worth pointing out that I am running this server on an x86 system running NixOS, hence why I have the system defined as x86_64_linux for the package. This helps ensure that it is built correctly.
What I find great is that the root directory of the website can easily be defined using the package name! All that is left is to do is update the flake with nix flake update, then rebuild the system.
End note
This post marks the start of my homelab blogging, I hope this is something that I will be able to maintain on the long term. I may also revisit some of these posts and update them as needed.
While this blog is intended to be personal documentation of my projects, I realize that it could come in handy for others too, therefore I decided to make it publicly accessible online. Part of this is because I heavily rely on online information written by others myself, which have taught me the majority of what I know. I see this as a way of giving back to the community.
I hope the information published here will be helpful to a future reader and hopefully get somebody else’s issues resolved. I am looking to implement a way for future readers to also provide feedback to improve both the clarity of the information provided, as well as improving the projects presented.
The following guides helped me do this project: This Site Is Built With a Flake, This Site is Built on NixOS, and Hugo Website, NixOS, and CD ↩︎