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:::