4.4 KiB
title | date | expirydate | draft | tags | ||
---|---|---|---|---|---|---|
Declaratively Deploying Multiple Blog Versions with NixOS and Flakes | 2021-10-23T18:01:31-07:00 | 2021-10-23T18:01:31-07:00 | true |
|
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 thedefault.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: theflake.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 asjq
, 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 thenixpkgs
version is stored inflake.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.