Infinite recursion caused by flake input in a container in nixops

Hello,

I’m using nixops to deploy servers and also use nixos-containers to further isolate services, this is all in a flake.
I’m running into an infinite recursion error when using one of the flake input, in my case simple-nixos-mailserver ; but I suspect it would do the same with another.

It is caused by using the input flake’s module in the container’s inputs.
I narrowed it down to this minimal example:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-23.11";
  };

  outputs = { self, nixpkgs, simple-nixos-mailserver, ... }: {
    devShells.x86_64-linux.default =
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in pkgs.mkShell {
      packages = [
        pkgs.nixops_unstable
      ];
    };

    nixopsConfigurations.default = {
      inherit nixpkgs;
      network.storage.legacy = {};

      testhost = {...}: {

        imports = [
          ({...}: {
            fileSystems."/" = { device = "/dev/disk/by-label/nixos"; fsType = "ext4"; };
            boot.loader.grub.device = "/dev/vda"; #lib.mkDefault "/dev/vda";
            containers.mail.config = { pkgs, simple-nixos-mailserver, ... }: {
              imports = [ simple-nixos-mailserver.nixosModule ];
            };
          })
        ];
      };
    };
  };
}

And building that with nixops fails with the infinite recursive error:

nix develop
nixops deploy --build-only
...
       … while calling the 'derivationStrict' builtin

         at /builtin/derivation.nix:9:12: (source not available)

       … while evaluating derivation 'nixops-machines'
         whose name attribute is located at /nix/store/l6ymqz1y4fiy57xh6f3y23zwp0i9lr4f-source/pkgs/stdenv/generic/make-derivation.nix:348:7

       … while evaluating attribute 'buildCommand' of derivation 'nixops-machines'

         at /nix/store/l6ymqz1y4fiy57xh6f3y23zwp0i9lr4f-source/pkgs/build-support/trivial-builders/default.nix:87:14:

           86|       enableParallelBuilding = true;
           87|       inherit buildCommand name;
             |              ^
           88|       passAsFile = [ "buildCommand" ]
...
… while evaluating the module argument `simple-nixos-mailserver' in ":anon-1541:anon-1":

       error: infinite recursion encountered

       at /nix/store/l6ymqz1y4fiy57xh6f3y23zwp0i9lr4f-source/lib/modules.nix:506:28:

          505|         builtins.addErrorContext (context name)
          506|           (args.${name} or config._module.args.${name})
             |                            ^
          507|       ) (lib.functionArgs f);

I’m new to Nix, and I feel using flakes in containers is probably quite common. What am I doing wrong ?

Regards

Try removing simple-nixos-mailserver from this line.

Thanks ! It fixes my example, the full flake still has the issue but I’ll look into it now that I have this example working.

I got it to work. In my real flake I use imports and this didn’t fix it. In the imported nix file, it just didn’t know what simple-nixos-mailserver was. And adding it in the module’s arguments (not the container’s) led to the same infinite recursion.

I had to move the simple-nixos-mailserver imports out of the file like so and it works. Extract from the flake:

imports = [
          ./mymailcontainer.nix
          ({...}: {
            containers.mail.config.imports = [ simple-nixos-mailserver.nixosModule ];
          })
        ];

It doesn’t look good but does the job.

I honestly don’t know where the infinite recursion here comes from. I also tested around until things were working. If you want to pass extra arguments to your container config, you can also use containers.<name>.specialArgs, which is probably the correct way to do this. In order to avoid any conflicts with the parent system module, putting the container module in an extra file could work.

I am also currently setting up a server with Nixos containers (no NixOps though) and found this to be quite tricky at times, but I think I got all use-cases working that I am going to need. In case you are interested, here is the link to the machine config.