diff --git a/content/blog/blog_with_nix.md b/content/blog/blog_with_nix.md index 8cd75ae..d2e01af 100644 --- a/content/blog/blog_with_nix.md +++ b/content/blog/blog_with_nix.md @@ -61,7 +61,7 @@ me use flakes? Well, two things: 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 + 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 @@ -218,6 +218,60 @@ to configure the challenge path to be writeable. Click the `module.nix` link abo to check out the full file. #### Creating a Flake +We now have two "things" that handle the deployment of the blog: +the builder functions `english` and `russian` which help describe various +blog versions, and the NixOS module that configures the server's Nginx to +serve said versions. We now want to expose these to the NixOS system configuration, +which describes the entire server. I decided to do this using a flake. +[Yanik Sander](https://blog.ysndr.de/posts/internals/2021-01-01-flake-ification/index.html) wrote up +a pretty comprehensive explanation of how their blog is deployed using flakes, which I often consulted +while getting started -- check it out if you are looking for more details. + +In brief, a Nix flake has _inputs_ and _outputs_. Inputs can be other flakes or source files that +the flake needs access to, and outputs are simply Nix expressions that the flake provides. + +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__ +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, +they will use the same version of their inputs. This achieves the __versioning__ goal for my blog, too, since +now it will pull the pre-defined commit from Git until I tell it to fetch the updated site. +In addition to pinning the version of my blog, though, the flake also locks down the version of `nixpkgs` itself. +This means that the same packages will be used in the build process, instead of those found on the host +system at the time. This has the nice effect of preventing updates to dependencies from breaking the build; +it's a nice step towards purity and reproducibility. + +Let's take a look at the inputs of my blog flake: + +{{< codelines "Nix" "blog-static-flake/flake.nix" 2 19 >}} + +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 +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. This is the exact purpose of the `outputs.nixosModule` attribute. +It's sufficient to simply import the module file: + +{{< codelines "Nix" "blog-static-flake/flake.nix" 28 28 >}} + +This is great, but it's not enough. Specifically, the module configuration requires a list of +packages created using our builders. But how should the NixOS configuration even reference these builders? +There's no "standard" way for exposing a pure function from a flake (as far as I know), but the good news is that +if you add a non-standard attribute to the flake, it will be accessible from wherever it is imported. +Thus, I simply provide a `buildersFor` function: + +{{< codelines "Nix" "blog-static-flake/flake.nix" 23 27 >}} + +The `nixpkgs` flake requires a `system` argument, which means that the builders themselves +(which depend on packages from `nixpkgs`) need to be aware of what system they're being used for. +This is why `buildersFor` is itself a function. + {{< todo >}} This needs to be done {{< /todo >}} #### Using the Module