From fe1c05fe46336ab43402c863dbba49851cd63c08 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Sun, 10 Apr 2022 00:53:35 -0700 Subject: [PATCH] Finih up draft of the Nix Blog article --- content/blog/blog_with_nix.md | 49 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/content/blog/blog_with_nix.md b/content/blog/blog_with_nix.md index 7006c2a..60fedcd 100644 --- a/content/blog/blog_with_nix.md +++ b/content/blog/blog_with_nix.md @@ -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!