1# Option Definitions {#sec-option-definitions}
2
3Option definitions are generally straight-forward bindings of values to
4option names, like
5
6```nix
7{
8 config = {
9 services.httpd.enable = true;
10 };
11}
12```
13
14However, sometimes you need to wrap an option definition or set of
15option definitions in a *property* to achieve certain effects:
16
17## Delaying Conditionals {#sec-option-definitions-delaying-conditionals}
18
19If a set of option definitions is conditional on the value of another
20option, you may need to use `mkIf`. Consider, for instance:
21
22```nix
23{
24 config = if config.services.httpd.enable then {
25 environment.systemPackages = [ /* ... */ ];
26 # ...
27 } else {};
28}
29```
30
31This definition will cause Nix to fail with an "infinite recursion"
32error. Why? Because the value of `config.services.httpd.enable` depends
33on the value being constructed here. After all, you could also write the
34clearly circular and contradictory:
35
36```nix
37{
38 config = if config.services.httpd.enable then {
39 services.httpd.enable = false;
40 } else {
41 services.httpd.enable = true;
42 };
43}
44```
45
46The solution is to write:
47
48```nix
49{
50 config = mkIf config.services.httpd.enable {
51 environment.systemPackages = [ /* ... */ ];
52 # ...
53 };
54}
55```
56
57The special function `mkIf` causes the evaluation of the conditional to
58be "pushed down" into the individual definitions, as if you had written:
59
60```nix
61{
62 config = {
63 environment.systemPackages = if config.services.httpd.enable then [ /* ... */ ] else [];
64 # ...
65 };
66}
67```
68
69## Setting Priorities {#sec-option-definitions-setting-priorities}
70
71A module can override the definitions of an option in other modules by
72setting an *override priority*. All option definitions that do not have the lowest
73priority value are discarded. By default, option definitions have
74priority 100 and option defaults have priority 1500.
75You can specify an explicit priority by using `mkOverride`, e.g.
76
77```nix
78{
79 services.openssh.enable = mkOverride 10 false;
80}
81```
82
83This definition causes all other definitions with priorities above 10 to
84be discarded. The function `mkForce` is equal to `mkOverride 50`, and
85`mkDefault` is equal to `mkOverride 1000`.
86
87## Ordering Definitions {#sec-option-definitions-ordering}
88
89It is also possible to influence the order in which the definitions for an option are
90merged by setting an *order priority* with `mkOrder`. The default order priority is 1000.
91The functions `mkBefore` and `mkAfter` are equal to `mkOrder 500` and `mkOrder 1500`, respectively.
92As an example,
93
94```nix
95{
96 hardware.firmware = mkBefore [ myFirmware ];
97}
98```
99
100This definition ensures that `myFirmware` comes before other unordered
101definitions in the final list value of `hardware.firmware`.
102
103Note that this is different from [override priorities](#sec-option-definitions-setting-priorities):
104setting an order does not affect whether the definition is included or not.
105
106## Merging Configurations {#sec-option-definitions-merging}
107
108In conjunction with `mkIf`, it is sometimes useful for a module to
109return multiple sets of option definitions, to be merged together as if
110they were declared in separate modules. This can be done using
111`mkMerge`:
112
113```nix
114{
115 config = mkMerge
116 [ # Unconditional stuff.
117 { environment.systemPackages = [ /* ... */ ];
118 }
119 # Conditional stuff.
120 (mkIf config.services.bla.enable {
121 environment.systemPackages = [ /* ... */ ];
122 })
123 ];
124}
125```