1<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-modularity">
2 <title>Modularity</title>
3 <para>
4 The NixOS configuration mechanism is modular. If your
5 <literal>configuration.nix</literal> becomes too big, you can split
6 it into multiple files. Likewise, if you have multiple NixOS
7 configurations (e.g. for different computers) with some commonality,
8 you can move the common configuration into a shared file.
9 </para>
10 <para>
11 Modules have exactly the same syntax as
12 <literal>configuration.nix</literal>. In fact,
13 <literal>configuration.nix</literal> is itself a module. You can use
14 other modules by including them from
15 <literal>configuration.nix</literal>, e.g.:
16 </para>
17 <programlisting language="bash">
18{ config, pkgs, ... }:
19
20{ imports = [ ./vpn.nix ./kde.nix ];
21 services.httpd.enable = true;
22 environment.systemPackages = [ pkgs.emacs ];
23 ...
24}
25</programlisting>
26 <para>
27 Here, we include two modules from the same directory,
28 <literal>vpn.nix</literal> and <literal>kde.nix</literal>. The
29 latter might look like this:
30 </para>
31 <programlisting language="bash">
32{ config, pkgs, ... }:
33
34{ services.xserver.enable = true;
35 services.xserver.displayManager.sddm.enable = true;
36 services.xserver.desktopManager.plasma5.enable = true;
37 environment.systemPackages = [ pkgs.vim ];
38}
39</programlisting>
40 <para>
41 Note that both <literal>configuration.nix</literal> and
42 <literal>kde.nix</literal> define the option
43 <xref linkend="opt-environment.systemPackages" />. When multiple
44 modules define an option, NixOS will try to
45 <emphasis>merge</emphasis> the definitions. In the case of
46 <xref linkend="opt-environment.systemPackages" />, that’s easy: the
47 lists of packages can simply be concatenated. The value in
48 <literal>configuration.nix</literal> is merged last, so for
49 list-type options, it will appear at the end of the merged list. If
50 you want it to appear first, you can use
51 <literal>mkBefore</literal>:
52 </para>
53 <programlisting language="bash">
54boot.kernelModules = mkBefore [ "kvm-intel" ];
55</programlisting>
56 <para>
57 This causes the <literal>kvm-intel</literal> kernel module to be
58 loaded before any other kernel modules.
59 </para>
60 <para>
61 For other types of options, a merge may not be possible. For
62 instance, if two modules define
63 <xref linkend="opt-services.httpd.adminAddr" />,
64 <literal>nixos-rebuild</literal> will give an error:
65 </para>
66 <programlisting>
67The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
68</programlisting>
69 <para>
70 When that happens, it’s possible to force one definition take
71 precedence over the others:
72 </para>
73 <programlisting language="bash">
74services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
75</programlisting>
76 <para>
77 When using multiple modules, you may need to access configuration
78 values defined in other modules. This is what the
79 <literal>config</literal> function argument is for: it contains the
80 complete, merged system configuration. That is,
81 <literal>config</literal> is the result of combining the
82 configurations returned by every module <footnote>
83 <para>
84 If you’re wondering how it’s possible that the (indirect)
85 <emphasis>result</emphasis> of a function is passed as an
86 <emphasis>input</emphasis> to that same function: that’s because
87 Nix is a <quote>lazy</quote> language — it only computes values
88 when they are needed. This works as long as no individual
89 configuration value depends on itself.
90 </para>
91 </footnote> . For example, here is a module that adds some packages
92 to <xref linkend="opt-environment.systemPackages" /> only if
93 <xref linkend="opt-services.xserver.enable" /> is set to
94 <literal>true</literal> somewhere else:
95 </para>
96 <programlisting language="bash">
97{ config, pkgs, ... }:
98
99{ environment.systemPackages =
100 if config.services.xserver.enable then
101 [ pkgs.firefox
102 pkgs.thunderbird
103 ]
104 else
105 [ ];
106}
107</programlisting>
108 <para>
109 With multiple modules, it may not be obvious what the final value of
110 a configuration option is. The command
111 <literal>nixos-option</literal> allows you to find out:
112 </para>
113 <programlisting>
114$ nixos-option services.xserver.enable
115true
116
117$ nixos-option boot.kernelModules
118[ "tun" "ipv6" "loop" ... ]
119</programlisting>
120 <para>
121 Interactive exploration of the configuration is possible using
122 <literal>nix repl</literal>, a read-eval-print loop for Nix
123 expressions. A typical use:
124 </para>
125 <programlisting>
126$ nix repl '<nixpkgs/nixos>'
127
128nix-repl> config.networking.hostName
129"mandark"
130
131nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
132[ "example.org" "example.gov" ]
133</programlisting>
134 <para>
135 While abstracting your configuration, you may find it useful to
136 generate modules using code, instead of writing files. The example
137 below would have the same effect as importing a file which sets
138 those options.
139 </para>
140 <programlisting language="bash">
141{ config, pkgs, ... }:
142
143let netConfig = hostName: {
144 networking.hostName = hostName;
145 networking.useDHCP = false;
146};
147
148in
149
150{ imports = [ (netConfig "nixos.localdomain") ]; }
151</programlisting>
152</section>