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 = "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" />). It may be omitted, but
42 that’s not advisable since it may lead to errors that are hard
43 to diagnose.
44 </para>
45 </listitem>
46 </varlistentry>
47 <varlistentry>
48 <term>
49 <literal>default</literal>
50 </term>
51 <listitem>
52 <para>
53 The default value used if no value is defined by any module. A
54 default is not required; but if a default is not given, then
55 users of the module will have to define the value of the
56 option, otherwise an error will be thrown.
57 </para>
58 </listitem>
59 </varlistentry>
60 <varlistentry>
61 <term>
62 <literal>defaultText</literal>
63 </term>
64 <listitem>
65 <para>
66 A textual representation of the default value to be rendered
67 verbatim in the manual. Useful if the default value is a
68 complex expression or depends on other values or packages. Use
69 <literal>lib.literalExpression</literal> for a Nix expression,
70 <literal>lib.literalDocBook</literal> for a plain English
71 description in DocBook format.
72 </para>
73 </listitem>
74 </varlistentry>
75 <varlistentry>
76 <term>
77 <literal>example</literal>
78 </term>
79 <listitem>
80 <para>
81 An example value that will be shown in the NixOS manual. You
82 can use <literal>lib.literalExpression</literal> and
83 <literal>lib.literalDocBook</literal> in the same way as in
84 <literal>defaultText</literal>.
85 </para>
86 </listitem>
87 </varlistentry>
88 <varlistentry>
89 <term>
90 <literal>description</literal>
91 </term>
92 <listitem>
93 <para>
94 A textual description of the option, in DocBook format, that
95 will be included in the NixOS manual.
96 </para>
97 </listitem>
98 </varlistentry>
99 </variablelist>
100 <section xml:id="sec-option-declarations-eot">
101 <title>Extensible Option Types</title>
102 <para>
103 Extensible option types is a feature that allow to extend certain
104 types declaration through multiple module files. This feature only
105 work with a restricted set of types, namely
106 <literal>enum</literal> and <literal>submodules</literal> and any
107 composed forms of them.
108 </para>
109 <para>
110 Extensible option types can be used for <literal>enum</literal>
111 options that affects multiple modules, or as an alternative to
112 related <literal>enable</literal> options.
113 </para>
114 <para>
115 As an example, we will take the case of display managers. There is
116 a central display manager module for generic display manager
117 options and a module file per display manager backend (sddm, gdm
118 ...).
119 </para>
120 <para>
121 There are two approach to this module structure:
122 </para>
123 <itemizedlist>
124 <listitem>
125 <para>
126 Managing the display managers independently by adding an
127 enable option to every display manager module backend. (NixOS)
128 </para>
129 </listitem>
130 <listitem>
131 <para>
132 Managing the display managers in the central module by adding
133 an option to select which display manager backend to use.
134 </para>
135 </listitem>
136 </itemizedlist>
137 <para>
138 Both approaches have problems.
139 </para>
140 <para>
141 Making backends independent can quickly become hard to manage. For
142 display managers, there can be only one enabled at a time, but the
143 type system can not enforce this restriction as there is no
144 relation between each backend <literal>enable</literal> option. As
145 a result, this restriction has to be done explicitely by adding
146 assertions in each display manager backend module.
147 </para>
148 <para>
149 On the other hand, managing the display managers backends in the
150 central module will require to change the central module option
151 every time a new backend is added or removed.
152 </para>
153 <para>
154 By using extensible option types, it is possible to create a
155 placeholder option in the central module
156 (<link linkend="ex-option-declaration-eot-service">Example:
157 Extensible type placeholder in the service module</link>), and to
158 extend it in each backend module
159 (<link linkend="ex-option-declaration-eot-backend-gdm">Example:
160 Extending
161 <literal>services.xserver.displayManager.enable</literal> in the
162 <literal>gdm</literal> module</link>,
163 <link linkend="ex-option-declaration-eot-backend-sddm">Example:
164 Extending
165 <literal>services.xserver.displayManager.enable</literal> in the
166 <literal>sddm</literal> module</link>).
167 </para>
168 <para>
169 As a result, <literal>displayManager.enable</literal> option
170 values can be added without changing the main service module file
171 and the type system automatically enforce that there can only be a
172 single display manager enabled.
173 </para>
174 <anchor xml:id="ex-option-declaration-eot-service" />
175 <para>
176 <emphasis role="strong">Example: Extensible type placeholder in
177 the service module</emphasis>
178 </para>
179 <programlisting language="bash">
180services.xserver.displayManager.enable = mkOption {
181 description = "Display manager to use";
182 type = with types; nullOr (enum [ ]);
183};
184</programlisting>
185 <anchor xml:id="ex-option-declaration-eot-backend-gdm" />
186 <para>
187 <emphasis role="strong">Example: Extending
188 <literal>services.xserver.displayManager.enable</literal> in the
189 <literal>gdm</literal> module</emphasis>
190 </para>
191 <programlisting language="bash">
192services.xserver.displayManager.enable = mkOption {
193 type = with types; nullOr (enum [ "gdm" ]);
194};
195</programlisting>
196 <anchor xml:id="ex-option-declaration-eot-backend-sddm" />
197 <para>
198 <emphasis role="strong">Example: Extending
199 <literal>services.xserver.displayManager.enable</literal> in the
200 <literal>sddm</literal> module</emphasis>
201 </para>
202 <programlisting language="bash">
203services.xserver.displayManager.enable = mkOption {
204 type = with types; nullOr (enum [ "sddm" ]);
205};
206</programlisting>
207 <para>
208 The placeholder declaration is a standard
209 <literal>mkOption</literal> declaration, but it is important that
210 extensible option declarations only use the
211 <literal>type</literal> argument.
212 </para>
213 <para>
214 Extensible option types work with any of the composed variants of
215 <literal>enum</literal> such as
216 <literal>with types; nullOr (enum [ "foo" "bar" ])</literal>
217 or
218 <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.
219 </para>
220 </section>
221</section>