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.javaProperties` { *`comment`* ? `"Generated with Nix"` } 36 37: A function taking an attribute set with values 38 39 `comment` 40 41 : A string to put at the start of the 42 file in a comment. It can have multiple 43 lines. 44 45 It returns the `type`: `attrsOf str` and a function 46 `generate` to build a Java `.properties` file, taking 47 care of the correct escaping, etc. 48 49`pkgs.formats.json` { } 50 51: A function taking an empty attribute set (for future extensibility) 52 and returning a set with JSON-specific attributes `type` and 53 `generate` as specified [below](#pkgs-formats-result). 54 55`pkgs.formats.yaml` { } 56 57: A function taking an empty attribute set (for future extensibility) 58 and returning a set with YAML-specific attributes `type` and 59 `generate` as specified [below](#pkgs-formats-result). 60 61`pkgs.formats.ini` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \.\.\. } 62 63: A function taking an attribute set with values 64 65 `listsAsDuplicateKeys` 66 67 : A boolean for controlling whether list values can be used to 68 represent duplicate INI keys 69 70 `listToValue` 71 72 : A function for turning a list of values into a single value. 73 74 It returns a set with INI-specific attributes `type` and `generate` 75 as specified [below](#pkgs-formats-result). 76 The type of the input is an *attrset* of sections; key-value pairs where 77 the key is the section name and the value is the corresponding content 78 which is also an *attrset* of key-value pairs for the actual key-value 79 mappings of the INI format. 80 The values of the INI atoms are subject to the above parameters (e.g. lists 81 may be transformed into multiple key-value pairs depending on 82 `listToValue`). 83 84`pkgs.formats.iniWithGlobalSection` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \.\.\. } 85 86: A function taking an attribute set with values 87 88 `listsAsDuplicateKeys` 89 90 : A boolean for controlling whether list values can be used to 91 represent duplicate INI keys 92 93 `listToValue` 94 95 : A function for turning a list of values into a single value. 96 97 It returns a set with INI-specific attributes `type` and `generate` 98 as specified [below](#pkgs-formats-result). 99 The type of the input is an *attrset* of the structure 100 `{ sections = {}; globalSection = {}; }` where *sections* are several 101 sections as with *pkgs.formats.ini* and *globalSection* being just a single 102 attrset of key-value pairs for a single section, the global section which 103 preceedes the section definitions. 104 105`pkgs.formats.toml` { } 106 107: A function taking an empty attribute set (for future extensibility) 108 and returning a set with TOML-specific attributes `type` and 109 `generate` as specified [below](#pkgs-formats-result). 110 111`pkgs.formats.elixirConf { elixir ? pkgs.elixir }` 112 113: A function taking an attribute set with values 114 115 `elixir` 116 117 : The Elixir package which will be used to format the generated output 118 119 It returns a set with Elixir-Config-specific attributes `type`, `lib`, and 120 `generate` as specified [below](#pkgs-formats-result). 121 122 The `lib` attribute contains functions to be used in settings, for 123 generating special Elixir values: 124 125 `mkRaw elixirCode` 126 127 : Outputs the given string as raw Elixir code 128 129 `mkGetEnv { envVariable, fallback ? null }` 130 131 : Makes the configuration fetch an environment variable at runtime 132 133 `mkAtom atom` 134 135 : Outputs the given string as an Elixir atom, instead of the default 136 Elixir binary string. Note: lowercase atoms still needs to be prefixed 137 with `:` 138 139 `mkTuple array` 140 141 : Outputs the given array as an Elixir tuple, instead of the default 142 Elixir list 143 144 `mkMap attrset` 145 146 : Outputs the given attribute set as an Elixir map, instead of the 147 default Elixir keyword list 148 149`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php} 150 151: A function taking an attribute set with values 152 153 `finalVariable` 154 155 : The variable that will store generated expression (usually `config`). If set to `null`, generated expression will contain `return`. 156 157 It returns a set with PHP-Config-specific attributes `type`, `lib`, and 158 `generate` as specified [below](#pkgs-formats-result). 159 160 The `lib` attribute contains functions to be used in settings, for 161 generating special PHP values: 162 163 `mkRaw phpCode` 164 165 : Outputs the given string as raw PHP code 166 167 `mkMixedArray list set` 168 169 : Creates PHP array that contains both indexed and associative values. For example, `lib.mkMixedArray [ "hello" "world" ] { "nix" = "is-great"; }` returns `['hello', 'world', 'nix' => 'is-great']` 170 171[]{#pkgs-formats-result} 172These functions all return an attribute set with these values: 173 174`type` 175 176: A module system type representing a value of the format 177 178`lib` 179 180: Utility functions for convenience, or special interactions with the format. 181 This attribute is optional. It may contain inside a `types` attribute 182 containing types specific to this format. 183 184`generate` *`filename jsonValue`* 185 186: A function that can render a value of the format to a file. Returns 187 a file path. 188 189 ::: {.note} 190 This function puts the value contents in the Nix store. So this 191 should be avoided for secrets. 192 ::: 193 194::: {#ex-settings-nix-representable .example} 195### Module with conventional `settings` option 196 197The following shows a module for an example program that uses a JSON 198configuration file. It demonstrates how above values can be used, along 199with some other related best practices. See the comments for 200explanations. 201 202```nix 203{ options, config, lib, pkgs, ... }: 204let 205 cfg = config.services.foo; 206 # Define the settings format used for this program 207 settingsFormat = pkgs.formats.json {}; 208in { 209 210 options.services.foo = { 211 enable = lib.mkEnableOption "foo service"; 212 213 settings = lib.mkOption { 214 # Setting this type allows for correct merging behavior 215 type = settingsFormat.type; 216 default = {}; 217 description = '' 218 Configuration for foo, see 219 <link xlink:href="https://example.com/docs/foo"/> 220 for supported settings. 221 ''; 222 }; 223 }; 224 225 config = lib.mkIf cfg.enable { 226 # We can assign some default settings here to make the service work by just 227 # enabling it. We use `mkDefault` for values that can be changed without 228 # problems 229 services.foo.settings = { 230 # Fails at runtime without any value set 231 log_level = lib.mkDefault "WARN"; 232 233 # We assume systemd's `StateDirectory` is used, so we require this value, 234 # therefore no mkDefault 235 data_path = "/var/lib/foo"; 236 237 # Since we use this to create a user we need to know the default value at 238 # eval time 239 user = lib.mkDefault "foo"; 240 }; 241 242 environment.etc."foo.json".source = 243 # The formats generator function takes a filename and the Nix value 244 # representing the format value and produces a filepath with that value 245 # rendered in the format 246 settingsFormat.generate "foo-config.json" cfg.settings; 247 248 # We know that the `user` attribute exists because we set a default value 249 # for it above, allowing us to use it without worries here 250 users.users.${cfg.settings.user} = { isSystemUser = true; }; 251 252 # ... 253 }; 254} 255``` 256::: 257 258### Option declarations for attributes {#sec-settings-attrs-options} 259 260Some `settings` attributes may deserve some extra care. They may need a 261different type, default or merging behavior, or they are essential 262options that should show their documentation in the manual. This can be 263done using [](#sec-freeform-modules). 264 265We extend above example using freeform modules to declare an option for 266the port, which will enforce it to be a valid integer and make it show 267up in the manual. 268 269::: {#ex-settings-typed-attrs .example} 270### Declaring a type-checked `settings` attribute 271```nix 272{ 273 settings = lib.mkOption { 274 type = lib.types.submodule { 275 276 freeformType = settingsFormat.type; 277 278 # Declare an option for the port such that the type is checked and this option 279 # is shown in the manual. 280 options.port = lib.mkOption { 281 type = lib.types.port; 282 default = 8080; 283 description = '' 284 Which port this service should listen on. 285 ''; 286 }; 287 288 }; 289 default = {}; 290 description = '' 291 Configuration for Foo, see 292 <link xlink:href="https://example.com/docs/foo"/> 293 for supported values. 294 ''; 295 }; 296} 297``` 298:::