3
0
Fork 0
forked from mirrors/nixpkgs

nixos: nixos/doc/manual/configuration/modularity.xml to CommonMark

This commit is contained in:
Bobby Rong 2021-07-01 21:14:17 +08:00
parent 07ca0e237e
commit 6122fb4123
4 changed files with 288 additions and 148 deletions

View file

@ -20,6 +20,5 @@ xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
</para>
<xi:include href="../from_md/configuration/config-file.section.xml" />
<xi:include href="../from_md/configuration/abstractions.section.xml" />
<xi:include href="modularity.xml" />
<xi:include href="summary.xml" />
<xi:include href="../from_md/configuration/modularity.section.xml" />
</chapter>

View file

@ -0,0 +1,133 @@
# Modularity {#sec-modularity}
The NixOS configuration mechanism is modular. If your
`configuration.nix` 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.
Modules have exactly the same syntax as `configuration.nix`. In fact,
`configuration.nix` is itself a module. You can use other modules by
including them from `configuration.nix`, e.g.:
```nix
{ config, pkgs, ... }:
{ imports = [ ./vpn.nix ./kde.nix ];
services.httpd.enable = true;
environment.systemPackages = [ pkgs.emacs ];
...
}
```
Here, we include two modules from the same directory, `vpn.nix` and
`kde.nix`. The latter might look like this:
```nix
{ config, pkgs, ... }:
{ services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
environment.systemPackages = [ pkgs.vim ];
}
```
Note that both `configuration.nix` and `kde.nix` define the option
[`environment.systemPackages`](options.html#opt-environment.systemPackages). When multiple modules define an
option, NixOS will try to *merge* the definitions. In the case of
[`environment.systemPackages`](options.html#opt-environment.systemPackages), that's easy: the lists of
packages can simply be concatenated. The value in `configuration.nix` 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 `mkBefore`:
```nix
boot.kernelModules = mkBefore [ "kvm-intel" ];
```
This causes the `kvm-intel` kernel module to be loaded before any other
kernel modules.
For other types of options, a merge may not be possible. For instance,
if two modules define [`services.httpd.adminAddr`](options.html#opt-services.httpd.adminAddr),
`nixos-rebuild` will give an error:
```plain
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
```
When that happens, it's possible to force one definition take precedence
over the others:
```nix
services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
```
When using multiple modules, you may need to access configuration values
defined in other modules. This is what the `config` function argument is
for: it contains the complete, merged system configuration. That is,
`config` is the result of combining the configurations returned by every
module [^1] . For example, here is a module that adds some packages to
[`environment.systemPackages`](options.html#opt-environment.systemPackages) only if
[`services.xserver.enable`](options.html#opt-services.xserver.enable) is set to `true` somewhere else:
```nix
{ config, pkgs, ... }:
{ environment.systemPackages =
if config.services.xserver.enable then
[ pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
```
With multiple modules, it may not be obvious what the final value of a
configuration option is. The command `nixos-option` allows you to find
out:
```ShellSession
$ nixos-option services.xserver.enable
true
$ nixos-option boot.kernelModules
[ "tun" "ipv6" "loop" ... ]
```
Interactive exploration of the configuration is possible using `nix
repl`, a read-eval-print loop for Nix expressions. A typical use:
```ShellSession
$ nix repl '<nixpkgs/nixos>'
nix-repl> config.networking.hostName
"mandark"
nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
[ "example.org" "example.gov" ]
```
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.
```nix
{ config, pkgs, ... }:
let netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{ imports = [ (netConfig "nixos.localdomain") ]; }
```
[^1]: If you're wondering how it's possible that the (indirect) *result*
of a function is passed as an *input* 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.

View file

@ -1,146 +0,0 @@
<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;
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ];
}
</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"/>,
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>
<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, its 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 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 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 '&lt;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>

View file

@ -0,0 +1,154 @@
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-modularity">
<title>Modularity</title>
<para>
The NixOS configuration mechanism is modular. If your
<literal>configuration.nix</literal> 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
<literal>configuration.nix</literal>. In fact,
<literal>configuration.nix</literal> is itself a module. You can use
other modules by including them from
<literal>configuration.nix</literal>, e.g.:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ imports = [ ./vpn.nix ./kde.nix ];
services.httpd.enable = true;
environment.systemPackages = [ pkgs.emacs ];
...
}
</programlisting>
<para>
Here, we include two modules from the same directory,
<literal>vpn.nix</literal> and <literal>kde.nix</literal>. The
latter might look like this:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
environment.systemPackages = [ pkgs.vim ];
}
</programlisting>
<para>
Note that both <literal>configuration.nix</literal> and
<literal>kde.nix</literal> define the option
<link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link>.
When multiple modules define an option, NixOS will try to
<emphasis>merge</emphasis> the definitions. In the case of
<link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link>,
thats easy: the lists of packages can simply be concatenated. The
value in <literal>configuration.nix</literal> 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
<literal>mkBefore</literal>:
</para>
<programlisting language="bash">
boot.kernelModules = mkBefore [ &quot;kvm-intel&quot; ];
</programlisting>
<para>
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
<link xlink:href="options.html#opt-services.httpd.adminAddr"><literal>services.httpd.adminAddr</literal></link>,
<literal>nixos-rebuild</literal> will give an error:
</para>
<programlisting>
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
</programlisting>
<para>
When that happens, its possible to force one definition take
precedence over the others:
</para>
<programlisting language="bash">
services.httpd.adminAddr = pkgs.lib.mkForce &quot;bob@example.org&quot;;
</programlisting>
<para>
When using multiple modules, you may need to access configuration
values defined in other modules. This is what the
<literal>config</literal> function argument is for: it contains the
complete, merged system configuration. That is,
<literal>config</literal> 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 <quote>lazy</quote> 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
<link xlink:href="options.html#opt-environment.systemPackages"><literal>environment.systemPackages</literal></link>
only if
<link xlink:href="options.html#opt-services.xserver.enable"><literal>services.xserver.enable</literal></link>
is set to <literal>true</literal> somewhere else:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ environment.systemPackages =
if config.services.xserver.enable then
[ pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
</programlisting>
<para>
With multiple modules, it may not be obvious what the final value of
a configuration option is. The command
<literal>nixos-option</literal> allows you to find out:
</para>
<programlisting>
$ nixos-option services.xserver.enable
true
$ nixos-option boot.kernelModules
[ &quot;tun&quot; &quot;ipv6&quot; &quot;loop&quot; ... ]
</programlisting>
<para>
Interactive exploration of the configuration is possible using
<literal>nix repl</literal>, a read-eval-print loop for Nix
expressions. A typical use:
</para>
<programlisting>
$ nix repl '&lt;nixpkgs/nixos&gt;'
nix-repl&gt; config.networking.hostName
&quot;mandark&quot;
nix-repl&gt; map (x: x.hostName) config.services.httpd.virtualHosts
[ &quot;example.org&quot; &quot;example.gov&quot; ]
</programlisting>
<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.
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
let netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{ imports = [ (netConfig &quot;nixos.localdomain&quot;) ]; }
</programlisting>
</section>