forked from mirrors/nixpkgs
197 lines
7.3 KiB
XML
197 lines
7.3 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" 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 <literal>/etc/nixos/configuration.nix</literal>.
|
|||
|
Most of the others live in the
|
|||
|
<link xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><literal>nixos/modules</literal></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"><literal>pam.nix</literal></link>
|
|||
|
declares the option <literal>security.pam.services</literal> that
|
|||
|
allows other modules (e.g.
|
|||
|
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><literal>sshd.nix</literal></link>)
|
|||
|
to define PAM services; and it defines the option
|
|||
|
<literal>environment.etc</literal> (declared by
|
|||
|
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><literal>etc.nix</literal></link>)
|
|||
|
to cause files to be created in <literal>/etc/pam.d</literal>.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
In <xref linkend="sec-configuration-syntax" />, we saw the following
|
|||
|
structure of NixOS modules:
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
{ config, pkgs, ... }:
|
|||
|
|
|||
|
{ option definitions
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
<para>
|
|||
|
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
|
|||
|
<link linkend="ex-module-syntax">Example: Structure of NixOS
|
|||
|
Modules</link>.
|
|||
|
</para>
|
|||
|
<anchor xml:id="ex-module-syntax" />
|
|||
|
<para>
|
|||
|
<emphasis role="strong">Example: Structure of NixOS
|
|||
|
Modules</emphasis>
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
{ config, pkgs, ... }:
|
|||
|
|
|||
|
{
|
|||
|
imports =
|
|||
|
[ paths of other modules
|
|||
|
];
|
|||
|
|
|||
|
options = {
|
|||
|
option declarations
|
|||
|
};
|
|||
|
|
|||
|
config = {
|
|||
|
option definitions
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
<para>
|
|||
|
The meaning of each part is as follows.
|
|||
|
</para>
|
|||
|
<itemizedlist>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
The first line makes the current Nix expression a function. The
|
|||
|
variable <literal>pkgs</literal> contains Nixpkgs (by default,
|
|||
|
it takes the <literal>nixpkgs</literal> entry of
|
|||
|
<literal>NIX_PATH</literal>, see the
|
|||
|
<link xlink:href="https://nixos.org/manual/nix/stable/#sec-common-env">Nix
|
|||
|
manual</link> for further details), while
|
|||
|
<literal>config</literal> contains the full system
|
|||
|
configuration. This line can be omitted if there is no reference
|
|||
|
to <literal>pkgs</literal> and <literal>config</literal> inside
|
|||
|
the module.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
This <literal>imports</literal> 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 <literal>modules/module-list.nix</literal>. These don't
|
|||
|
need to be added in the import list.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
The attribute <literal>options</literal> is a nested set of
|
|||
|
<emphasis>option declarations</emphasis> (described below).
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
The attribute <literal>config</literal> is a nested set of
|
|||
|
<emphasis>option definitions</emphasis> (also described below).
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</itemizedlist>
|
|||
|
<para>
|
|||
|
<link linkend="locate-example">Example: NixOS Module for the
|
|||
|
<quote>locate</quote> Service</link> shows a module that handles the
|
|||
|
regular update of the <quote>locate</quote> 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
|
|||
|
<literal>configuration.nix</literal>):
|
|||
|
<literal>services.locate.enable</literal> (whether the database
|
|||
|
should be updated) and <literal>services.locate.interval</literal>
|
|||
|
(when the update should be done). It implements its functionality by
|
|||
|
defining two options declared by other modules:
|
|||
|
<literal>systemd.services</literal> (the set of all systemd
|
|||
|
services) and <literal>systemd.timers</literal> (the list of
|
|||
|
commands to be executed periodically by <literal>systemd</literal>).
|
|||
|
</para>
|
|||
|
<anchor xml:id="locate-example" />
|
|||
|
<para>
|
|||
|
<emphasis role="strong">Example: NixOS Module for the
|
|||
|
<quote>locate</quote> Service</emphasis>
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
{ config, lib, pkgs, ... }:
|
|||
|
|
|||
|
with lib;
|
|||
|
|
|||
|
let
|
|||
|
cfg = config.services.locate;
|
|||
|
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 locate command.
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
interval = mkOption {
|
|||
|
type = types.str;
|
|||
|
default = "02:15";
|
|||
|
example = "hourly";
|
|||
|
description = ''
|
|||
|
Update the locate database at this interval. Updates by
|
|||
|
default at 2:15 AM every day.
|
|||
|
|
|||
|
The format is described in
|
|||
|
systemd.time(7).
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
# Other options omitted for documentation
|
|||
|
};
|
|||
|
|
|||
|
config = {
|
|||
|
systemd.services.update-locatedb =
|
|||
|
{ description = "Update Locate Database";
|
|||
|
path = [ pkgs.su ];
|
|||
|
script =
|
|||
|
''
|
|||
|
mkdir -m 0755 -p $(dirname ${toString cfg.output})
|
|||
|
exec updatedb \
|
|||
|
--localuser=${cfg.localuser} \
|
|||
|
${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \
|
|||
|
--output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
|
|||
|
'';
|
|||
|
};
|
|||
|
|
|||
|
systemd.timers.update-locatedb = mkIf cfg.enable
|
|||
|
{ description = "Update timer for locate database";
|
|||
|
partOf = [ "update-locatedb.service" ];
|
|||
|
wantedBy = [ "timers.target" ];
|
|||
|
timerConfig.OnCalendar = cfg.interval;
|
|||
|
};
|
|||
|
};
|
|||
|
}
|
|||
|
</programlisting>
|
|||
|
<xi:include href="option-declarations.section.xml" />
|
|||
|
<xi:include href="option-types.section.xml" />
|
|||
|
<xi:include href="option-def.section.xml" />
|
|||
|
<xi:include href="assertions.section.xml" />
|
|||
|
<xi:include href="meta-attributes.section.xml" />
|
|||
|
<xi:include href="importing-modules.section.xml" />
|
|||
|
<xi:include href="replace-modules.section.xml" />
|
|||
|
<xi:include href="freeform-modules.section.xml" />
|
|||
|
<xi:include href="settings-options.section.xml" />
|
|||
|
</chapter>
|