Confirm how to pass references through imports

Hi there, I have the following files being imported in a chain:

flake.nix → home/rembot/default.nix → modules/default.nix → git/default.nix

(rembot = host, and the other files are via home-manager.)

What I am trying to do is pass a “secrets” reference down this chain. I am reading a json file with some sensitive info.

I am working from the “git-crypt” section of this article

So… I am going to post the relevant code snippets with a little context pre and post.

flake.nix

so here I am defining “secrets” reading from a JSON file. Then via “sepcialArgs”, I am passing the secrets reference.

outputs =
    inputs@{ self, nixpkgs, nixvim, home-manager, nixos-hardware, nur, ... }:
    let
      nixpkgsConfig = { overlays = [ ]; };
      secrets =
        builtins.fromJSON (builtins.readFile "${self}/secrets/secrets.json");
    in {

      nixosConfigurations = {

# Fulrther down, to  myhost:

# rembot = desktop hostname
        rembot = nixpkgs.lib.nixosSystem {
          specialArgs = { inherit inputs secrets; };
          system = "x86_64-linux";
          modules = [
            home-manager.nixosModules.home-manager
            {
              home-manager.useGlobalPkgs = true;
              home-manager.useUserPackages = true;
              home-manager.users.dustin = {
                imports =
                  [ ./home/rembot ];
              };

/home/rembot

Here I am passing in “secrets” so the context (if I understand correctly) continues with the imports.

{ config, inputs, pkgs, secrets, ... }: {
  # Home Manager needs a bit of information about you and the
  # paths it should manage.
  home.username = "dustin";
  home.homeDirectory = "/home/dustin";

  imports = [ ../modules ../modules/gnome ];

…/modules

Nothing crazy, simply adding “secrets”, and the next import.,

{ config, inputs, pkgs, secrets, ... }: {

  imports = [
# snip
    ./git
#snip
  ];

}

./git/default.nix

here, have secrets coming in, and they try to use a value.

{ pkgs, lib, secrets, ... }:
# let globalconf = import ../../cfg;
#in
{
  programs = {
    git = {
      enable = true;
      userName = "${secrets.git.username}";


# snipped


But when I run my rebuild, I am getting:

error: attribute 'secrets' missing

I must be doing something wrong.

Thank you.

Cheers.

Home-Manager is doing its own thing. Try adding:

home-manager.extraSpecialArgs = { inherit secrets; };
1 Like

The first three modules only evaluate because you are not actually referencing secrets argument in them. (I guess it is laziness at work.)

The issue is that you are passing the value to specialArgs of NixOS module evaluation but home-manager evaluates each user configuration module separately. So you will need to pass the arguments to those modules as well like @polygon mentions.

Though note that _module.args option is prefered over specialArgs & co.:

So you would do something like this:

nixpkgs.lib.nixosSystem {
  system = "x86_64-linux";
  modules = [
    home-manager.nixosModules.home-manager
    {
      # Here are the arguments injected for NixOS:
      module._args = { inherit inputs secrets; };

      home-manager.useGlobalPkgs = true;
      home-manager.useUserPackages = true;
      home-manager.users.dustin = {
        # And here for the hm user config:
        module._args = { inherit inputs secrets; };
        imports =
          [ ./home/rembot ];
      };
1 Like

That solved it! I did not realize the home manager did that separately.

I will have a look at this!

modules = [
    home-manager.nixosModules.home-manager
    {
      # Here are the arguments injected for NixOS:
      module._args = { inherit inputs secrets; };

Wouldn’t the module._args = { inherit inputs secrets; }; need to be outside the home-manager.nixosModules.home-manager though? (in some other way). I am not very good at nix yet, but it seems odd to me that it would be where you had shown the NixOS injected arguments.

Though note that _module.args option is prefered over specialArgs & co.:

Interesting, I need to look into this. Thank you!

In Nix, list elements are separated by white space and this takes precedence over function application so the attribute set is not an argument of home-manager.nixosModules.home-manager – you are including two separate modules:

  • home-manager NixOS module pulled in from home-manager flake (home-manager.nixosModules.home-manager)
  • a NixOS module defined inline (an attribute set). This one contains the following:
    • definition of module._args option (declared by the module system itself)
    • definition of some NixOS options declared by the home-manager NixOS module (imported above)
      • one of those options (home-manager.users.dustin) takes a home-manager module as the value, you are providing it inline
        • home-manager just uses a separate instance of NixOS module system so the module._args option is available there as well

You can split the NixOS module into multiple attribute sets if you prefer to have home-manager’s NixOS options separately from other NixOS options but, in the end, all listed NixOS modules (and their transitive imports) will be merged into a single configuration when the modules are evaluated.

1 Like