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.pythonVars` { } 362 363: A function taking an empty attribute set (for future extensibility) 364 and returning a set with python variable specific attributes `type`, `lib`, and 365 `generate` as specified [below](#pkgs-formats-result). 366 367 The `lib` attribute contains functions to be used in settings, for 368 generating special Python values: 369 370 `mkRaw pythonCode` 371 372 : Outputs the given string as raw Python code 373 374 `_imports` 375 376 `_imports` is a special value you can set to specify additional modules to be 377 imported on top of the file. 378 379 `Example usage:` 380 381 ```nix 382 let 383 format = pkgs.formats.pythonVars { }; 384 in { 385 _imports = [ "re" ]; 386 387 conditional = format.lib.mkRaw "1 if True else 2"; 388 function_result = format.lib.mkRaw "re.findall(r'\\bf[a-z]*', 'which foot or hand fell fastest')"; 389 } 390 ``` 391 392`pkgs.formats.cdn` { } 393 394: A function taking an empty attribute set (for future extensibility) 395 and returning a set with [CDN](https://github.com/dzikoysk/cdn)-specific 396 attributes `type` and `generate` as specified [below](#pkgs-formats-result). 397 398`pkgs.formats.elixirConf { elixir ? pkgs.elixir }` 399 400: A function taking an attribute set with values 401 402 `elixir` 403 404 : The Elixir package which will be used to format the generated output 405 406 It returns a set with Elixir-Config-specific attributes `type`, `lib`, and 407 `generate` as specified [below](#pkgs-formats-result). 408 409 The `lib` attribute contains functions to be used in settings, for 410 generating special Elixir values: 411 412 `mkRaw elixirCode` 413 414 : Outputs the given string as raw Elixir code 415 416 `mkGetEnv { envVariable, fallback ? null }` 417 418 : Makes the configuration fetch an environment variable at runtime 419 420 `mkAtom atom` 421 422 : Outputs the given string as an Elixir atom, instead of the default 423 Elixir binary string. Note: lowercase atoms still needs to be prefixed 424 with `:` 425 426 `mkTuple array` 427 428 : Outputs the given array as an Elixir tuple, instead of the default 429 Elixir list 430 431 `mkMap attrset` 432 433 : Outputs the given attribute set as an Elixir map, instead of the 434 default Elixir keyword list 435 436`pkgs.formats.lua { asBindings ? false, multiline ? true, columnWidth ? 100, indentWidth ? 2, indentUsingTabs ? false }` 437 438: A function taking an attribute set with values 439 440 `asBindings` (default `false`) 441 442 : Whether to treat attributes as variable bindings 443 444 `multiline` (default `true`) 445 446 : Whether to produce a multiline output. The output may still wrap across 447 multiple lines if it would otherwise exceed `columnWidth`. 448 449 `columnWidth` (default `100`) 450 451 : The column width to use to attempt to wrap lines. 452 453 `indentWidth` (default `2`) 454 455 : The width of a single indentation level. 456 457 `indentUsingTabs` (default `false`) 458 459 : Whether the indentation should use tabs instead of spaces. 460 461`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php} 462 463: A function taking an attribute set with values 464 465 `finalVariable` 466 467 : The variable that will store generated expression (usually `config`). If set to `null`, generated expression will contain `return`. 468 469 It returns a set with PHP-Config-specific attributes `type`, `lib`, and 470 `generate` as specified [below](#pkgs-formats-result). 471 472 The `lib` attribute contains functions to be used in settings, for 473 generating special PHP values: 474 475 `mkRaw phpCode` 476 477 : Outputs the given string as raw PHP code 478 479 `mkMixedArray list set` 480 481 : 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']` 482 483[]{#pkgs-formats-result} 484These functions all return an attribute set with these values: 485 486`type` 487 488: A module system type representing a value of the format 489 490`lib` 491 492: Utility functions for convenience, or special interactions with the format. 493 This attribute is optional. It may contain inside a `types` attribute 494 containing types specific to this format. 495 496`generate` *`filename jsonValue`* 497 498: A function that can render a value of the format to a file. Returns 499 a file path. 500 501 ::: {.note} 502 This function puts the value contents in the Nix store. So this 503 should be avoided for secrets. 504 ::: 505 506::: {#ex-settings-nix-representable .example} 507### Module with conventional `settings` option 508 509The following shows a module for an example program that uses a JSON 510configuration file. It demonstrates how above values can be used, along 511with some other related best practices. See the comments for 512explanations. 513 514```nix 515{ 516 options, 517 config, 518 lib, 519 pkgs, 520 ... 521}: 522let 523 cfg = config.services.foo; 524 # Define the settings format used for this program 525 settingsFormat = pkgs.formats.json { }; 526in 527{ 528 529 options.services.foo = { 530 enable = lib.mkEnableOption "foo service"; 531 532 settings = lib.mkOption { 533 # Setting this type allows for correct merging behavior 534 type = settingsFormat.type; 535 default = { }; 536 description = '' 537 Configuration for foo, see 538 <link xlink:href="https://example.com/docs/foo"/> 539 for supported settings. 540 ''; 541 }; 542 }; 543 544 config = lib.mkIf cfg.enable { 545 # We can assign some default settings here to make the service work by just 546 # enabling it. We use `mkDefault` for values that can be changed without 547 # problems 548 services.foo.settings = { 549 # Fails at runtime without any value set 550 log_level = lib.mkDefault "WARN"; 551 552 # We assume systemd's `StateDirectory` is used, so we require this value, 553 # therefore no mkDefault 554 data_path = "/var/lib/foo"; 555 556 # Since we use this to create a user we need to know the default value at 557 # eval time 558 user = lib.mkDefault "foo"; 559 }; 560 561 environment.etc."foo.json".source = 562 # The formats generator function takes a filename and the Nix value 563 # representing the format value and produces a filepath with that value 564 # rendered in the format 565 settingsFormat.generate "foo-config.json" cfg.settings; 566 567 # We know that the `user` attribute exists because we set a default value 568 # for it above, allowing us to use it without worries here 569 users.users.${cfg.settings.user} = { 570 isSystemUser = true; 571 }; 572 573 # ... 574 }; 575} 576``` 577::: 578 579### Option declarations for attributes {#sec-settings-attrs-options} 580 581Some `settings` attributes may deserve some extra care. They may need a 582different type, default or merging behavior, or they are essential 583options that should show their documentation in the manual. This can be 584done using [](#sec-freeform-modules). 585 586We extend above example using freeform modules to declare an option for 587the port, which will enforce it to be a valid integer and make it show 588up in the manual. 589 590::: {#ex-settings-typed-attrs .example} 591### Declaring a type-checked `settings` attribute 592```nix 593{ 594 settings = lib.mkOption { 595 type = lib.types.submodule { 596 597 freeformType = settingsFormat.type; 598 599 # Declare an option for the port such that the type is checked and this option 600 # is shown in the manual. 601 options.port = lib.mkOption { 602 type = lib.types.port; 603 default = 8080; 604 description = '' 605 Which port this service should listen on. 606 ''; 607 }; 608 609 }; 610 default = { }; 611 description = '' 612 Configuration for Foo, see 613 <link xlink:href="https://example.com/docs/foo"/> 614 for supported values. 615 ''; 616 }; 617} 618``` 619:::