Infinite recursion with wrapFirefox

I am trying to wrap a custom Firefox per this issue with the Firefox add-ons:

In apps.nix I have

{ config, pkgs, lib, ... }:

with pkgs;

{
  config = lib.mkIf config.services.xserver.enable {
    environment = {
      systemPackages = with pkgs; [
        ( callPackage ./firefox.nix {} )
      ];

      variables = {
        BROWSER = [ "firefox" ];
      };
    };
  };
}

and in firefox.nix I have :

{ pkgs, ... }:

 with pkgs;

 wrapFirefox firefox-unwrapped {
    nixExtensions = [
    (fetchFirefoxAddon {
        name = "ublock-origin";
        url = "https://addons.mozilla.org/firefox/downloads/file/3701081/ublock_origin-1.32.4-an+fx.xpi";
        sha256 = "1k5riwz9ljb9fsmz5bv5ci237rr9bfq21pc3dpzsc6ckfizzv52v";
    })
    
    ];

    extraPolicies = {
    DisablePocket = true;
    FirefoxHome = {
        Pocket = false;
        Snippets = false;
    };
    UserMessaging = {
        ExtensionRecommendations = false;
        SkipOnboarding = true;
    };
    };

    extraPrefs = ''
    // Show more ssl cert infos
    lockPref("security.identityblock.show_extended_validation", true);

    // Enable dark dev tools
    lockPref("devtools.theme","dark");

    // Disable add-on signing
    lockPref("xpinstall.signatures.required", false)

    // Disable language pack signing
    lockPref("extensions.langpacks.signatures.required", false)
    '';
} 

and the result of the evaluation (with sudo nixos-rebuild test --fast for example) gives

building the system configuration...
error: while evaluating the attribute 'config.system.build.toplevel' at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/eval-config.nix:64:5:
while evaluating 'evalModules' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:62:17, called from /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/eval-config.nix:58:12:
while evaluating 'mapAttrsRecursiveCond' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:289:36, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:139:28:
while evaluating 'recurse' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:291:23, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:299:8:
while evaluating the attribute 'matchedOptions' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:414:14:
while evaluating 'flip' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:138:16, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:382:23:
while evaluating 'byName' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:362:25, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:370:21:
while evaluating 'reverseList' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/lists.nix:393:17, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:131:33:
while evaluating anonymous function at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:249:37, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:127:25:
while evaluating 'filterModules' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:239:36, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:250:7:
while evaluating anonymous function at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:243:31, called from undefined position:
while evaluating the attribute 'disabled' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:221:13:
while evaluating the attribute 'disabled' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:221:13:
while evaluating 'loadModule' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:188:53, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:226:22:
while evaluating 'unifyModuleSyntax' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:254:34, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:191:14:
while evaluating 'applyIfFunction' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:284:29, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:191:59:
while evaluating anonymous function at /home/sirc/whatever/1/firefox.nix:1:1, called from /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:310:8:
while evaluating the module argument `pkgs' in "/home/sirc/whatever/1/firefox.nix":
infinite recursion encountered, at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:303:28

My questions are then:

  1. why is infinite recursion is triggered ?
  2. and (of course) how can I have this wrapping of Firefox in a separate file ?

Use config.environment = mkIf ... instead.

As you have it now, nix has to assume, that you might change config the value of your condition.

That does not solve the infinite recursion problem but it is indeed tidier.

I wanted to debug locally and therefore first make sure that your wrapped firefox builds.

But I get an error about extraPolicies beeing an unexpected argument.

What channel(s) are you on?

# nix-channel --list
home-manager https://github.com/nix-community/home-manager/archive/master.tar.gz
nixpkgs https://nixos.org/channels/nixpkgs-unstable

# sudo nix-channel --list
home-manager https://github.com/nix-community/home-manager/archive/master.tar.gz
nix-ld https://github.com/Mic92/nix-ld/archive/main.tar.gz
nixos https://nixos.org/channels/nixos-unstable

I have put everything int a wrapping configuration and ran a build. Worked without infinite recursion for me:

# configuration.nix
{ config, pkgs, ... }:

let
  vboxpkgs = pkgs.fetchFromGitHub {
    owner = "bachp";
    repo = "nixpkgs";
    rev = "aaf75813cd7599c5e0939d5ac905cc281ab6e7db";
    sha256 = pkgs.lib.fakeSha256;
  };
in
{
  imports = [
    ./hardware-configuration.nix
    ./conf.nix
  ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.supportedFilesystems = [ "ntfs" "btrfs" "exfat" "avfs" ];
  boot.cleanTmpDir = true;

  users.users.demo = {
    isNormalUser = true;
    description = "Demo user account";
    extraGroups = [ "wheel" "docker" ];
    uid = 1000;
    shell = pkgs.zsh;
    # home = "/home/nmelzer";
  };

  services.xserver.enable = true;
}

# conf.nix
{ config, pkgs, lib, ... }:

{
  config = lib.mkIf config.services.xserver.enable {
    environment = {
      systemPackages = with pkgs; [
        ( callPackage ./firefox.nix {} )
      ];

      variables = {
        BROWSER = [ "firefox" ];
      };
    };
  };
}

# firefox.nix
{ pkgs, ... }:

with pkgs;

wrapFirefox firefox-unwrapped {
  nixExtensions = [
    (fetchFirefoxAddon {
      name = "ublock-origin";
      url = "https://addons.mozilla.org/firefox/downloads/file/3701081/ublock_origin-1.32.4-an+fx.xpi";
      sha256 = "1k5riwz9ljb9fsmz5bv5ci237rr9bfq21pc3dpzsc6ckfizzv52v";
    })
  ];

  extraPolicies = {
    DisablePocket = true;
    FirefoxHome = {
      Pocket = false;
      Snippets = false;
    };
    UserMessaging = {
      ExtensionRecommendations = false;
      SkipOnboarding = true;
    };
  };

  extraPrefs = ''
    // Show more ssl cert infos
    lockPref("security.identityblock.show_extended_validation", true);

    // Enable dark dev tools
    lockPref("devtools.theme","dark");

    // Disable add-on signing
    lockPref("xpinstall.signatures.required", false)

    // Disable language pack signing
    lockPref("extensions.langpacks.signatures.required", false)
  '';
}

# hardware-configuration.nix
# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations.  Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }:

{
  imports = [ ];

  boot.initrd.availableKernelModules = [ "ohci_pci" "ahci" "sd_mod" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ ];
  boot.extraModulePackages = [ ];

  fileSystems."/" =
    { device = "/dev/disk/by-uuid/c1e4f201-3c0a-4d88-bd7c-fcd908412df2";
      fsType = "ext4";
    };

  swapDevices = [ ];

  nix.maxJobs = lib.mkDefault 2;
  virtualisation.virtualbox.guest.enable = true;
}

Command used to build was:

$ nixos-rebuild build -I nixos-config=/tmp/tmp.f5eoSHgFMf/configuration.nix -I nixpkgs=$HOME/Projects/nixpkgs

Why does it say that on my machine then…

Your configuration is probably much bigger than that. Do you have it publicly available in git or something?

The only difference I see from our two setups is that you directly import conf in the configuration.nix and I do this :

# modules/default.nix
{ lib, config, options, pkgs, ... }:

with lib;
let
  # Recursively constructs an attrset of a given folder, recursing on directories, value of attrs is the filetype
  getDir = dir:
    mapAttrs
      (file: type: if type == "directory" then getDir "${dir}/${file}" else type)
      (builtins.readDir dir);

  # Collects all files of a directory as a list of strings of paths
  files = dir:
    collect isString
      (mapAttrsRecursive (path: type: concatStringsSep "/" path) (getDir dir));

  # Filters out directories that don't end with .nix or are this file, also makes the strings absolute
  validFiles = dir:
    map (file: ./. + "/${file}")
      (filter (file: hasSuffix ".nix" file && file != "default.nix") (files dir));

in
{
  imports = validFiles ./.;

  # Sending the locations of the configuration files for the options here
  options.perso.dotfiles = mkOption {
    type = types.path;
    default = ../dotfiles;
    description = "Location of the configuration files.";
  };
}

and import that in mine

It is but why would nix point to the file for Firefox and when I remove that file and replace it by the content in-line it works ? I want to understand that phenomenon.

Are you perhaps autoimporting it through your validFiles?

EXACTLY! I am such an idiot.