Home Explore Blog CI



nixpkgs

7th chunk of `nixos/doc/manual/development/settings-options.section.md`
5a14e71ccff8b8927d22008c22cc4bf6c15932f13862b1e90000000100000c7c
    :::

::: {#ex-settings-nix-representable .example}
### Module with conventional `settings` option

The following shows a module for an example program that uses a JSON
configuration file. It demonstrates how above values can be used, along
with some other related best practices. See the comments for
explanations.

```nix
{ options, config, lib, pkgs, ... }:
let
  cfg = config.services.foo;
  # Define the settings format used for this program
  settingsFormat = pkgs.formats.json {};
in {

  options.services.foo = {
    enable = lib.mkEnableOption "foo service";

    settings = lib.mkOption {
      # Setting this type allows for correct merging behavior
      type = settingsFormat.type;
      default = {};
      description = ''
        Configuration for foo, see
        <link xlink:href="https://example.com/docs/foo"/>
        for supported settings.
      '';
    };
  };

  config = lib.mkIf cfg.enable {
    # We can assign some default settings here to make the service work by just
    # enabling it. We use `mkDefault` for values that can be changed without
    # problems
    services.foo.settings = {
      # Fails at runtime without any value set
      log_level = lib.mkDefault "WARN";

      # We assume systemd's `StateDirectory` is used, so we require this value,
      # therefore no mkDefault
      data_path = "/var/lib/foo";

      # Since we use this to create a user we need to know the default value at
      # eval time
      user = lib.mkDefault "foo";
    };

    environment.etc."foo.json".source =
      # The formats generator function takes a filename and the Nix value
      # representing the format value and produces a filepath with that value
      # rendered in the format
      settingsFormat.generate "foo-config.json" cfg.settings;

    # We know that the `user` attribute exists because we set a default value
    # for it above, allowing us to use it without worries here
    users.users.${cfg.settings.user} = { isSystemUser = true; };

    # ...
  };
}
```
:::

### Option declarations for attributes {#sec-settings-attrs-options}

Some `settings` attributes may deserve some extra care. They may need a
different type, default or merging behavior, or they are essential
options that should show their documentation in the manual. This can be
done using [](#sec-freeform-modules).

We extend above example using freeform modules to declare an option for
the port, which will enforce it to be a valid integer and make it show
up in the manual.

::: {#ex-settings-typed-attrs .example}
### Declaring a type-checked `settings` attribute
```nix
{
  settings = lib.mkOption {
    type = lib.types.submodule {

      freeformType = settingsFormat.type;

      # Declare an option for the port such that the type is checked and this option
      # is shown in the manual.
      options.port = lib.mkOption {
        type = lib.types.port;
        default = 8080;
        description = ''
          Which port this service should listen on.
        '';
      };

    };
    default = {};
    description = ''
      Configuration for Foo, see
      <link xlink:href="https://example.com/docs/foo"/>
      for supported values.
    '';
  };
}
```
:::

Title: Module with Conventional 'settings' Option and Option Declarations
Summary
The first example shows a module configuration for a 'foo' service that uses a JSON configuration file. It defines options for enabling the service and setting its configuration. It assigns default settings, such as log level, requires a data path, and creates a system user. It also generates a configuration file and defines a system user based on the settings. The second example shows how to create specific options for attributes within the 'settings', such as declaring an option for the port, checking its type, and displaying it in the manual.