Search code examples
nixnixos

How can a build or test a smaller nixos container config independent of my host's Nixos config?


I'm trying to configure a container within nixos containers for example:

  containers.abc123 = {
    config = { config, pkgs, ... }:
    {
      systemd.services = {
        finder-email-requests = {
          description = "";
          enable = true;
          environment = {
              TESTING = "abcxyz";
          };
          serviceConfig = {
            Type      = "simple";

            ExecStart = "bash -c \"echo '$TESTING hello' >> /tmp/abcxyz\"";
            Restart   = "always";
            RestartSec   = 30;
          };
          wantedBy = [ "default.target" ];
        };
      };
    };
  };

However needing to test/compile this means running nixos-rebuild test which can take 10+ seconds on my machine (or 7s on a newly installed VM I just tried).

Is there some way I can more quickly test this container config independent from my entire host's Nixos config? For example building just the container config itself rather than the entire instance of this nixos config?


I've found that the nixos-rebuild command is a small shell script for example at https://github.com/NixOS/nixpkgs/blob/216f0e6ee4a65219f37caed95afda1a2c66188dc/nixos/modules/installer/tools/nixos-rebuild.sh

However after reading through it, I don't quite understand whats going on in terms of the relationship between this 'containers' unit and the general 'nixos config'.


Solution

  • NixOS Containers don't have a testing facility of their own (as of Nov 2020). They behave like normal NixOS systems for most intents and purposes. If you want to test your container, a normal NixOS test should be adequate.

    Writing NixOS tests is documented in the NixOS manual. You can use the pkgs.nixosTest function to write your own tests outside of the Nixpkgs repo.

    You could test either an approximation of the host system with your container, or just the container configuration as if it was the "top-level" NixOS system. I'd go with the latter, unless you need to test multiple containers in conjunction, or if you need to test interactions between host and container.

    However to test the container definition building correctly, we can use pkg.nixos. For example, a nix expression for your container (that can be be built with the usual nix-build method):

    { a = let pkgs = import <nixpkgs> {};
    in (pkgs.nixos
    {
      fileSystems."/".device = "x";
      boot.loader.grub.enable = false;
    
      systemd.services = {
              finder-email-requests-2 = {
                description = "";
                enable = true;
                environment = {
                    TESTING = "abcxyz";
                };
                serviceConfig = {
                  Type      = "simple";
    
                  ExecStart = "bash -c \"echo '$TESTING hello' >> /tmp/abcxyz\"";
                  Restart   = "always";
                  RestartSec   = 30;
                };
                wantedBy = [ "default.target" ];
              };
            };
    }).toplevel; 
    }