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```