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```