1<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-declarations">
2 <title>Option Declarations</title>
3 <para>
4 An option declaration specifies the name, type and description of a
5 NixOS configuration option. It is invalid to define an option that
6 hasn’t been declared in any module. An option declaration generally
7 looks like this:
8 </para>
9 <programlisting language="bash">
10options = {
11 name = mkOption {
12 type = type specification;
13 default = default value;
14 example = example value;
15 description = lib.mdDoc "Description for use in the NixOS manual.";
16 };
17};
18</programlisting>
19 <para>
20 The attribute names within the <literal>name</literal> attribute
21 path must be camel cased in general but should, as an exception,
22 match the
23 <link xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
24 package attribute name</link> when referencing a Nixpkgs package.
25 For example, the option
26 <literal>services.nix-serve.bindAddress</literal> references the
27 <literal>nix-serve</literal> Nixpkgs package.
28 </para>
29 <para>
30 The function <literal>mkOption</literal> accepts the following
31 arguments.
32 </para>
33 <variablelist>
34 <varlistentry>
35 <term>
36 <literal>type</literal>
37 </term>
38 <listitem>
39 <para>
40 The type of the option (see
41 <xref linkend="sec-option-types" />). This argument is
42 mandatory for nixpkgs modules. Setting this is highly
43 recommended for the sake of documentation and type checking.
44 In case it is not set, a fallback type with unspecified
45 behavior is used.
46 </para>
47 </listitem>
48 </varlistentry>
49 <varlistentry>
50 <term>
51 <literal>default</literal>
52 </term>
53 <listitem>
54 <para>
55 The default value used if no value is defined by any module. A
56 default is not required; but if a default is not given, then
57 users of the module will have to define the value of the
58 option, otherwise an error will be thrown.
59 </para>
60 </listitem>
61 </varlistentry>
62 <varlistentry>
63 <term>
64 <literal>defaultText</literal>
65 </term>
66 <listitem>
67 <para>
68 A textual representation of the default value to be rendered
69 verbatim in the manual. Useful if the default value is a
70 complex expression or depends on other values or packages. Use
71 <literal>lib.literalExpression</literal> for a Nix expression,
72 <literal>lib.literalMD</literal> for a plain English
73 description in
74 <link xlink:href="https://nixos.org/nixpkgs/manual/#sec-contributing-markup">Nixpkgs-flavored
75 Markdown</link> format.
76 </para>
77 </listitem>
78 </varlistentry>
79 <varlistentry>
80 <term>
81 <literal>example</literal>
82 </term>
83 <listitem>
84 <para>
85 An example value that will be shown in the NixOS manual. You
86 can use <literal>lib.literalExpression</literal> and
87 <literal>lib.literalMD</literal> in the same way as in
88 <literal>defaultText</literal>.
89 </para>
90 </listitem>
91 </varlistentry>
92 <varlistentry>
93 <term>
94 <literal>description</literal>
95 </term>
96 <listitem>
97 <para>
98 A textual description of the option, in
99 <link xlink:href="https://nixos.org/nixpkgs/manual/#sec-contributing-markup">Nixpkgs-flavored
100 Markdown</link> format, that will be included in the NixOS
101 manual. During the migration process from DocBook it is
102 necessary to mark descriptions written in CommonMark with
103 <literal>lib.mdDoc</literal>. The description may still be
104 written in DocBook (without any marker), but this is
105 discouraged and will be deprecated in the future.
106 </para>
107 </listitem>
108 </varlistentry>
109 </variablelist>
110 <section xml:id="sec-option-declarations-util">
111 <title>Utility functions for common option patterns</title>
112 <section xml:id="sec-option-declarations-util-mkEnableOption">
113 <title><literal>mkEnableOption</literal></title>
114 <para>
115 Creates an Option attribute set for a boolean value option i.e
116 an option to be toggled on or off.
117 </para>
118 <para>
119 This function takes a single string argument, the name of the
120 thing to be toggled.
121 </para>
122 <para>
123 The option’s description is <quote>Whether to enable
124 <name>.</quote>.
125 </para>
126 <para>
127 For example:
128 </para>
129 <anchor xml:id="ex-options-declarations-util-mkEnableOption-magic" />
130 <programlisting language="bash">
131lib.mkEnableOption "magic"
132# is like
133lib.mkOption {
134 type = lib.types.bool;
135 default = false;
136 example = true;
137 description = lib.mdDoc "Whether to enable magic.";
138}
139</programlisting>
140 <section xml:id="sec-option-declarations-util-mkPackageOption">
141 <title><literal>mkPackageOption</literal></title>
142 <para>
143 Usage:
144 </para>
145 <programlisting language="bash">
146mkPackageOption pkgs "name" { default = [ "path" "in" "pkgs" ]; example = "literal example"; }
147</programlisting>
148 <para>
149 Creates an Option attribute set for an option that specifies
150 the package a module should use for some purpose.
151 </para>
152 <para>
153 <emphasis role="strong">Note</emphasis>: You shouldn’t
154 necessarily make package options for all of your modules. You
155 can always overwrite a specific package throughout nixpkgs by
156 using
157 <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#chap-overlays">nixpkgs
158 overlays</link>.
159 </para>
160 <para>
161 The default package is specified as a list of strings
162 representing its attribute path in nixpkgs. Because of this,
163 you need to pass nixpkgs itself as the first argument.
164 </para>
165 <para>
166 The second argument is the name of the option, used in the
167 description <quote>The <name> package to use.</quote>.
168 You can also pass an example value, either a literal string or
169 a package’s attribute path.
170 </para>
171 <para>
172 You can omit the default path if the name of the option is
173 also attribute path in nixpkgs.
174 </para>
175 <anchor xml:id="ex-options-declarations-util-mkPackageOption" />
176 <para>
177 Examples:
178 </para>
179 <anchor xml:id="ex-options-declarations-util-mkPackageOption-hello" />
180 <programlisting language="bash">
181lib.mkPackageOption pkgs "hello" { }
182# is like
183lib.mkOption {
184 type = lib.types.package;
185 default = pkgs.hello;
186 defaultText = lib.literalExpression "pkgs.hello";
187 description = lib.mdDoc "The hello package to use.";
188}
189</programlisting>
190 <anchor xml:id="ex-options-declarations-util-mkPackageOption-ghc" />
191 <programlisting language="bash">
192lib.mkPackageOption pkgs "GHC" {
193 default = [ "ghc" ];
194 example = "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
195}
196# is like
197lib.mkOption {
198 type = lib.types.package;
199 default = pkgs.ghc;
200 defaultText = lib.literalExpression "pkgs.ghc";
201 example = lib.literalExpression "pkgs.haskell.packages.ghc92.ghc.withPackages (hkgs: [ hkgs.primes ])";
202 description = lib.mdDoc "The GHC package to use.";
203}
204</programlisting>
205 <section xml:id="sec-option-declarations-eot">
206 <title>Extensible Option Types</title>
207 <para>
208 Extensible option types is a feature that allow to extend
209 certain types declaration through multiple module files.
210 This feature only work with a restricted set of types,
211 namely <literal>enum</literal> and
212 <literal>submodules</literal> and any composed forms of
213 them.
214 </para>
215 <para>
216 Extensible option types can be used for
217 <literal>enum</literal> options that affects multiple
218 modules, or as an alternative to related
219 <literal>enable</literal> options.
220 </para>
221 <para>
222 As an example, we will take the case of display managers.
223 There is a central display manager module for generic
224 display manager options and a module file per display
225 manager backend (sddm, gdm ...).
226 </para>
227 <para>
228 There are two approaches we could take with this module
229 structure:
230 </para>
231 <itemizedlist>
232 <listitem>
233 <para>
234 Configuring the display managers independently by adding
235 an enable option to every display manager module
236 backend. (NixOS)
237 </para>
238 </listitem>
239 <listitem>
240 <para>
241 Configuring the display managers in the central module
242 by adding an option to select which display manager
243 backend to use.
244 </para>
245 </listitem>
246 </itemizedlist>
247 <para>
248 Both approaches have problems.
249 </para>
250 <para>
251 Making backends independent can quickly become hard to
252 manage. For display managers, there can only be one enabled
253 at a time, but the type system cannot enforce this
254 restriction as there is no relation between each backend’s
255 <literal>enable</literal> option. As a result, this
256 restriction has to be done explicitly by adding assertions
257 in each display manager backend module.
258 </para>
259 <para>
260 On the other hand, managing the display manager backends in
261 the central module will require changing the central module
262 option every time a new backend is added or removed.
263 </para>
264 <para>
265 By using extensible option types, it is possible to create a
266 placeholder option in the central module
267 (<link linkend="ex-option-declaration-eot-service">Example:
268 Extensible type placeholder in the service module</link>),
269 and to extend it in each backend module
270 (<link linkend="ex-option-declaration-eot-backend-gdm">Example:
271 Extending
272 <literal>services.xserver.displayManager.enable</literal> in
273 the <literal>gdm</literal> module</link>,
274 <link linkend="ex-option-declaration-eot-backend-sddm">Example:
275 Extending
276 <literal>services.xserver.displayManager.enable</literal> in
277 the <literal>sddm</literal> module</link>).
278 </para>
279 <para>
280 As a result, <literal>displayManager.enable</literal> option
281 values can be added without changing the main service module
282 file and the type system automatically enforces that there
283 can only be a single display manager enabled.
284 </para>
285 <anchor xml:id="ex-option-declaration-eot-service" />
286 <para>
287 <emphasis role="strong">Example: Extensible type placeholder
288 in the service module</emphasis>
289 </para>
290 <programlisting language="bash">
291services.xserver.displayManager.enable = mkOption {
292 description = "Display manager to use";
293 type = with types; nullOr (enum [ ]);
294};
295</programlisting>
296 <anchor xml:id="ex-option-declaration-eot-backend-gdm" />
297 <para>
298 <emphasis role="strong">Example: Extending
299 <literal>services.xserver.displayManager.enable</literal> in
300 the <literal>gdm</literal> module</emphasis>
301 </para>
302 <programlisting language="bash">
303services.xserver.displayManager.enable = mkOption {
304 type = with types; nullOr (enum [ "gdm" ]);
305};
306</programlisting>
307 <anchor xml:id="ex-option-declaration-eot-backend-sddm" />
308 <para>
309 <emphasis role="strong">Example: Extending
310 <literal>services.xserver.displayManager.enable</literal> in
311 the <literal>sddm</literal> module</emphasis>
312 </para>
313 <programlisting language="bash">
314services.xserver.displayManager.enable = mkOption {
315 type = with types; nullOr (enum [ "sddm" ]);
316};
317</programlisting>
318 <para>
319 The placeholder declaration is a standard
320 <literal>mkOption</literal> declaration, but it is important
321 that extensible option declarations only use the
322 <literal>type</literal> argument.
323 </para>
324 <para>
325 Extensible option types work with any of the composed
326 variants of <literal>enum</literal> such as
327 <literal>with types; nullOr (enum [ "foo" "bar" ])</literal>
328 or
329 <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.
330 </para>
331 </section>
332 </section>
333 </section>
334 </section>
335</section>