Passing NixOS Flake Inputs Through Colmena

I'm pass the one year anniversary of using NixOS and I'm still learning a lot about the language and infrastructure. For the most part, I still feel good about the results even with my troubles playing video games and my underpowered hardware.

In the beginning, I also decided to go “all in” on Flakes. They covered a lot of the things I wanted in Nix, has the isolation that played well with my writing and programming environment. They were also barely understood, shiny, and I like taking the hardest path possible.

Once I realized I liked NixOS, I started putting it on other machines. For that, I settled on Colmena. It had pretty output and, for the most part, did what I wanted instead of the more complex systems that I couldn't understand due to my low skill in the Nix language.

Flake Inputs

One thing that had been vexing me for the last year is how to pass a flake input from infrastructure project (the repository that builds out all the servers) into the individual nodes (servers). This would let me install custom tools on servers or just use something outside of Nixpkgs that wouldn't require me to hunt down hashes every time the project built. Eventually, I hope to include:

  • Author Intrusion (if it ever works)
  • Fedran CLI
  • FlakeHub (current curiosity)
  • Catappuccin theme for Gitea

Since I was messing with NixOS over the last few days, I decided to make another attempt at solving the problem. A few questions on Matrix didn't answer, so I decided that a real-time chat isn't the best place for this type of question and went with the NixOS Discourse and posted there. Lo and behold, someone answered with exactly the answer I needed.

# flake.nix
  # An example flake to pass into the node.
  inputs.fh.url = "*.tar.gz";

  outputs = inputs @ {self, ...}: let
    system = "x86_64-linux";
    pkgs = import inputs.nixpkgs {inherit system;};
  in rec {
    colmena = {
      meta = {
        # Inject the inputs for the top-level flake into a variable so the
        # nodes can pull them down consistently. I renamed this to flakes
        # instead of inputs since I always use `inputs` for my parameters
        # for nested Nix files.
        specialArgs.flakes = inputs; = {
          flakes = inputs;
          system = system; # I cannot figure out the "correct" way to do this yet.

      machine-a = import ./machine-a.nix;

# machine-a.nix
{config, pkgs, flakes, system, ...}: {
  environment.systemPackages = [

Nix as a Language

I still don't really “like” Nix, but I'm getting better at it. It is one of those things that grows on you, even though I have a strong preference for statically compiled languages because they catch many trivial typos.

Automated handling of trivial things has become something I need. While I have pretty good attention to detail, I don't always have the bandwidth to full focus on an item. So anything that I can do to fix those without thinking is a good thing.

Trying to solve this is a good example of my problems. I spent a year trying to solve this, occasionally asking on Matrix and other places. And a GitHub issues page really isn't the best place to ask beginning questions, though I have done that in the past.

I also couldn't find an example of how to do things, which is one reason why I'm creating these posts. At least then, hopefully, someone who is struggling with the same things can stumble on the answer.