Finih up draft of the Nix Blog article

This commit is contained in:
Danila Fedorin 2022-04-10 00:53:35 -07:00
parent dc3f086b9d
commit fe1c05fe46

View File

@ -1,6 +1,6 @@
---
title: "Declaratively Deploying Multiple Blog Versions with NixOS and Flakes"
date: 2021-10-23T18:01:31-07:00
date: 2022-04-10T00:24:58-07:00
draft: true
tags: ["Hugo", "Nix"]
---
@ -32,18 +32,15 @@ re-read what I wrote from any device that has an internet connection. The third
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 handled 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.
I wanted to be able to represent all of this complexity in my NixOS configuration file, and
that's what this post is about!
### Why Flakes
This article is about using Nix Flakes to manage my configuration. But what is it that made
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
@ -52,7 +49,7 @@ me use flakes? Well, two things:
overlays; however, how should my system configuration get my overlay Nix expression? I would
like to be able to separate my build-the-blog code from my describe-the-server code, and
so I need a clean way to let my system access the former from the latter.
flakes solve this issue my letting me specify a blog flake, and pull it in as one
flakes solve this issue by 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 fethcing
the latest commit from the `master` branch of my blog repository, and updating the `default.nix`
@ -98,7 +95,7 @@ There are a few things here:
because __they don't actually matter for the derivation itself__ -- they just aren't used
in the builder. However, attributes given to a derivation are accessible from "outside",
and these settings will play a role later.
* Lines 10 through 14 deal with setting the base URL of the site. Hugo, my static site generator,
* Lines 10 through 14 deal with setting the base URL of the site. Hugo
does not know how to interpret
the `--baseURL` option when a blog has multiple languages. What this means is that in the end,
it is impossible to configure the base URL used in links from the command line,
@ -108,7 +105,7 @@ There are a few things here:
However, the configuration file only knows one base URL per language, and so it _doesn't_ know
when or when not to use the `drafts.` prefix. The `urlSub` variable is used in the builder.
* On line 15, the `publicPath` variable is set; while single-language Hugo puts all the generated
HTML into the `public` folder, the multi-language configuration places them into `public/[language-code]`.
HTML into the `public` folder, the multi-language configuration places it into `public/[language-code]`.
Thus, depending on the configuration, the builer needs to look in a different place for final output.
This new `website` function is general enough to represent all my blog versions, but it's too low-level.
@ -153,7 +150,7 @@ describing my blog. However, by themselves, they aren't quite enough to clean
up my system configuration: for each of these blog versions, I'd need to add
an Nginx `virtualHosts` entry where I'd pass in the corresponding host (like `danilafe.com` or
`drafts.danilafe.com`), configure SSL, and so on. At one point, too, all paths
in `/var` were by default mounted as read-only by NixOS, which meant that it was necessay
in `/var` were by default mounted as read-only by NixOS, which meant that it was necessary
to tell `systemd` that `/var/www/challenges` should be writeable so that the SSL
certificate for the site could be properly renewed. Overall, this was a lot of detail
that I didn't want front-and-center in my server configuration.
@ -163,7 +160,8 @@ of the information required to configure Nginx. The virtual host, for instance,
is the same as `replaceUrl.to` (since I'd want the Nginx virtual host for a blog
version to handle links within that version). The `ssl` ghost parameter corresponds
precisely to whether or not a virtual host will need SSL (and thus ACME, and thus
the `systemd` setting).
the `systemd` setting). For each derivation built using `website`, I can access
the attributes like `ssl` or `host` to generate the corresponding piece of the Nginx configuation.
To make this _really_ nice, I wanted all of this to be "just another section of my
configuration file". That is, I wanted to control my site deployment via regular
@ -232,7 +230,7 @@ the flake needs access to, and outputs are simply Nix expressions that the flake
The nice thing about flakes' inputs is that they can reference other flakes via Git. This means
that, should I write a flake for my blog (as I am about to do) I will be able to reference its git URL
in another flake, and Nix will automatically clone and import it. This helps provide the __adding custom packages__
in another flake, and Nix will automatically clone and import it. This helps achieve the __adding custom packages__
goal, since I can now easily write Nix expressions and reference them from my system configuration.
Importantly, flakes track the versions of their inputs in a `flake.lock` file; this means that, unless explicitly told to do otherwise,
@ -249,14 +247,14 @@ Let's take a look at the inputs of my blog flake:
Two of these inputs are my blog source code, pulled from its usual Git host. They are marked as
`flake = false` (my blog is just a Hugo project!), and both require submodules to be fetched. One
of them is set to the `localization` branch, once again because localization is not yet stabled
of them is set to the `localization` branch, once again because localization is not yet stabilized
and thus not merged into my blog's `master` branch. The other three inputs are flakes, one of
which is just `nixpkgs`. The `flake-utils` flake provides some convenient functions for writing other
flakes, and `katex-html` is my own creation, a KaTeX-to-HTML conversion script that I use to post-process the blog.
So what outputs should this flake provide? Well, we've already defined a NixOS module for the blog, and we'd like
our flake to expose this module to the world. But the module alone is not enough; its configuration requires a list of
packages created using our builders. But where does one procure such a list? The caller will need access to the builders
packages created using our builders. Where does one procure such a list? The caller will need access to the builders
themselves. To make all of this work, I ended up with the following expression for my `outputs`:
{{< codelines "Nix" "blog-static-flake/flake.nix" 21 34 >}}
@ -284,4 +282,23 @@ And that's it for the blog flake! I simply push it to Git, and move on to actual
#### Using the Module
In my server configuration (which is, itself, a flake), I simply list my `blog-static-flake` as one
of the inputs:
{{< codelines "Nix" "server-config/flake.nix" 4 4 >}}
Then, in the `modules` attribute, I include `blog.nixosModule`, making NixOS aware of its options and configuration.
The final little piece is to provide the `english` and `russian` builders to the system configuration;
this can be done using the `specialArgs` attribute. The whole `flake.nix` file is pretty short:
{{< codeblock "Nix" "server-config/flake.nix" >}}
Finally, in `configuration.nix`, taking `builders` as one of the inputs, I finally write what you saw above:
{{< codelines "Nix" "server-config/configuration.nix" 42 59 >}}
### Wrapping Up
So there you have it, a flake-based blog deployment written in a declarative style. You can
check out both my [system configuration flake](https://dev.danilafe.com/Nix-Configs/server-config)
and my [blog flake](https://dev.danilafe.com/Nix-Configs/blog-static-flake) on my Git server.
If you want more, check out the articles by Xe and Yannik linked above. Thanks for reading!