3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/nixos/doc/manual/configuration/modularity.xml

143 lines
4.9 KiB
XML
Raw Normal View History

<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 ];
2018-04-05 09:43:56 +01:00
<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, ... }:
2018-04-05 09:43:56 +01:00
{ <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
2018-04-05 09:43:56 +01:00
<xref linkend="opt-environment.systemPackages"/>. When multiple modules
define an option, NixOS will try to <emphasis>merge</emphasis> the
definitions. In the case of
2018-04-05 09:43:56 +01:00
<xref linkend="opt-environment.systemPackages"/>, thats 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>
2018-04-05 09:43:56 +01:00
<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
2018-04-05 09:43:56 +01:00
<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, its possible to force one definition take
precedence over the others:
<programlisting>
2018-04-05 09:43:56 +01:00
<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><para>If youre
wondering how its possible that the (indirect)
<emphasis>result</emphasis> of a function is passed as an
<emphasis>input</emphasis> to that same function: thats 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
2018-04-05 09:43:56 +01:00
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, ... }:
2018-04-05 09:43:56 +01:00
{ <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>
2018-04-05 09:43:56 +01:00
$ nixos-option <xref linkend="opt-services.xserver.enable"/>
true
2018-04-05 09:43:56 +01:00
$ nixos-option <xref linkend="opt-boot.kernelModules"/>
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
</screen>
Interactive exploration of the configuration is possible using
<command
xlink:href="https://github.com/edolstra/nix-repl">nix-repl</command>,
a read-eval-print loop for Nix expressions. Its not installed by
default; run <literal>nix-env -i nix-repl</literal> to get it. A
typical use:
<screen>
2016-12-11 18:51:18 +00:00
$ nix-repl '&lt;nixpkgs/nixos>'
2018-04-05 09:43:56 +01:00
nix-repl> config.<xref linkend="opt-networking.hostName"/>
"mandark"
2018-04-05 09:43:56 +01:00
nix-repl> map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/>
[ "example.org" "example.gov" ]
</screen>
</para>
</section>