Unable pass custom pkgs set to nixosSystem in flake

I’m using flakes for my system configuration. Most things are going smoothly, but I’m stuck on one thing. I create a custom pkgs attribute set in flake.nix and then attempt to pass it to nixosSystem for use in all modules of my config. Here’s my flake.nix:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/master";
    home.url = "github:rycee/home-manager/bqv-flakes";
    emacsOverlay.url = "github:nix-community/emacs-overlay";
    # package overrides
    sageNixpkgs.url = "github:nixos/nixpkgs/7866440f1223dc447f38cb23c00e10b44b4c98fe";
    paraviewNixpkgs.url = "github:nixos/nixpkgs/72158c231ae46a34ec16b8134d2a8598506acd9c";
  };

  outputs = { self
  , nixpkgs
  , home
  , emacsOverlay
  , sageNixpkgs
  , paraviewNixpkgs
  }:
  let
    inherit (builtins) attrNames attrValues readDir;
    inherit (nixpkgs) lib;
    inherit (lib) recursiveUpdate genAttrs mapAttrs' nameValuePair;
    inherit (utils) pathsToImportedAttrs;

    utils = import ./lib/utils.nix { inherit lib; };

    system = "x86_64-linux";

    externalOverlays = [
      emacsOverlay.overlay
    ];

    pkgImport = pkgs: import pkgs {
      inherit system;
      # Order is significant. First incorporate external overlays. We
      # can then use and override these in custom packages (defined
      # in `self.overlay`). Finally overlays in ./overlays can
      # override everything else.
      overlays = externalOverlays
        ++ [ self.overlay ]
        ++ (attrValues self.overlays);
      config = { allowUnfree = true; };
    };

    overridePkgs = {
      sageWithDoc = (pkgImport sageNixpkgs).sageWithDoc;
      paraview = (pkgImport paraviewNixpkgs).paraview;
    };

    pkgs = (pkgImport nixpkgs) // overridePkgs;
  in {
    # Set of machine/build outputs, where key is the machine name and
    # the value defines the configuration of the machine.
    nixosConfigurations = import ./hosts {
      inherit utils lib pkgs system home self;
    };

    overlay = import ./pkgs;

    overlays =
      let
        overlayDir = ./overlays;
        fullPath = name: overlayDir + "/${name}";
        overlayPaths = map fullPath (attrNames (readDir overlayDir));
      in
      pathsToImportedAttrs overlayPaths;

    devShell."${system}" = import ./shell.nix {
      inherit pkgs;
    };

    packages."${system}" = pkgs;
  };
}

and here’s the file that invokes nixosSystem (under ./hosts/default.nix):

{ utils
, lib
, pkgs
, system
, home
, self
}:

let
  inherit (utils) recImport;

  config = hostName:
  lib.nixosSystem {
    inherit system;

    modules = let
      inherit (home.nixosModules) home-manager;

      common = {
        imports = [
          ../profiles  # hardware-independent system configurations
          ../users
          ../modules
        ];

        hardware.enableRedistributableFirmware = lib.mkDefault true;

        networking.hostName = hostName;
        system.configurationRevision = lib.mkIf (self ? rev) self.rev;
        users.mutableUsers = false;

        nixpkgs.pkgs = pkgs;
        # environment.systemPackages = with pkgs; [
        #   sageWithDoc
        # ];
      };

      machine = import "${toString ./.}/${hostName}.nix";
    in [
      common
      machine
      home-manager
    ];
  };

  hosts = recImport {
    dir = ./.;
    _import = config;
  };
in
hosts

Notably, the overriden version of sageWithDoc is available in my flake output, but not in any of the modules imported from that second file. If, however, I uncomment the environment.systemPackages list, it is available.

If these files look familiar, that’s because I’ve copied most of this from nixflk. The definition of recImport can be found here.

I’ve specified nixpkgs.pkgs = pkgs, so why don’t my modules use this?

2 Likes

I was able to get this working. Here’s a snippet of the change from the ./hosts/default.nix file:

[...]
  config = hostName:
  lib.nixosSystem {
    inherit system;
    inherit pkgs;
[...]

Specifically, I need to pass pkgs explicitly to nixosSystem. I took a look in the eval-config.nix file and it had this comment about the pkgs parameter:

, # !!! is this argument needed any more? The pkgs argument can
  # be set modularly anyway.
  pkgs ? null

I believe setting pkgs modularly is exactly what I did with the nixpkgs.pkgs = pkgs line in the common module. Am I wrong. If this is correct, it very much seems that this parameter is still needed.

6 Likes