187 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			6.8 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.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" />
 | ||
| </chapter>
 | 
