vuls: init at 0.27.0
[NixPkgs.git] / nixos / doc / manual / development / freeform-modules.section.md
blob4f344dd804601238c57949895173749eb69538c0
1 # Freeform modules {#sec-freeform-modules}
3 Freeform modules allow you to define values for option paths that have
4 not been declared explicitly. This can be used to add attribute-specific
5 types to what would otherwise have to be `attrsOf` options in order to
6 accept all attribute names.
8 This feature can be enabled by using the attribute `freeformType` to
9 define a freeform type. By doing this, all assignments without an
10 associated option will be merged using the freeform type and combined
11 into the resulting `config` set. Since this feature nullifies name
12 checking for entire option trees, it is only recommended for use in
13 submodules.
15 ::: {#ex-freeform-module .example}
16 ### Freeform submodule
18 The following shows a submodule assigning a freeform type that allows
19 arbitrary attributes with `str` values below `settings`, but also
20 declares an option for the `settings.port` attribute to have it
21 type-checked and assign a default value. See
22 [Example: Declaring a type-checked `settings` attribute](#ex-settings-typed-attrs)
23 for a more complete example.
25 ```nix
26 { lib, config, ... }: {
28   options.settings = lib.mkOption {
29     type = lib.types.submodule {
31       freeformType = with lib.types; attrsOf str;
33       # We want this attribute to be checked for the correct type
34       options.port = lib.mkOption {
35         type = lib.types.port;
36         # Declaring the option also allows defining a default value
37         default = 8080;
38       };
40     };
41   };
43 ```
45 And the following shows what such a module then allows
47 ```nix
49   # Not a declared option, but the freeform type allows this
50   settings.logLevel = "debug";
52   # Not allowed because the the freeform type only allows strings
53   # settings.enable = true;
55   # Allowed because there is a port option declared
56   settings.port = 80;
58   # Not allowed because the port option doesn't allow strings
59   # settings.port = "443";
61 ```
62 :::
64 ::: {.note}
65 Freeform attributes cannot depend on other attributes of the same set
66 without infinite recursion:
68 ```nix
70   # This throws infinite recursion encountered
71   settings.logLevel = lib.mkIf (config.settings.port == 80) "debug";
73 ```
75 To prevent this, declare options for all attributes that need to depend
76 on others. For above example this means to declare `logLevel` to be an
77 option.
78 :::