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.