Compare commits

...

2 Commits

3 changed files with 67 additions and 5 deletions

@ -1 +1 @@
Subproject commit f2bb36b862b7c730c42abb0b759ddd3c1c4f3d4b Subproject commit 67b47d9c298e7476c2ca211aac5c5fd961637b7b

View File

@ -4,7 +4,7 @@
url = "https://dev.danilafe.com/Advent-of-Code/AdventOfCode-2020/src/commit/7a8503c3fe1aa7e624e4d8672aa9b56d24b4ba82" url = "https://dev.danilafe.com/Advent-of-Code/AdventOfCode-2020/src/commit/7a8503c3fe1aa7e624e4d8672aa9b56d24b4ba82"
path = "aoc-2020" path = "aoc-2020"
[params.submoduleLinks.blogstaticflake] [params.submoduleLinks.blogstaticflake]
url = "https://dev.danilafe.com/Nix-Configs/blog-static-flake/src/commit/f2bb36b862b7c730c42abb0b759ddd3c1c4f3d4b" url = "https://dev.danilafe.com/Nix-Configs/blog-static-flake/src/commit/67b47d9c298e7476c2ca211aac5c5fd961637b7b"
path = "blog-static-flake" path = "blog-static-flake"
[params.submoduleLinks.serverconfig] [params.submoduleLinks.serverconfig]
url = "https://dev.danilafe.com/Nix-Configs/server-config/src/commit/98cffe09546aee1678f7baebdea5eb5fef288935" url = "https://dev.danilafe.com/Nix-Configs/server-config/src/commit/98cffe09546aee1678f7baebdea5eb5fef288935"

View File

@ -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 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 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 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. updates to Hugo or Ruby, since the `nixpkgs` version is stored in `flake.lock`, too.
### The Final Result ### The Final Result
@ -116,7 +116,7 @@ Do I really want to specify the `publicPath` each time I want to describe a vers
What about `settings.replaceUrl`, or the source code? Just like I would in any garden variety language, What about `settings.replaceUrl`, or the source code? Just like I would in any garden variety language,
I defined two helper functions: I defined two helper functions:
{{< codelines "Nix" "blog-static-flake/lib.nix" 25 46 >}} {{< codelines "Nix" "blog-static-flake/lib.nix" 25 48 >}}
Both of these simply make a call to the `website` function (and thus return derivations), but they Both of these simply make a call to the `website` function (and thus return derivations), but they
make some decisions for the caller, and provide a nicer interface by allowing attributes to be omitted. make some decisions for the caller, and provide a nicer interface by allowing attributes to be omitted.
@ -218,7 +218,69 @@ to configure the challenge path to be writeable. Click the `module.nix` link abo
to check out the full file. to check out the full file.
#### Creating a Flake #### Creating a Flake
{{< todo >}} This needs to be done {{< /todo >}} 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. 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
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 >}}
The flake `output` schema provides a standard option for exposing modules, `nixosModule`. Then,
exposing my `module.nix` file from the flake is simply a matter of importing it, as on line 31.
There is, however, no standard way for exposing a _function_. The good news is that any
attribute defined on a flake is accessible from code that imports that flake. Thus, I simply
added a `buildersFor` function, which, given an operating system, fetches the `nixpkgs` collection
and LaTeX builder script for that system, and feeds them to the file that defines the `english`
and `russian` builders. This `buildersFor` function also provides the builders with the two
different blog sources they reference, `blog-source` and `blog-source-localized`.
The `system` parameter to `buildersFor` is necessary because the set of packages from `nixpkgs` depends on it. Thus, if the
builders use any packages from the collection (they do), they must know which system to pull packages for.
This is a common pattern in flakes: the `packages` attribute is typically a system-to-package mapping, too.
Finally, the last little bit on lines 32 through 34 defines a default package for the flake. This
is the package that is built if a user runs `nix build .#`. This isn't strictly necessary for my purposes,
but it's nice to be able to test that the builders still work by running a test build. The
`eachDefaultSystem` function generates a `defaultPackage` attribute for each of the "default"
operating systems, so that the package is buildable on more than just my server architecture.
And that's it for the blog flake! I simply push it to Git, and move on to actually _using_ it from elsewhere.
#### Using the Module #### Using the Module