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.hocon` { *`generator`* ? `<derivation>`, *`validator`* ? `<derivation>`, *`doCheck`* ? true } 50 51: A function taking an attribute set with values 52 53 `generator` 54 55 : A derivation used for converting the JSON output 56 from the nix settings into HOCON. This might be 57 useful if your HOCON variant is slightly different 58 from the java-based one, or for testing purposes. 59 60 `validator` 61 62 : A derivation used for verifying that the HOCON 63 output is correct and parsable. This might be 64 useful if your HOCON variant is slightly different 65 from the java-based one, or for testing purposes. 66 67 `doCheck` 68 69 : Whether to enable/disable the validator check. 70 71 It returns an attrset with a `type`, `generate` function, 72 and a `lib` attset, as specified [below](#pkgs-formats-result). 73 Some of the lib functions will be best understood if you have 74 read the reference specification. You can find this 75 specification here: 76 77 <https://github.com/lightbend/config/blob/main/HOCON.md> 78 79 Inside of `lib`, you will find these functions 80 81 `mkInclude` 82 83 : This is used together with a specially named 84 attribute `includes`, to include other HOCON 85 sources into the document. 86 87 The function has a shorthand variant where it 88 is up to the HOCON parser to figure out what type 89 of include is being used. The include will default 90 to being non-required. If you want to be more 91 explicit about the details of the include, you can 92 provide an attrset with following arguments 93 94 `required` 95 96 : Whether the parser should fail upon failure 97 to include the document 98 99 `type` 100 101 : Type of the source of the included document. 102 Valid values are `file`, `url` and `classpath`. 103 See upstream documentation for the semantics 104 behind each value 105 106 `value` 107 108 : The URI/path/classpath pointing to the source of 109 the document to be included. 110 111 `Example usage:` 112 113 ```nix 114 let 115 format = pkgs.formats.hocon { }; 116 hocon_file = pkgs.writeText "to_include.hocon" '' 117 a = 1; 118 ''; 119 in { 120 some.nested.hocon.attrset = { 121 _includes = [ 122 (format.lib.mkInclude hocon_file) 123 (format.lib.mkInclude "https://example.com/to_include.hocon") 124 (format.lib.mkInclude { 125 required = true; 126 type = "file"; 127 value = include_file; 128 }) 129 ]; 130 ... 131 }; 132 } 133 ``` 134 135 `mkAppend` 136 137 : This is used to invoke the `+=` operator. 138 This can be useful if you need to add something 139 to a list that is included from outside of nix. 140 See upstream documentation for the semantics 141 behind the `+=` operation. 142 143 `Example usage:` 144 145 ```nix 146 let 147 format = pkgs.formats.hocon { }; 148 hocon_file = pkgs.writeText "to_include.hocon" '' 149 a = [ 1 ]; 150 b = [ 2 ]; 151 ''; 152 in { 153 _includes = [ 154 (format.lib.mkInclude hocon_file) 155 ]; 156 157 c = 3; 158 a = format.lib.mkAppend 3; 159 b = format.lib.mkAppend (format.lib.mkSubstitution "c"); 160 } 161 ``` 162 163 `mkSubstitution` 164 165 : This is used to make HOCON substitutions. 166 Similarly to `mkInclude`, this function has 167 a shorthand variant where you just give it 168 the string with the substitution value. 169 The substitution is not optional by default. 170 Alternatively, you can provide an attrset 171 with more options 172 173 `optional` 174 175 : Whether the parser should fail upon 176 failure to fetch the substitution value. 177 178 `value` 179 180 : The name of the variable to use for 181 substitution. 182 183 See upstream documentation for semantics 184 behind the substitution functionality. 185 186 `Example usage:` 187 188 ```nix 189 let 190 format = pkgs.formats.hocon { }; 191 in { 192 a = 1; 193 b = format.lib.mkSubstitution "a"; 194 c = format.lib.mkSubstitution "SOME_ENVVAR"; 195 d = format.lib.mkSubstitution { 196 value = "SOME_OPTIONAL_ENVVAR"; 197 optional = true; 198 }; 199 } 200 ``` 201 202 `Implementation notes:` 203 204 - classpath includes are not implemented in pyhocon, 205 which is used for validating the HOCON output. This 206 means that if you are using classpath includes, 207 you will want to either use an alternative validator 208 or set `doCheck = false` in the format options. 209 210`pkgs.formats.libconfig` { *`generator`* ? `<derivation>`, *`validator`* ? `<derivation>` } 211 212: A function taking an attribute set with values 213 214 `generator` 215 216 : A derivation used for converting the JSON output 217 from the nix settings into libconfig. This might be 218 useful if your libconfig variant is slightly different 219 from the original one, or for testing purposes. 220 221 `validator` 222 223 : A derivation used for verifying that the libconfig 224 output is correct and parsable. This might be 225 useful if your libconfig variant is slightly different 226 from the original one, or for testing purposes. 227 228 It returns an attrset with a `type`, `generate` function, 229 and a `lib` attset, as specified [below](#pkgs-formats-result). 230 Some of the lib functions will be best understood if you have 231 read the reference specification. You can find this 232 specification here: 233 234 <https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files> 235 236 Inside of `lib`, you will find these functions 237 238 `mkHex`, `mkOctal`, `mkFloat` 239 240 : Use these to specify numbers in other formats. 241 242 `Example usage:` 243 244 ```nix 245 let 246 format = pkgs.formats.libconfig { }; 247 in { 248 myHexValue = format.lib.mkHex "0x1FC3"; 249 myOctalValue = format.lib.mkOctal "0027"; 250 myFloatValue = format.lib.mkFloat "1.2E-3"; 251 } 252 ``` 253 254 `mkArray`, `mkList` 255 256 : Use these to differentiate between whether 257 a nix list should be considered as a libconfig 258 array or a libconfig list. See the upstream 259 documentation for the semantics behind these types. 260 261 `Example usage:` 262 263 ```nix 264 let 265 format = pkgs.formats.libconfig { }; 266 in { 267 myList = format.lib.mkList [ "foo" 1 true ]; 268 myArray = format.lib.mkArray [ 1 2 3 ]; 269 } 270 ``` 271 272 `Implementation notes:` 273 274 - Since libconfig does not allow setting names to start with an underscore, 275 this is used as a prefix for both special types and include directives. 276 277 - The difference between 32bit and 64bit values became optional in libconfig 278 1.5, so we assume 64bit values for all numbers. 279 280`pkgs.formats.json` { } 281 282: A function taking an empty attribute set (for future extensibility) 283 and returning a set with JSON-specific attributes `type` and 284 `generate` as specified [below](#pkgs-formats-result). 285 286`pkgs.formats.yaml` { } 287 288: A function taking an empty attribute set (for future extensibility) 289 and returning a set with YAML-specific attributes `type` and 290 `generate` as specified [below](#pkgs-formats-result). 291 292`pkgs.formats.ini` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \.\.\. } 293 294: A function taking an attribute set with values 295 296 `listsAsDuplicateKeys` 297 298 : A boolean for controlling whether list values can be used to 299 represent duplicate INI keys 300 301 `listToValue` 302 303 : A function for turning a list of values into a single value. 304 305 It returns a set with INI-specific attributes `type` and `generate` 306 as specified [below](#pkgs-formats-result). 307 The type of the input is an *attrset* of sections; key-value pairs where 308 the key is the section name and the value is the corresponding content 309 which is also an *attrset* of key-value pairs for the actual key-value 310 mappings of the INI format. 311 The values of the INI atoms are subject to the above parameters (e.g. lists 312 may be transformed into multiple key-value pairs depending on 313 `listToValue`). 314 315 The attribute `lib.type.atom` contains the used INI atom. 316 317`pkgs.formats.iniWithGlobalSection` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \.\.\. } 318 319: A function taking an attribute set with values 320 321 `listsAsDuplicateKeys` 322 323 : A boolean for controlling whether list values can be used to 324 represent duplicate INI keys 325 326 `listToValue` 327 328 : A function for turning a list of values into a single value. 329 330 It returns a set with INI-specific attributes `type` and `generate` 331 as specified [below](#pkgs-formats-result). 332 The type of the input is an *attrset* of the structure 333 `{ sections = {}; globalSection = {}; }` where *sections* are several 334 sections as with *pkgs.formats.ini* and *globalSection* being just a single 335 attrset of key-value pairs for a single section, the global section which 336 precedes the section definitions. 337 338 The attribute `lib.type.atom` contains the used INI atom. 339 340`pkgs.formats.toml` { } 341 342: A function taking an empty attribute set (for future extensibility) 343 and returning a set with TOML-specific attributes `type` and 344 `generate` as specified [below](#pkgs-formats-result). 345 346`pkgs.formats.xml` { format ? "badgerfish", withHeader ? true} 347 348: A function taking an attribute set with values 349 and returning a set with XML-specific attributes `type` and 350 `generate` as specified [below](#pkgs-formats-result). 351 352 `format` 353 354 : Input format. Because XML can not be translated one-to-one, we have to use intermediate formats. Possible values: 355 - `"badgerfish"`: Uses [badgerfish](http://www.sklar.com/badgerfish/) conversion. 356 357 `withHeader` 358 359 : Outputs the xml with header. 360 361`pkgs.formats.cdn` { } 362 363: A function taking an empty attribute set (for future extensibility) 364 and returning a set with [CDN](https://github.com/dzikoysk/cdn)-specific 365 attributes `type` and `generate` as specified [below](#pkgs-formats-result). 366 367`pkgs.formats.elixirConf { elixir ? pkgs.elixir }` 368 369: A function taking an attribute set with values 370 371 `elixir` 372 373 : The Elixir package which will be used to format the generated output 374 375 It returns a set with Elixir-Config-specific attributes `type`, `lib`, and 376 `generate` as specified [below](#pkgs-formats-result). 377 378 The `lib` attribute contains functions to be used in settings, for 379 generating special Elixir values: 380 381 `mkRaw elixirCode` 382 383 : Outputs the given string as raw Elixir code 384 385 `mkGetEnv { envVariable, fallback ? null }` 386 387 : Makes the configuration fetch an environment variable at runtime 388 389 `mkAtom atom` 390 391 : Outputs the given string as an Elixir atom, instead of the default 392 Elixir binary string. Note: lowercase atoms still needs to be prefixed 393 with `:` 394 395 `mkTuple array` 396 397 : Outputs the given array as an Elixir tuple, instead of the default 398 Elixir list 399 400 `mkMap attrset` 401 402 : Outputs the given attribute set as an Elixir map, instead of the 403 default Elixir keyword list 404 405`pkgs.formats.lua { asBindings ? false, multiline ? true, columnWidth ? 100, indentWidth ? 2, indentUsingTabs ? false }` 406 407: A function taking an attribute set with values 408 409 `asBindings` (default `false`) 410 411 : Whether to treat attributes as variable bindings 412 413 `multiline` (default `true`) 414 415 : Whether to produce a multiline output. The output may still wrap across 416 multiple lines if it would otherwise exceed `columnWidth`. 417 418 `columnWidth` (default `100`) 419 420 : The column width to use to attempt to wrap lines. 421 422 `indentWidth` (default `2`) 423 424 : The width of a single indentation level. 425 426 `indentUsingTabs` (default `false`) 427 428 : Whether the indentation should use tabs instead of spaces. 429 430`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php} 431 432: A function taking an attribute set with values 433 434 `finalVariable` 435 436 : The variable that will store generated expression (usually `config`). If set to `null`, generated expression will contain `return`. 437 438 It returns a set with PHP-Config-specific attributes `type`, `lib`, and 439 `generate` as specified [below](#pkgs-formats-result). 440 441 The `lib` attribute contains functions to be used in settings, for 442 generating special PHP values: 443 444 `mkRaw phpCode` 445 446 : Outputs the given string as raw PHP code 447 448 `mkMixedArray list set` 449 450 : 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']` 451 452[]{#pkgs-formats-result} 453These functions all return an attribute set with these values: 454 455`type` 456 457: A module system type representing a value of the format 458 459`lib` 460 461: Utility functions for convenience, or special interactions with the format. 462 This attribute is optional. It may contain inside a `types` attribute 463 containing types specific to this format. 464 465`generate` *`filename jsonValue`* 466 467: A function that can render a value of the format to a file. Returns 468 a file path. 469 470 ::: {.note} 471 This function puts the value contents in the Nix store. So this 472 should be avoided for secrets. 473 ::: 474 475::: {#ex-settings-nix-representable .example} 476### Module with conventional `settings` option 477 478The following shows a module for an example program that uses a JSON 479configuration file. It demonstrates how above values can be used, along 480with some other related best practices. See the comments for 481explanations. 482 483```nix 484{ options, config, lib, pkgs, ... }: 485let 486 cfg = config.services.foo; 487 # Define the settings format used for this program 488 settingsFormat = pkgs.formats.json {}; 489in { 490 491 options.services.foo = { 492 enable = lib.mkEnableOption "foo service"; 493 494 settings = lib.mkOption { 495 # Setting this type allows for correct merging behavior 496 type = settingsFormat.type; 497 default = {}; 498 description = '' 499 Configuration for foo, see 500 <link xlink:href="https://example.com/docs/foo"/> 501 for supported settings. 502 ''; 503 }; 504 }; 505 506 config = lib.mkIf cfg.enable { 507 # We can assign some default settings here to make the service work by just 508 # enabling it. We use `mkDefault` for values that can be changed without 509 # problems 510 services.foo.settings = { 511 # Fails at runtime without any value set 512 log_level = lib.mkDefault "WARN"; 513 514 # We assume systemd's `StateDirectory` is used, so we require this value, 515 # therefore no mkDefault 516 data_path = "/var/lib/foo"; 517 518 # Since we use this to create a user we need to know the default value at 519 # eval time 520 user = lib.mkDefault "foo"; 521 }; 522 523 environment.etc."foo.json".source = 524 # The formats generator function takes a filename and the Nix value 525 # representing the format value and produces a filepath with that value 526 # rendered in the format 527 settingsFormat.generate "foo-config.json" cfg.settings; 528 529 # We know that the `user` attribute exists because we set a default value 530 # for it above, allowing us to use it without worries here 531 users.users.${cfg.settings.user} = { isSystemUser = true; }; 532 533 # ... 534 }; 535} 536``` 537::: 538 539### Option declarations for attributes {#sec-settings-attrs-options} 540 541Some `settings` attributes may deserve some extra care. They may need a 542different type, default or merging behavior, or they are essential 543options that should show their documentation in the manual. This can be 544done using [](#sec-freeform-modules). 545 546We extend above example using freeform modules to declare an option for 547the port, which will enforce it to be a valid integer and make it show 548up in the manual. 549 550::: {#ex-settings-typed-attrs .example} 551### Declaring a type-checked `settings` attribute 552```nix 553{ 554 settings = lib.mkOption { 555 type = lib.types.submodule { 556 557 freeformType = settingsFormat.type; 558 559 # Declare an option for the port such that the type is checked and this option 560 # is shown in the manual. 561 options.port = lib.mkOption { 562 type = lib.types.port; 563 default = 8080; 564 description = '' 565 Which port this service should listen on. 566 ''; 567 }; 568 569 }; 570 default = {}; 571 description = '' 572 Configuration for Foo, see 573 <link xlink:href="https://example.com/docs/foo"/> 574 for supported values. 575 ''; 576 }; 577} 578``` 579:::