I’m trying to pass extra arguments into configuration.nix, so I can conditionally activate options based on whether the machine in question is, for instance, a desktop computer or not. This is currently how I’m going about it. The relevant bits of my system flake.nix:
mkNixosConfiguration = machineSpecific: nixpkgs.lib.nixosSystem {
system = machineSpecific.system;
modules = [
({ pkgs, ... }: {
nixpkgs.overlays = [
# ... stuff here ...
];
})
# why do we need to add the pkgs argument here? is it only passed if explicitly specified?
(args @ { pkgs, ... }: import ./configuration.nix ({
inherit machineSpecific;
} // args))
home-manager.nixosModules.home-manager {
# Use the system nixpkgs, not home-manager's own
# This causes it to use our overlays
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit machineSpecific; };
home-manager.users.<my username> = import ./home.nix;
}
];
}
Is there a better way to do this? Is there anything wrong with doing it this way?
I ask because it’s suggested here that it’s recommended not to do what I’ve done with configuration.nix, since the config variable might be incorrect or something? Which I don’t totally understand, since I’m passing along whatever would’ve been passed to the module in the first place.
Also, what’s going on with the pkgs argument to the function that imports ./configuration.nix? pkgs isn’t propagated into configuration.nix unless I explicitly specify it as an argument to that function. Is this intended behavior?
Unfortunately I can’t link to documentation because it’s not rendered for some reason (I should fix that), but the _module.args option should be used to add custom arguments:
So only this is needed, no custom configuration.nix import:
While all the previous answers are technically correct, AFAIK the classic (and less digging-in-the-bowels-of-the-module-system) way is to declare and import a module with an option of appropriate type (e.g. Boolean for isDesktop or an enumeration or whatever suits your needs) and set your configuration values depending on what that option is set to in a given configuration.
The issue with incorrect config in the linked thread was with the comment preceding the one you linked. The pattern you use (and what I used as an example) is fine, just unnecessarily verbose. Well, in your case the verbosity is needed for your chosen approach but there are better ways as mentioned by Silvan and Jake. Plus the subjectively nicer, although more verbose option proposed by Valentin.
Oh yeah very good point. Module arguments are really just untyped and non-namespaced options. Creating a custom option should be preferred over module arguments. In this case it would look like this: