I’m trying to pass down some config variables to modules. For instance in my flake.nix I have this hosts set in the let..in to avoid repeating the config for every host. Thing is, I could use this hostName inside my configuration.nix file for say networking.hostName or even in a HomeManager configuration where a script is based on the hostname.
So my question is, how to make sure this variable is usable inside my configuration.nix and my home.nix files? And generally speaking how to pass this set of variables that are host specific, is using the let .. in even a good approach, or is there a better one to make those parameters reachable everywhere?
If you need it in both places, I think so, and no, a module would not avoid the repetition because NixOS modules and HM modules are different things if I’m not mistaken.
Though, in this example it seems you only need it for your NixOS configuration?
Another option is to use overlays (assuming both NixOS and HM share the same pkgs instance), which avoids the repetition of having to do things twice. E.g. assuming the following overlay:
f: p: {
erwyn.hosts = { ... };
}
Then you could access it from anywhere via pkgs.erwyn.hosts.
Though, in this example it seems you only need it for your NixOS configuration?
I actually do, Home Manager is using this hostName for a shell alias for instance.
Another option is to use overlays (assuming both NixOS and HM share the same pkgs instance),
I see. I’m not sure it feels kind of hacky but that gave me an idea: would it be possible to pass it to config instead ?
I’m actually asking this because I just found Passing parameters into import - #4 by Infinisil but I’m not sure how I would pass the hostname to this module so that any other part of the config could access it through config.myConfig.hostName. Or if it’s even a thing actually…
Would you happen to have any guidance or pointers/examples? Following the post I linked I kinda see how to create this module, but what I don’t know is how to include it into my flake.nix and give it the proper parameters.
Thanks for this example! I think I understand better how it is supposed to be glued together but there still might be some blind spots on my side.
I have one issue I see here:
If I’m understanding correctly what’s done here, the config.networking.hostName attr is used to decide which hardware profile to load. In my case I would also like networking.hostName to be determined by name of the nixosConfiguration which is itself based on a list entries in the set. Each configuration has a name, the name has to be used as both hostName of the machine AND used to determine the hardware profile to load.
I feel like:
There should be a descriptive set, somewhere, maybe in another nix file where I can have this:
And then, and I really don’t know how, maybe through the module, I need a few things set:
networking.hostName
whatever config coming from the nixos-hardware module selected from the hostName
whatever other config based on the otherWhateverHostSpecificInfo attrs
So I feel like the module needs to know the configuration’s name and can’t rely on the networking.hostName to determine it as it will set it itself, and the descriptive set needs either to be somewhere else and passed both to the module AND the flake.nix or be in the module itself and reachable from the flake.nix.
Yes, use an anonymous module in your flake.nix that you put in modules.
Then, access your NixOS config via osConfig in HM.
Not at all, you can manually choose a configuration using nixos-rebuild --flake FLAKE#CONFIGNAME. nixos-rebuild just happens to choose the configuration that matches your hostname, by default.
Agreed. What I meant is the module can’t rely on networking.hostName as it will iself declare it. So somewhere we need to have the name of the config available to decide which module/specificities apply there.
The context is that I have 2 hosts on which I want to deploy the same configuration but for a few minor adjustements. As of today those adjustments are:
The networking.hostName
A script that is deployed via HomeManager and that relies on the hostname of the machine
The nixos-hardware module
Although that’s all I need today, I’m trying to grasp the way of doing it properly so that when I need to introduce more specifities later on I know how to get there.
In order to do that, I started by introducing a set in the let...in of my flake.nix file that would describe each possible host and its specifities like this:
This works well for generating each conf and having the correct nixos-hardware module set up, but I don’t know how to provide the hostName variable that is the configuration name from the set to my configuration.nix and home.nix so that I can set networking.hostName and my script with it.
@gvolpe suggested using a module which seems to my novice eyes like a great idea. The thing is that in my understanding the proposed solution moves the descriptive set to configuration.nix which I kinda dislike and make it unavailable in my flake.nix to generate the configurations; also, it relies on the networking.hostName value to choose the nixos-hardware module to select but I don’t know it as I need to get this hostName variable from the flake.nix file to know what the actual hostname of the machine is based on the configuration’s name.
So, I would like to iterate from there (or not using modules if it’s not the correct tool here) so that the descriptive set is somewhere usable in the flake.nix for the configurations generation and in the module itself. Or whatever other solution that is more appropriate.
Wasn’t specialArgs and extraSpecialArgs mentioned above? Either use those to create a new module arg, or use the anonymous module; those are your options. Unless I am misunderstanding your question entirely.
EDIT: Or, there is the option to wrap your flake itself in a lib.evalModules call, in which case you can define options (or args) at the flake level, and pass those into your config. That’s essentially what flake-parts does, though you may find it overkill in some aspects.
Right, my bad, I discarded it because of my lack of knowledge and because we were talking about a slightly different solution when it was first mentioned but now I see that this is actually the way to provide more context to modules.
Thank you both of you for your invaluable inputs that helped me grasping the concepts further and what I was trying to achieve. You’ll tell me if this is completely wrong, but in order to provide closure to this thread I wanted to show what I ended up implementing in case anybody ends up here. This seems to work well and is essentially a merger of both your inputs plus a bit of toying around with map and mergeAttrsList.
1. Having a hostsInventory.nix file to describe my different hosts
I create a hostsInventory.nix file that look like this:
It needs nixos-hardware for the hardwarePresets attribute
2. Creating a module to set host specific attributes
I created a module specificHostConfig.nix that reads a hostConfiguration in order to set config attributes that are host specifics, appart from the nixos-hardware module that need to be set directly in flake.nix:
In my flake.nix file I changed the nixosConfigurations to be generated from the hostsInventory.nix and to pass the hostConfiguration in the specialArgs so that the specificHostConfig.nix module could read it.
I also imported the specificHostConfig module in my modules and imported the correct nixos-hardware module based on the host entry in the inventory:
If I may suggest further optimization to reduce boilerplate, I think that your second step can be avoided completely by defining those settings directly in your hostsInventory.nix file, e.g.: