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