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