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