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