I’ve mentioned the insane power of NixOS’ QEMU-based integration tests.

If you're wondering why you (yes, you!) should care at all about this random Linux distro, expand this carat for my summary.
For those not in the know, a **NixOS configuration** is a data structure that fully determines a Linux system, from the kernel to the users and the systemd processes. It's a highly reproducible artifact backed by the largest open-source package repo in existence. You can:
  • Put it in version control and use it for your daily driver to make hardware migrations painless
  • Deploy to bare metal VPS with low-resource “build-then-push” tooling
  • Build Docker/OCI containers from it to appease corporate goons
  • Run it in CI/CD pipelines
  • Share it with teammates for identical dev environments
  • Parameterize it to define a cluster of nodes

The integration test framework lets you define virtualized nodes with pass/fail conditions on the behavior of the components therein. Furthermore the nodes can be embedded within an arbitrary network topology to test the overall system-of-systems behavior. With the tests defined, they’re wrapped into the very notion of validity for your configuration(s).

This system is obviously the future of infrastructure. NixOS is doing things that are deep on the long-term roadmap for other system-of-system solutions. You could burn serious man-hours approximating this capability in docker-compose and end up nowhere near the raw reproducible bare-metal power.

However, in my own experiments, the virtualization layer quickly made my $300 dev laptop smoke at the ears for anything beyond 1 node. That’s why I’m excited that Nixcademy has announced a new feature. An unnamed corporate patron has supported development of namespace-based containerization backed by systemd-nspawn.

Here’s an abbreviated example illustrating how I could bake this very post into my VPS deployment!

{
  description = "NixOS configuration with test";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  outputs = { self, nixpkgs }: 
  {
    checks.x86_64-linux.test = let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in pkgs.testers.runNixOSTest {
      
      name = "configuration-test";
      
      nodes.server = { config, pkgs, paradigmatic, ... }: {
        services.nginx = {
          enable = true;
          virtualHosts."_" = {
            root = "${paradigmatic.packages.${system}.website}";
          }
        };
      };
      
      nodes.client = { config, pkgs, ... } : {};

      testScript = ''
        server.start()
        client.start()
        server.wait_for_unit("nginx.service")
        client.wait_for_unit("multi-user.target")
        client.succeed("curl http://server/posts/integration-containers 
        | grep 'Hello from this very text block!'")
      '';
    };
  };
}

Nice!

Want to chat about NixOS adoption? Email me