1<section xmlns="http://docbook.org/ns/docbook"
2 xmlns:xlink="http://www.w3.org/1999/xlink"
3 xmlns:xi="http://www.w3.org/2001/XInclude"
4 version="5.0"
5 xml:id="sec-option-definitions">
6
7<title>Option Definitions</title>
8
9<para>Option definitions are generally straight-forward bindings of values to option names, like
10
11<programlisting>
12config = {
13 services.httpd.enable = true;
14};
15</programlisting>
16
17However, sometimes you need to wrap an option definition or set of
18option definitions in a <emphasis>property</emphasis> to achieve
19certain effects:</para>
20
21<simplesect><title>Delaying Conditionals</title>
22
23<para>If a set of option definitions is conditional on the value of
24another option, you may need to use <varname>mkIf</varname>.
25Consider, for instance:
26
27<programlisting>
28config = if config.services.httpd.enable then {
29 environment.systemPackages = [ <replaceable>...</replaceable> ];
30 <replaceable>...</replaceable>
31} else {};
32</programlisting>
33
34This definition will cause Nix to fail with an “infinite recursion”
35error. Why? Because the value of
36<option>config.services.httpd.enable</option> depends on the value
37being constructed here. After all, you could also write the clearly
38circular and contradictory:
39<programlisting>
40config = if config.services.httpd.enable then {
41 services.httpd.enable = false;
42} else {
43 services.httpd.enable = true;
44};
45</programlisting>
46
47The solution is to write:
48
49<programlisting>
50config = mkIf config.services.httpd.enable {
51 environment.systemPackages = [ <replaceable>...</replaceable> ];
52 <replaceable>...</replaceable>
53};
54</programlisting>
55
56The special function <varname>mkIf</varname> causes the evaluation of
57the conditional to be “pushed down” into the individual definitions,
58as if you had written:
59
60<programlisting>
61config = {
62 environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else [];
63 <replaceable>...</replaceable>
64};
65</programlisting>
66
67</para>
68
69</simplesect>
70
71<simplesect><title>Setting Priorities</title>
72
73<para>A module can override the definitions of an option in other
74modules by setting a <emphasis>priority</emphasis>. All option
75definitions that do not have the lowest priority value are discarded.
76By default, option definitions have priority 1000. You can specify an
77explicit priority by using <varname>mkOverride</varname>, e.g.
78
79<programlisting>
80services.openssh.enable = mkOverride 10 false;
81</programlisting>
82
83This definition causes all other definitions with priorities above 10
84to be discarded. The function <varname>mkForce</varname> is
85equal to <varname>mkOverride 50</varname>.</para>
86
87</simplesect>
88
89<simplesect><title>Merging Configurations</title>
90
91<para>In conjunction with <literal>mkIf</literal>, it is sometimes
92useful for a module to return multiple sets of option definitions, to
93be merged together as if they were declared in separate modules. This
94can be done using <varname>mkMerge</varname>:
95
96<programlisting>
97config = mkMerge
98 [ # Unconditional stuff.
99 { environment.systemPackages = [ <replaceable>...</replaceable> ];
100 }
101 # Conditional stuff.
102 (mkIf config.services.bla.enable {
103 environment.systemPackages = [ <replaceable>...</replaceable> ];
104 })
105 ];
106</programlisting>
107
108</para>
109
110</simplesect>
111
112</section>