1# Options for Program Settings {#sec-settings-options} 2 3Many programs have configuration files where program-specific settings 4can be declared. File formats can be separated into two categories: 5 6- Nix-representable ones: These can trivially be mapped to a subset of 7 Nix syntax. E.g. JSON is an example, since its values like 8 `{"foo":{"bar":10}}` can be mapped directly to Nix: 9 `{ foo = { bar = 10; }; }`. Other examples are INI, YAML and TOML. 10 The following section explains the convention for these settings. 11 12- Non-nix-representable ones: These can\'t be trivially mapped to a 13 subset of Nix syntax. Most generic programming languages are in this 14 group, e.g. bash, since the statement `if true; then echo hi; fi` 15 doesn\'t have a trivial representation in Nix. 16 17 Currently there are no fixed conventions for these, but it is common 18 to have a `configFile` option for setting the configuration file 19 path directly. The default value of `configFile` can be an 20 auto-generated file, with convenient options for controlling the 21 contents. For example an option of type `attrsOf str` can be used 22 for representing environment variables which generates a section 23 like `export FOO="foo"`. Often it can also be useful to also include 24 an `extraConfig` option of type `lines` to allow arbitrary text 25 after the autogenerated part of the file. 26 27## Nix-representable Formats (JSON, YAML, TOML, INI, \...) {#sec-settings-nix-representable} 28 29By convention, formats like this are handled with a generic `settings` 30option, representing the full program configuration as a Nix value. The 31type of this option should represent the format. The most common formats 32have a predefined type and string generator already declared under 33`pkgs.formats`: 34 35`pkgs.formats.json` { } 36 37: A function taking an empty attribute set (for future extensibility) 38 and returning a set with JSON-specific attributes `type` and 39 `generate` as specified [below](#pkgs-formats-result). 40 41`pkgs.formats.yaml` { } 42 43: A function taking an empty attribute set (for future extensibility) 44 and returning a set with YAML-specific attributes `type` and 45 `generate` as specified [below](#pkgs-formats-result). 46 47`pkgs.formats.ini` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \... } 48 49: A function taking an attribute set with values 50 51 `listsAsDuplicateKeys` 52 53 : A boolean for controlling whether list values can be used to 54 represent duplicate INI keys 55 56 `listToValue` 57 58 : A function for turning a list of values into a single value. 59 60 It returns a set with INI-specific attributes `type` and `generate` 61 as specified [below](#pkgs-formats-result). 62 63`pkgs.formats.toml` { } 64 65: A function taking an empty attribute set (for future extensibility) 66 and returning a set with TOML-specific attributes `type` and 67 `generate` as specified [below](#pkgs-formats-result). 68 69::: {#pkgs-formats-result} 70These functions all return an attribute set with these values: 71::: 72 73`type` 74 75: A module system type representing a value of the format 76 77`generate` *`filename jsonValue`* 78 79: A function that can render a value of the format to a file. Returns 80 a file path. 81 82 ::: {.note} 83 This function puts the value contents in the Nix store. So this 84 should be avoided for secrets. 85 ::: 86 87::: {#ex-settings-nix-representable .example} 88::: {.title} 89**Example: Module with conventional `settings` option** 90::: 91The following shows a module for an example program that uses a JSON 92configuration file. It demonstrates how above values can be used, along 93with some other related best practices. See the comments for 94explanations. 95 96```nix 97{ options, config, lib, pkgs, ... }: 98let 99 cfg = config.services.foo; 100 # Define the settings format used for this program 101 settingsFormat = pkgs.formats.json {}; 102in { 103 104 options.services.foo = { 105 enable = lib.mkEnableOption "foo service"; 106 107 settings = lib.mkOption { 108 # Setting this type allows for correct merging behavior 109 type = settingsFormat.type; 110 default = {}; 111 description = '' 112 Configuration for foo, see 113 <link xlink:href="https://example.com/docs/foo"/> 114 for supported settings. 115 ''; 116 }; 117 }; 118 119 config = lib.mkIf cfg.enable { 120 # We can assign some default settings here to make the service work by just 121 # enabling it. We use `mkDefault` for values that can be changed without 122 # problems 123 services.foo.settings = { 124 # Fails at runtime without any value set 125 log_level = lib.mkDefault "WARN"; 126 127 # We assume systemd's `StateDirectory` is used, so we require this value, 128 # therefore no mkDefault 129 data_path = "/var/lib/foo"; 130 131 # Since we use this to create a user we need to know the default value at 132 # eval time 133 user = lib.mkDefault "foo"; 134 }; 135 136 environment.etc."foo.json".source = 137 # The formats generator function takes a filename and the Nix value 138 # representing the format value and produces a filepath with that value 139 # rendered in the format 140 settingsFormat.generate "foo-config.json" cfg.settings; 141 142 # We know that the `user` attribute exists because we set a default value 143 # for it above, allowing us to use it without worries here 144 users.users.${cfg.settings.user} = { isSystemUser = true; }; 145 146 # ... 147 }; 148} 149``` 150::: 151 152### Option declarations for attributes {#sec-settings-attrs-options} 153 154Some `settings` attributes may deserve some extra care. They may need a 155different type, default or merging behavior, or they are essential 156options that should show their documentation in the manual. This can be 157done using [](#sec-freeform-modules). 158 159We extend above example using freeform modules to declare an option for 160the port, which will enforce it to be a valid integer and make it show 161up in the manual. 162 163::: {#ex-settings-typed-attrs .example} 164::: {.title} 165**Example: Declaring a type-checked `settings` attribute** 166::: 167```nix 168settings = lib.mkOption { 169 type = lib.types.submodule { 170 171 freeformType = settingsFormat.type; 172 173 # Declare an option for the port such that the type is checked and this option 174 # is shown in the manual. 175 options.port = lib.mkOption { 176 type = lib.types.port; 177 default = 8080; 178 description = '' 179 Which port this service should listen on. 180 ''; 181 }; 182 183 }; 184 default = {}; 185 description = '' 186 Configuration for Foo, see 187 <link xlink:href="https://example.com/docs/foo"/> 188 for supported values. 189 ''; 190}; 191``` 192:::