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