2014-08-24 18:18:18 +01:00
|
|
|
|
<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">
|
2018-05-02 00:57:09 +01:00
|
|
|
|
<title>Modularity</title>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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.
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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.:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<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 ];
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<replaceable>...</replaceable>
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
Here, we include two modules from the same directory,
|
|
|
|
|
<filename>vpn.nix</filename> and <filename>kde.nix</filename>. The latter
|
|
|
|
|
might look like this:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<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;
|
2020-02-29 11:11:42 +00:00
|
|
|
|
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ];
|
2014-08-24 18:18:18 +01:00
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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>:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<programlisting>
|
2018-04-05 09:43:56 +01:00
|
|
|
|
<xref linkend="opt-boot.kernelModules"/> = mkBefore [ "kvm-intel" ];
|
2014-08-24 18:18:18 +01:00
|
|
|
|
</programlisting>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
This causes the <literal>kvm-intel</literal> kernel module to be loaded
|
|
|
|
|
before any other kernel modules.
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<screen>
|
|
|
|
|
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
|
|
|
|
|
</screen>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
When that happens, it’s possible to force one definition take precedence
|
|
|
|
|
over the others:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<programlisting>
|
2018-04-05 09:43:56 +01:00
|
|
|
|
<xref linkend="opt-services.httpd.adminAddr"/> = pkgs.lib.mkForce "bob@example.org";
|
2014-08-24 18:18:18 +01:00
|
|
|
|
</programlisting>
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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
|
2018-09-01 21:24:37 +01:00
|
|
|
|
<footnote xml:id="footnote-nix-is-lazy">
|
2018-05-02 00:57:09 +01:00
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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.
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
|
|
|
|
</footnote>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
. 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:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<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
|
2014-08-24 18:18:18 +01:00
|
|
|
|
[ pkgs.firefox
|
|
|
|
|
pkgs.thunderbird
|
|
|
|
|
]
|
|
|
|
|
else
|
|
|
|
|
[ ];
|
|
|
|
|
}
|
|
|
|
|
</programlisting>
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
|
2018-05-02 00:57:09 +01:00
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<screen>
|
2019-06-17 12:25:50 +01:00
|
|
|
|
<prompt>$ </prompt>nixos-option <xref linkend="opt-services.xserver.enable"/>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
true
|
|
|
|
|
|
2019-06-17 12:25:50 +01:00
|
|
|
|
<prompt>$ </prompt>nixos-option <xref linkend="opt-boot.kernelModules"/>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
|
|
|
|
|
</screen>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
Interactive exploration of the configuration is possible using <command>nix
|
|
|
|
|
repl</command>, a read-eval-print loop for Nix expressions. A typical use:
|
2014-08-24 18:18:18 +01:00
|
|
|
|
<screen>
|
2019-06-17 12:25:50 +01:00
|
|
|
|
<prompt>$ </prompt>nix repl '<nixpkgs/nixos>'
|
2014-08-24 18:18:18 +01:00
|
|
|
|
|
2019-06-17 12:25:50 +01:00
|
|
|
|
<prompt>nix-repl> </prompt>config.<xref linkend="opt-networking.hostName"/>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
"mandark"
|
|
|
|
|
|
2019-06-17 12:25:50 +01:00
|
|
|
|
<prompt>nix-repl> </prompt>map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
[ "example.org" "example.gov" ]
|
|
|
|
|
</screen>
|
2018-05-02 00:57:09 +01:00
|
|
|
|
</para>
|
2018-11-28 11:39:51 +00:00
|
|
|
|
|
|
|
|
|
<para>
|
2019-09-19 18:17:30 +01:00
|
|
|
|
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.
|
2019-06-17 11:01:51 +01:00
|
|
|
|
<programlisting>
|
|
|
|
|
{ config, pkgs, ... }:
|
2018-11-28 11:39:51 +00:00
|
|
|
|
|
2021-02-23 14:38:11 +00:00
|
|
|
|
let netConfig = hostName: {
|
2019-06-17 11:01:51 +01:00
|
|
|
|
networking.hostName = hostName;
|
|
|
|
|
networking.useDHCP = false;
|
|
|
|
|
};
|
2018-11-28 11:39:51 +00:00
|
|
|
|
|
2019-06-17 11:01:51 +01:00
|
|
|
|
in
|
2018-11-28 11:39:51 +00:00
|
|
|
|
|
2019-06-17 11:01:51 +01:00
|
|
|
|
{ imports = [ (netConfig "nixos.localdomain") ]; }
|
|
|
|
|
</programlisting>
|
2019-03-22 13:44:11 +00:00
|
|
|
|
</para>
|
2014-08-24 18:18:18 +01:00
|
|
|
|
</section>
|