The manual mentions how "[config and pkgs] are explained later". Added a link to where they are explained, and a hint pointing to the NIX_PATH variable.
		
			
				
	
	
		
			192 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			7.1 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 (by default, it takes the
 | 
						||
     <varname>nixpkgs</varname> entry of <envar>NIX_PATH</envar>, see the <link
 | 
						||
     xlink:href="https://nixos.org/manual/nix/stable/#sec-common-env">Nix
 | 
						||
     manual</link> for further details), 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.interval</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>systemd.timers</option> (the list of commands
 | 
						||
  to be executed periodically by <command>systemd</command>).
 | 
						||
 </para>
 | 
						||
 <example xml:id='locate-example'>
 | 
						||
  <title>NixOS Module for the “locate” Service</title>
 | 
						||
<programlisting>
 | 
						||
{ 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 <command>locate</command> 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
 | 
						||
        <citerefentry><refentrytitle>systemd.time</refentrytitle>
 | 
						||
        <manvolnum>7</manvolnum></citerefentry>.
 | 
						||
      '';
 | 
						||
    };
 | 
						||
 | 
						||
    # 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>
 | 
						||
 </example>
 | 
						||
 <xi:include href="option-declarations.xml" />
 | 
						||
 <xi:include href="option-types.xml" />
 | 
						||
 <xi:include href="option-def.xml" />
 | 
						||
 <xi:include href="assertions.xml" />
 | 
						||
 <xi:include href="meta-attributes.xml" />
 | 
						||
 <xi:include href="importing-modules.xml" />
 | 
						||
 <xi:include href="replace-modules.xml" />
 | 
						||
 <xi:include href="freeform-modules.xml" />
 | 
						||
 <xi:include href="settings-options.xml" />
 | 
						||
</chapter>
 |