Dependency not tracked when using path in nixos settings

Suppose I want to reference a file in the settings of a certain service (the settings will be converted to .ini file). This is what I’m currently doing:

{
  services.example = {
    settings = {
      configFile1 = toString ./config/configFile1;
      configFile2 = toString ./config/configFile2;
   };
  };
}

However, using this approach, the dependency won’t be tracked in the derivation of the example service. Once I run nix-garbage-collect, the config files won’t be in nix store anymore as the nixos dir will be removed.

Is there a way to declare the dependency between the config files and the settings?

Thanks

I found one solution is to build a derivation containing those config files. But I’m still confused why a separate derivation is needed here.

When converting a path to a string, it refers to a nix store path, and that path is inside the nixos config dir. Isn’t the nixos config dir added to nix store (when rebuilding the system) as a derivation as well?

builtins.toString does not copy paths to store so it does not add them to string context. String context is what is used to keep track of dependencies during evaluation.

This is because the path passed to builtins.toString does not have to be a store path:

nix-repl> builtins.toString ./lib
"/home/jtojnar/Projects/nixpkgs/lib"

If you want a path to be copied to store you need to, for example, interpolate it into a string:

nix-repl> "${./lib}"                   
"/nix/store/8c8a1b9c9ixh3rr6p32yppjijiwcvnsr-lib"

See Understanding Nix's String Context | Shea's site if you are interested in the nitty-gritty.

1 Like

It’s interesting to know the toString is different from interpolation. Thanks for your answer!