Passing parameters into import

Hello folks,

I’m new at NixOS and I’m having problems with structuring my configurations. Basic setup is done, but I want to deploy my files to different machines via git. One part of my config contains all user programs with their specific configurations etc. I want to use the same config on my other machine, but with a different username.
I could just copy the file and changing the username, but than I’ll have to apply all future changes to both files.
Is there any way to pass parameters (like username etc.) into my imported files from configuration.nix? Or is there another good practice for things like that? I already found some (older) posts on that topic, but none of them worked or fit’s my purpose.

Thanks in advance!

#users.nix
{ config, pkgs, lib, ... }:
{
  users.users.larry = {
    description = "Larry Larryson";
    isNormalUser = true;
    extraGroups = [ "wheel" "scanner" "lp" ]; # Enable ‘sudo’ for the user.
    initialPassword = "1234";
    shell = pkgs.zsh;  
    packages = with pkgs; [
      firefox
      ...
  };
}
#configuration.nix                                       
{ config, pkgs, lib, ... }:
let
  user = "larry";
in {  
  networking.hostName = "larry-pc";

  imports = [
    ./hardware-configuration.nix
    ./users.nix # Some import parameters here like user etc. ?!?
  ]

  ...
}

I placed an answer in the SO post you link years ago that should work:

If you prefer you can avoid mixing standard and ad hoc arguments like I do in the answer by creating a module that takes two arguments, instead of one, i.e.:

# module.nix
{ argA, argB, ... }: { config, pkgs, ... }: {
  # module code
}
# how to import module.nix
{ imports = [ (import ./module.nix { argA = 1; arbB = 2; }) ]; }
2 Likes

So simple…

Thanks for fast reply! :slight_smile:

Passing individual arguments to modules is generally an anti-pattern because those arguments can’t be overridden anymore and aren’t type checked.

Instead it’s better for modules to expose options to customise their behavior, e.g.

{
  imports = [ ./myModule.nix ];
  
  myModule.argA = 1;
  myModule.argB = 2;
}

where in module.nix you have

{ lib, config, ... }: {
  options.myModule.argA = lib.mkOption {
    type = lib.types.int;
  };
  options.myModule.argB = lib.mkOption {
    type = lib.types.int;
  };

  config = {
    environment.etc.a.text = toString config.myModule.argA;
    environment.etc.b.text = toString config.myModule.argB;
  };
}
8 Likes