Search code examples
nixnixos

NixOS: how to import some configuration from GitLab? infinite recursion encountered


I'm trying to deploy a NixOS VM while storing its configuration on a private GitLab repository.

My configuration.nix looks like this (simplified to only include the relevant bits):

{ pkgs, ... }:
let
  repo = pkgs.fetchFromGitLab { owner = "hectorj"; repo = "nix-fleet"; };
in {
  imports = [
    ./hardware-configuration.nix
    "${repo}/my-server-name/host.nix"
  ];
}

but it is giving me this error:

error: infinite recursion encountered

       at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:496:28:

          495|         builtins.addErrorContext (context name)
          496|           (args.${name} or config._module.args.${name})
             |                            ^
          497|       ) (lib.functionArgs f);

I do not understand where the recursion is happening.

It doesn't seem like its even fetching the repo, as I can put any non-existing names in the args and get the same error.

I saw https://nixos.org/guides/installing-nixos-on-a-raspberry-pi.html doing something similar without issue:

imports = ["${fetchTarball "https://github.com/NixOS/nixos-hardware/archive/936e4649098d6a5e0762058cb7687be1b2d90550.tar.gz" }/raspberry-pi/4"];

And I can use that line on my VM and it will build fine.

What am I missing?


Solution

  • The recursion is as follows

    1. Compute the configuration
    2. Compute the config fixpoint of all modules
    3. Find all modules
    4. Compute "${repo}/my-server-name/host.nix"
    5. Compute repo (pkgs.fetch...)
    6. Compute pkgs
    7. Compute config._module.args.pkgs (Nixpkgs can be configured by NixOS options)
    8. Compute the configuration (= 1)

    You can break the recursion at 6 by using builtins.fetchTarball instead.

    Alternatively, you can break it around 7, by using a different "pkgs".

    If you're using configuration.nix as part of a larger expression, you may be able to pass an invoked Nixpkgs to NixOS via specialArgs.pkgs2 = import nixpkgs { ... }. This creates a pkgs2 module argument that can't be configured by NixOS itself.

    Otherwise, you could define pkgs2 in a let binding.

    { pkgs, ... }:
    let
      # pkgs2: An independent Nixpkgs that can be constructed before the NixOS
      # imports are resolved.
      pkgs2 = import <nixpkgs> {};
      repo = pkgs2.fetchFromGitLab { owner = "hectorj"; repo = "nix-fleet"; };
    in {
      imports = [
        ./hardware-configuration.nix
        "${repo}/my-server-name/host.nix"
      ];
    }