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