How to provide module config defaults that can be changed

I am trying to make the health configuration of the excellent netdata service easy. I parse all the default config files and convert them to an attrset, and then I generate a new config file from the attrset.

I would like to simply add attributes to the attrset, but also change the defaults.

How can I make it so that services.netdata.health is an attrset with the defaults and it can be altered, e.g. setting services.netdata.health.disk_space_usage.enabled = false?

I think you can use a submodule.

Well yeah, but that doesn’t give me the defaults I think?

In any case, I just figured it out: I added

imports: [{services.netdata.health = ...;}];

which simply populates the value. Seems to work, but not sure about overriding values :-/

Create a new module under your own namespace: wout.services.netdata

Give it an enable option and a settings attr.

In there you define some defaults and then do something like:

{
  cfg = config.wout.services.netdata;

  let
    finalSettings = lib.recursiveUpdate {
      my: "default";
      settings: 132;
    } cfg.settings;
  in
  {
    config = lib.mkMerge [
      (lib.mkIf cfg.enable {
        services.netdata = {
          enable = true;
          settings = finalSettings;
        };
      })

    ];
  }
}

This way you set the settings in your own namespace that then get merged in with your defaults and put where you want them.

This is how I have done it for everything.

Thanks, that’s indeed a nice solution, but I want to put this in the official netdata module, so I can’t do that here.

importing defaults gives them the same priority as user values, which is terrible for overriding. it can also be done in the module itself without an import as an unconditional assignment. what you really want to to is what eg kubernetes does: https://github.com/NixOS/nixpkgs/blob/68196a61c26748d3e53a6803de3d2f8c69f27831/nixos/modules/services/cluster/kubernetes/default.nix#L259

1 Like

You need 2 things:

  1. a set of default settings applied to all hosts, and
  2. host specific settings that override/add to the defaults

The netdata module only has a single set so that means you have to keep that somewhere. You could of course do this by having a helper function that reads stuff from a file when you assign to the settings for that given host or split up the existing settings into defaultSettings and settings or something like that.

I personally think that’s a bad idea. The cleanest option is to extend the module system - your case is not going to be general anyway.

The problem right now is that the netdata health configuration is hard to configure, and with the system I have now you can easily add a typechecked configuration, and override the configurations that are there.
So I’m not configuring anything for me, I’m making it easy for everyone. I’ll make a PR soon.

The solution that @pennae gave is what I needed.