Difference between a module's config property and directly defining options

I’ve been reading manual on how to define NixOS modules, trying to wrap my head around the inner workings of how the system all comes together. As far as I understand, any file I include with the imports statement, as well as my top-level configuration.nix is referred to as a module. The documentation states that modules can contain an options property to declare options (as in: what types they have) and a config section which then defines actual values for these options (which have been declared in other modules).

Here comes my question: how does this config property differ from simply defining values at the top-level? For example, I’m not sure where the difference is between these two modules:

{ config, ... }: 

{
  environment.etc.firstfile.text = "hello";
  environment.etc.secondfile.text = config.networking.hostName;
}
{ config, ... }: 

{
  config = {
    environment.etc.firstfile.text = "hello";
    environment.etc.secondfile.text = config.networking.hostName;
  };
}

In both cases, I get “hello” in /etc/firstfile and the system’s hostname in /etc/secondfile. If any property that doesn’t have a special meaning gets merged into config anyway, what’s the point of having a special config property? And why do most modules use config instead of directly defining options?

1 Like

And as a follow-up question: in my second example, which config is line 6 referencing? In my understanding, it should be the config from line 1 and not from line 4, since the latter doesn’t use rec, correct?

That’s correct.

As for the difference between putting definitions under config or not, it’s just because doing so is optional if you’re not also declaring options. Just makes config-only files (like a typical beginner’s configuration.nix) a little cleaner looking. Once you want to declare some new options though, you have to put your config definitions under config.

2 Likes

Just want to point it out that if you wanted to reference a value defined inside the config from line 4 (e.g., on line 5) on line 6, you would be able to. While it is correct to say you are using the config from line 1, that one is actually a fixed point created by merging the config in each module, including the one from line 4.

Great - thanks for both of your explanations!