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