blog-static/content/blog/blog_with_nix.md

79 lines
4.4 KiB
Markdown
Raw Normal View History

2021-12-04 00:41:01 -08:00
---
title: "Declaratively Deploying Multiple Blog Versions with NixOS and Flakes"
date: 2021-10-23T18:01:31-07:00
expirydate: 2021-10-23T18:01:31-07:00
draft: true
tags: ["Hugo", "Nix"]
---
### Prologue
You can skip this section if you'd like.
For the last few days, I've been stuck inside of my room due to some kind of cold or flu, which
or
{{< sidenote "right" "pcr-note" "may or may not be COVID." >}}
The results of the PCR test are pending at the time of writing.
{{< /sidenote >}}
In seeming correspondence with the progression of my cold, a thought occured in the back of my mind:
"_Your blog deployment is kind of a mess_". On the first day, when I felt only a small tingling in
my throat, I waved that thought away pretty easily. On the second day, feeling unwell and staying
in bed, I couldn't help but start to look up Nix documentation. And finally, on the third day,
between coughing fits and overconsumption of oral analgesic, I got to work.
In short, this post is the closest thing I've written to a fever dream.
### The Constraints
I run several versions of this site. The first is, of course, the "production" version, hosted
at the time of writing on `danilafe.com` and containing the articles that I would like to share
with the world. The second is a version of this site on which drafts are displayed - this
way, I can share posts with my friends before they are published, get feedback, and even just
re-read what I wrote from any device that has an internet connection. The third is the Russian
version of my blog. It's rather empty, because translation is hard work, so it only exists
so far as another "draft" website.
My build process (a derivative of what I describe in [rendering mathematics on the back end]({{< relref "./backend_math_rendering.md" >}})) is also fairly unconventional. When I developed this site, the best
form of server-side mathematics rendering was handlded by KaTeX, and required some additional
work to get rolling (specifically, I needed to write code to replace sections of LaTeX on
a page with their HTML and MathML versions). There may be a better way now, but I haven't yet
performed any kind of migration.
Currently, only my main site is behind HTTPS. However, I would like for it to be possible to
adjust this, and possibly even switch my hosts without changing any of the code that actually
builds my blog.
### Why Flakes
This article is about using Nix Flakes to manage my configuration. But what is it that made
me use flakes? Well, two things:
* __Adding custom packages__. The Nix code for my blog provides a package / derivation for each
version of my website, and I want to use these packages in my `configuration.nix` so that
I can point various Nginx virtual hosts to each of them. This is typically done using
overlays, but I need a clean way to let my system configuration pull in my blog overlay (or blog
packages); flakes solve this issue my letting me specify a blog flake, and pull it in as one
of the inputs.
* __Versioning__. My process for deploying new versions of the site prior to flakes boiled down to fetcing
the latest commit from the `master` branch of my blog repository, and updating the `default.nix`
file with that commit. This way, I could reliably fetch the version of my site that
I want published. Flakes do the same thing: the `flake.lock` file
contains the hashes of the Git-based dependencies of a flake, and thus prevents builds from
accidentally pulling in something else. However, unlike my approach, which relies on custom
scripts and extra tools such as `jq`, the locking mechanism used by flakes is provided with
standard Nix tooling. Using Flakes also guarantees that my build process won't break with
updates to Hugo or Ruby, since the `nixpkgs` version is stored in `flake.lock`, too.
### The Final Result
Here's the relevant section of my configuration:
{{< codelines "Nix" "server-config/configuration.nix" 42 59 >}}
I really like how this turned out for three reasons. First,
it's very clear from the configuration what I want from my server:
three virtual hosts, one with HTTPS, one with drafts, and one with drafts and
_in Russian_. Second, there's plenty of code reuse. I'm using two builder functions,
`english` and `russian`, but under the hood, the exact same code is being
used to run Hugo and all the necessay post-processing. Finally, all of this can be
used pretty much immediately given my blog flake, which reduces the amount of glue
code I have to write.