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