Finih up draft of the Nix Blog article
This commit is contained in:
parent
dc3f086b9d
commit
fe1c05fe46
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Declaratively Deploying Multiple Blog Versions with NixOS and Flakes"
|
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
|
draft: true
|
||||||
tags: ["Hugo", "Nix"]
|
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
|
version of my blog. It's rather empty, because translation is hard work, so it only exists
|
||||||
so far as another "draft" website.
|
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
|
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
|
adjust this, and possibly even switch my hosts without changing any of the code that actually
|
||||||
builds my blog.
|
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
|
### 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:
|
me use flakes? Well, two things:
|
||||||
|
|
||||||
* __Adding custom packages__. The Nix code for my blog provides a package / derivation for each
|
* __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
|
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
|
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.
|
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.
|
of the inputs.
|
||||||
* __Versioning__. My process for deploying new versions of the site prior to flakes boiled down to fethcing
|
* __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`
|
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
|
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",
|
in the builder. However, attributes given to a derivation are accessible from "outside",
|
||||||
and these settings will play a role later.
|
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
|
does not know how to interpret
|
||||||
the `--baseURL` option when a blog has multiple languages. What this means is that in the end,
|
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,
|
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
|
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.
|
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
|
* 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.
|
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.
|
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
|
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
|
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
|
`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
|
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
|
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.
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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.
|
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,
|
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
|
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
|
`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
|
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
|
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.
|
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
|
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
|
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`:
|
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 >}}
|
{{< 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
|
#### 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 >}}
|
{{< 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!
|
||||||
|
|
Loading…
Reference in New Issue
Block a user