MatthiasBenaets/nix-config

Question on passing arguments to modules

Twiggeh opened this issue · 2 comments

Sorry didnt mean to submit it here, was going to write it in the yt comments but yes anyways.

I was checking your configuration on how you were passing arguments to modules, and it appears that you do it by changing the output = stuff to ouput = inputs @ { ... }, then inside the modules import { inherit variable; }, and finally inside the module you have the specialArgs = {inherit variable; }; and at the very beginning also { some stuff, variable, ... }

The question is whether those 3 pieces is all that is necessary to pass around variables, or whether something else is needed. I was trying for the past 2 days but couldn't find the relevant information, it just results in a "cannot convert set to string" error :(

(variable is just a user = "twiggeh"; so I don't think I am trying to do anything insane; The video is awesome btw ! Thank you so much for making it 😊)

So the output = inputs @ { ... } is pretty much used to pass the channels to the output. These indeed need to be added to the top of the modules so it can actually evaluate it with the correct channels. Otherwise it will think that some options do not exist.
I would not recommend adding random variables in your inputs. Rather declare them under outputs :

let
  user = "twiggeh"
in {

You can set this up in flake.nix to actually take effect throughout the whole flake.
But you can also just add it inside a modules if you use it often and it can differ from module to module.

It's quite hard to figure out where it goes wrong for you since I don't have a reference config so I will just use my own config variable "user" and explain the steps. My first guess is that you just forgot to reference the variable somewhere as an argument, so during the evaluation the user variable does not have a value meaning its not possible to convert to string.

  1. My user for all host is the same, it make sense that I declare it at the top level so in this case flake.nix. This is just a generel variable and not a channel, so I ignore the outputs = inputs @ { ... } where channels are used to evaluate the flake.
  2. For this I use let in as seen in my example above.
  3. Since my nixosConfigurations are declared in another document, i need to inherit user to the document that I import (/nixos-config/hosts/default.nix).
  4. Inside /nixos-config/hosts/default.nix I need to add the argument to the top of the file so it can actually be used since we just inherited it.
  5. Inside the created host I set specialArgs which can then be used inside the modules as an argument so it can be evaluated. So: specialArgs = { inherit user; };
  6. I also want to use this variable in home-manager. Since I have inherited user under specialArgs, I can use it within modules. One of these is home-manager.nixosModules, but again to actually make use of the variable for home-manager modules I need to specify it as well as a special argument. Therefore the option home-manager.extraSpecialArgs = { inherit user; }
  7. Inside the nixosSystem.modules and nixosModules.home-manager I reference configuration.nix and home.nix as a module. Inside these files I don't forget to mention the variable as an argument at the top of the module { user, ... }:.

I should now be able to use the variable and reference the value using ${user} since everything links back to the original declared variable from flake.nix. If this "chain" is broken somewhere, the variable might just be NULL when it get evaluated in a module.

Hopefully with this explanation you can figure out where you are getting stuck with you own setup.

Man thank you! I put the specialArgs = {inherit user;} in the wrong place! I put it not inside the lib.nixosSystem, but into the module itself 😅

Thank you !!! It works now 😊