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> |