This reverts commit ea6e8775bd69e4676c623a85c39f1da540d29ad1. The new format is not an improvement.
		
			
				
	
	
		
			146 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
<section xmlns="http://docbook.org/ns/docbook"
 | 
						||
         xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
						||
         xmlns:xi="http://www.w3.org/2001/XInclude"
 | 
						||
         version="5.0"
 | 
						||
         xml:id="sec-modularity">
 | 
						||
 <title>Modularity</title>
 | 
						||
 | 
						||
 <para>
 | 
						||
  The NixOS configuration mechanism is modular. If your
 | 
						||
  <filename>configuration.nix</filename> becomes too big, you can split it into
 | 
						||
  multiple files. Likewise, if you have multiple NixOS configurations (e.g. for
 | 
						||
  different computers) with some commonality, you can move the common
 | 
						||
  configuration into a shared file.
 | 
						||
 </para>
 | 
						||
 | 
						||
 <para>
 | 
						||
  Modules have exactly the same syntax as
 | 
						||
  <filename>configuration.nix</filename>. In fact,
 | 
						||
  <filename>configuration.nix</filename> is itself a module. You can use other
 | 
						||
  modules by including them from <filename>configuration.nix</filename>, e.g.:
 | 
						||
<programlisting>
 | 
						||
{ config, pkgs, ... }:
 | 
						||
 | 
						||
{ imports = [ ./vpn.nix ./kde.nix ];
 | 
						||
  <xref linkend="opt-services.httpd.enable"/> = true;
 | 
						||
  <xref linkend="opt-environment.systemPackages"/> = [ pkgs.emacs ];
 | 
						||
  <replaceable>...</replaceable>
 | 
						||
}
 | 
						||
</programlisting>
 | 
						||
  Here, we include two modules from the same directory,
 | 
						||
  <filename>vpn.nix</filename> and <filename>kde.nix</filename>. The latter
 | 
						||
  might look like this:
 | 
						||
<programlisting>
 | 
						||
{ config, pkgs, ... }:
 | 
						||
 | 
						||
{ <xref linkend="opt-services.xserver.enable"/> = true;
 | 
						||
  <xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true;
 | 
						||
  <xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true;
 | 
						||
}
 | 
						||
</programlisting>
 | 
						||
  Note that both <filename>configuration.nix</filename> and
 | 
						||
  <filename>kde.nix</filename> define the option
 | 
						||
  <xref linkend="opt-environment.systemPackages"/>. When multiple modules
 | 
						||
  define an option, NixOS will try to <emphasis>merge</emphasis> the
 | 
						||
  definitions. In the case of <xref linkend="opt-environment.systemPackages"/>,
 | 
						||
  that’s easy: the lists of packages can simply be concatenated. The value in
 | 
						||
  <filename>configuration.nix</filename> is merged last, so for list-type
 | 
						||
  options, it will appear at the end of the merged list. If you want it to
 | 
						||
  appear first, you can use <varname>mkBefore</varname>:
 | 
						||
<programlisting>
 | 
						||
<xref linkend="opt-boot.kernelModules"/> = mkBefore [ "kvm-intel" ];
 | 
						||
</programlisting>
 | 
						||
  This causes the <literal>kvm-intel</literal> kernel module to be loaded
 | 
						||
  before any other kernel modules.
 | 
						||
 </para>
 | 
						||
 | 
						||
 <para>
 | 
						||
  For other types of options, a merge may not be possible. For instance, if two
 | 
						||
  modules define <xref linkend="opt-services.httpd.adminAddr"/>,
 | 
						||
  <command>nixos-rebuild</command> will give an error:
 | 
						||
<screen>
 | 
						||
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
 | 
						||
</screen>
 | 
						||
  When that happens, it’s possible to force one definition take precedence
 | 
						||
  over the others:
 | 
						||
<programlisting>
 | 
						||
<xref linkend="opt-services.httpd.adminAddr"/> = pkgs.lib.mkForce "bob@example.org";
 | 
						||
</programlisting>
 | 
						||
 </para>
 | 
						||
 | 
						||
 <para>
 | 
						||
  When using multiple modules, you may need to access configuration values
 | 
						||
  defined in other modules. This is what the <varname>config</varname> function
 | 
						||
  argument is for: it contains the complete, merged system configuration. That
 | 
						||
  is, <varname>config</varname> is the result of combining the configurations
 | 
						||
  returned by every module
 | 
						||
  <footnote xml:id="footnote-nix-is-lazy">
 | 
						||
   <para>
 | 
						||
    If you’re wondering how it’s possible that the (indirect)
 | 
						||
    <emphasis>result</emphasis> of a function is passed as an
 | 
						||
    <emphasis>input</emphasis> to that same function: that’s because Nix is a
 | 
						||
    “lazy” language — it only computes values when they are needed. This
 | 
						||
    works as long as no individual configuration value depends on itself.
 | 
						||
   </para>
 | 
						||
  </footnote>
 | 
						||
  . For example, here is a module that adds some packages to
 | 
						||
  <xref linkend="opt-environment.systemPackages"/> only if
 | 
						||
  <xref linkend="opt-services.xserver.enable"/> is set to
 | 
						||
  <literal>true</literal> somewhere else:
 | 
						||
<programlisting>
 | 
						||
{ config, pkgs, ... }:
 | 
						||
 | 
						||
{ <xref linkend="opt-environment.systemPackages"/> =
 | 
						||
    if config.<xref linkend="opt-services.xserver.enable"/> then
 | 
						||
      [ pkgs.firefox
 | 
						||
        pkgs.thunderbird
 | 
						||
      ]
 | 
						||
    else
 | 
						||
      [ ];
 | 
						||
}
 | 
						||
</programlisting>
 | 
						||
 </para>
 | 
						||
 | 
						||
 <para>
 | 
						||
  With multiple modules, it may not be obvious what the final value of a
 | 
						||
  configuration option is. The command <option>nixos-option</option> allows you
 | 
						||
  to find out:
 | 
						||
<screen>
 | 
						||
<prompt>$ </prompt>nixos-option <xref linkend="opt-services.xserver.enable"/>
 | 
						||
true
 | 
						||
 | 
						||
<prompt>$ </prompt>nixos-option <xref linkend="opt-boot.kernelModules"/>
 | 
						||
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
 | 
						||
</screen>
 | 
						||
  Interactive exploration of the configuration is possible using <command>nix
 | 
						||
  repl</command>, a read-eval-print loop for Nix expressions. A typical use:
 | 
						||
<screen>
 | 
						||
<prompt>$ </prompt>nix repl '<nixpkgs/nixos>'
 | 
						||
 | 
						||
<prompt>nix-repl> </prompt>config.<xref linkend="opt-networking.hostName"/>
 | 
						||
"mandark"
 | 
						||
 | 
						||
<prompt>nix-repl> </prompt>map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/>
 | 
						||
[ "example.org" "example.gov" ]
 | 
						||
</screen>
 | 
						||
 </para>
 | 
						||
 | 
						||
 <para>
 | 
						||
  While abstracting your configuration, you may find it useful to generate
 | 
						||
  modules using code, instead of writing files. The example below would have
 | 
						||
  the same effect as importing a file which sets those options.
 | 
						||
<programlisting>
 | 
						||
{ config, pkgs, ... }:
 | 
						||
 | 
						||
let netConfig = { hostName }: {
 | 
						||
  networking.hostName = hostName;
 | 
						||
  networking.useDHCP = false;
 | 
						||
};
 | 
						||
 | 
						||
in
 | 
						||
 | 
						||
{ imports = [ (netConfig "nixos.localdomain") ]; }
 | 
						||
</programlisting>
 | 
						||
 </para>
 | 
						||
</section>
 |