175 lines
6.2 KiB
XML
175 lines
6.2 KiB
XML
|
<chapter 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-writing-modules">
|
|||
|
|
|||
|
<title>Writing NixOS Modules</title>
|
|||
|
|
|||
|
<para>NixOS has a modular system for declarative configuration. This
|
|||
|
system combines multiple <emphasis>modules</emphasis> to produce the
|
|||
|
full system configuration. One of the modules that constitute the
|
|||
|
configuration is <filename>/etc/nixos/configuration.nix</filename>.
|
|||
|
Most of the others live in the <link
|
|||
|
xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link>
|
|||
|
subdirectory of the Nixpkgs tree.</para>
|
|||
|
|
|||
|
<para>Each NixOS module is a file that handles one logical aspect of
|
|||
|
the configuration, such as a specific kind of hardware, a service, or
|
|||
|
network settings. A module configuration does not have to handle
|
|||
|
everything from scratch; it can use the functionality provided by
|
|||
|
other modules for its implementation. Thus a module can
|
|||
|
<emphasis>declare</emphasis> options that can be used by other
|
|||
|
modules, and conversely can <emphasis>define</emphasis> options
|
|||
|
provided by other modules in its own implementation. For example, the
|
|||
|
module <link
|
|||
|
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link>
|
|||
|
declares the option <option>security.pam.services</option> that allows
|
|||
|
other modules (e.g. <link
|
|||
|
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>)
|
|||
|
to define PAM services; and it defines the option
|
|||
|
<option>environment.etc</option> (declared by <link
|
|||
|
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>)
|
|||
|
to cause files to be created in
|
|||
|
<filename>/etc/pam.d</filename>.</para>
|
|||
|
|
|||
|
<para xml:id="para-module-syn">In <xref
|
|||
|
linkend="sec-configuration-syntax"/>, we saw the following structure
|
|||
|
of NixOS modules:
|
|||
|
|
|||
|
<programlisting>
|
|||
|
{ config, pkgs, ... }:
|
|||
|
|
|||
|
{ <replaceable>option definitions</replaceable>
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
|
|||
|
This is actually an <emphasis>abbreviated</emphasis> form of module
|
|||
|
that only defines options, but does not declare any. The structure of
|
|||
|
full NixOS modules is shown in <xref linkend='ex-module-syntax' />.</para>
|
|||
|
|
|||
|
<example xml:id='ex-module-syntax'><title>Structure of NixOS Modules</title>
|
|||
|
<programlisting>
|
|||
|
{ config, pkgs, ... }: <co xml:id='module-syntax-1' />
|
|||
|
|
|||
|
{
|
|||
|
imports =
|
|||
|
[ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' />
|
|||
|
];
|
|||
|
|
|||
|
options = {
|
|||
|
<replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' />
|
|||
|
};
|
|||
|
|
|||
|
config = {
|
|||
|
<replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' />
|
|||
|
};
|
|||
|
}</programlisting>
|
|||
|
</example>
|
|||
|
|
|||
|
<para>The meaning of each part is as follows.
|
|||
|
|
|||
|
<calloutlist>
|
|||
|
<callout arearefs='module-syntax-1'>
|
|||
|
<para>This line makes the current Nix expression a function. The
|
|||
|
variable <varname>pkgs</varname> contains Nixpkgs, while
|
|||
|
<varname>config</varname> contains the full system configuration.
|
|||
|
This line can be omitted if there is no reference to
|
|||
|
<varname>pkgs</varname> and <varname>config</varname> inside the
|
|||
|
module.</para>
|
|||
|
</callout>
|
|||
|
|
|||
|
<callout arearefs='module-syntax-2'>
|
|||
|
<para>This list enumerates the paths to other NixOS modules that
|
|||
|
should be included in the evaluation of the system configuration.
|
|||
|
A default set of modules is defined in the file
|
|||
|
<filename>modules/module-list.nix</filename>. These don't need to
|
|||
|
be added in the import list.</para>
|
|||
|
</callout>
|
|||
|
|
|||
|
<callout arearefs='module-syntax-3'>
|
|||
|
<para>The attribute <varname>options</varname> is a nested set of
|
|||
|
<emphasis>option declarations</emphasis> (described below).</para>
|
|||
|
</callout>
|
|||
|
|
|||
|
<callout arearefs='module-syntax-4'>
|
|||
|
<para>The attribute <varname>config</varname> is a nested set of
|
|||
|
<emphasis>option definitions</emphasis> (also described
|
|||
|
below).</para>
|
|||
|
</callout>
|
|||
|
</calloutlist>
|
|||
|
|
|||
|
</para>
|
|||
|
|
|||
|
<para><xref linkend='locate-example' /> shows a module that handles
|
|||
|
the regular update of the “locate” database, an index of all files in
|
|||
|
the file system. This module declares two options that can be defined
|
|||
|
by other modules (typically the user’s
|
|||
|
<filename>configuration.nix</filename>):
|
|||
|
<option>services.locate.enable</option> (whether the database should
|
|||
|
be updated) and <option>services.locate.period</option> (when the
|
|||
|
update should be done). It implements its functionality by defining
|
|||
|
two options declared by other modules:
|
|||
|
<option>systemd.services</option> (the set of all systemd services)
|
|||
|
and <option>services.cron.systemCronJobs</option> (the list of
|
|||
|
commands to be executed periodically by <command>cron</command>).</para>
|
|||
|
|
|||
|
<example xml:id='locate-example'><title>NixOS Module for the “locate” Service</title>
|
|||
|
<programlisting>
|
|||
|
{ config, lib, pkgs, ... }:
|
|||
|
|
|||
|
with lib;
|
|||
|
|
|||
|
let locatedb = "/var/cache/locatedb"; in
|
|||
|
|
|||
|
{
|
|||
|
options = {
|
|||
|
|
|||
|
services.locate = {
|
|||
|
|
|||
|
enable = mkOption {
|
|||
|
type = types.bool;
|
|||
|
default = false;
|
|||
|
description = ''
|
|||
|
If enabled, NixOS will periodically update the database of
|
|||
|
files used by the <command>locate</command> command.
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
period = mkOption {
|
|||
|
type = types.str;
|
|||
|
default = "15 02 * * *";
|
|||
|
description = ''
|
|||
|
This option defines (in the format used by cron) when the
|
|||
|
locate database is updated. The default is to update at
|
|||
|
02:15 at night every day.
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
config = {
|
|||
|
|
|||
|
systemd.services.update-locatedb =
|
|||
|
{ description = "Update Locate Database";
|
|||
|
path = [ pkgs.su ];
|
|||
|
script =
|
|||
|
''
|
|||
|
mkdir -m 0755 -p $(dirname ${locatedb})
|
|||
|
exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /media /run'
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
services.cron.systemCronJobs = optional config.services.locate.enable
|
|||
|
"${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service";
|
|||
|
|
|||
|
};
|
|||
|
}</programlisting>
|
|||
|
</example>
|
|||
|
|
|||
|
<xi:include href="option-declarations.xml" />
|
|||
|
<xi:include href="option-def.xml" />
|
|||
|
|
|||
|
</chapter>
|