at 16.09-beta 6.7 kB view raw
1<chapter xmlns="http://docbook.org/ns/docbook" 2 xmlns:xlink="http://www.w3.org/1999/xlink" 3 xmlns:xi="http://www.w3.org/2001/XInclude" 4 version="5.0" 5 xml:id="sec-writing-modules"> 6 7<title>Writing NixOS Modules</title> 8 9<para>NixOS has a modular system for declarative configuration. This 10system combines multiple <emphasis>modules</emphasis> to produce the 11full system configuration. One of the modules that constitute the 12configuration is <filename>/etc/nixos/configuration.nix</filename>. 13Most of the others live in the <link 14xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link> 15subdirectory of the Nixpkgs tree.</para> 16 17<para>Each NixOS module is a file that handles one logical aspect of 18the configuration, such as a specific kind of hardware, a service, or 19network settings. A module configuration does not have to handle 20everything from scratch; it can use the functionality provided by 21other modules for its implementation. Thus a module can 22<emphasis>declare</emphasis> options that can be used by other 23modules, and conversely can <emphasis>define</emphasis> options 24provided by other modules in its own implementation. For example, the 25module <link 26xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link> 27declares the option <option>security.pam.services</option> that allows 28other modules (e.g. <link 29xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>) 30to define PAM services; and it defines the option 31<option>environment.etc</option> (declared by <link 32xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>) 33to cause files to be created in 34<filename>/etc/pam.d</filename>.</para> 35 36<para xml:id="para-module-syn">In <xref 37linkend="sec-configuration-syntax"/>, we saw the following structure 38of NixOS modules: 39 40<programlisting> 41{ config, pkgs, ... }: 42 43{ <replaceable>option definitions</replaceable> 44} 45</programlisting> 46 47This is actually an <emphasis>abbreviated</emphasis> form of module 48that only defines options, but does not declare any. The structure of 49full NixOS modules is shown in <xref linkend='ex-module-syntax' />.</para> 50 51<example xml:id='ex-module-syntax'><title>Structure of NixOS Modules</title> 52<programlisting> 53{ config, pkgs, ... }: <co xml:id='module-syntax-1' /> 54 55{ 56 imports = 57 [ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' /> 58 ]; 59 60 options = { 61 <replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' /> 62 }; 63 64 config = { 65 <replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' /> 66 }; 67}</programlisting> 68</example> 69 70<para>The meaning of each part is as follows. 71 72<calloutlist> 73 <callout arearefs='module-syntax-1'> 74 <para>This line makes the current Nix expression a function. The 75 variable <varname>pkgs</varname> contains Nixpkgs, while 76 <varname>config</varname> contains the full system configuration. 77 This line can be omitted if there is no reference to 78 <varname>pkgs</varname> and <varname>config</varname> inside the 79 module.</para> 80 </callout> 81 82 <callout arearefs='module-syntax-2'> 83 <para>This list enumerates the paths to other NixOS modules that 84 should be included in the evaluation of the system configuration. 85 A default set of modules is defined in the file 86 <filename>modules/module-list.nix</filename>. These don't need to 87 be added in the import list.</para> 88 </callout> 89 90 <callout arearefs='module-syntax-3'> 91 <para>The attribute <varname>options</varname> is a nested set of 92 <emphasis>option declarations</emphasis> (described below).</para> 93 </callout> 94 95 <callout arearefs='module-syntax-4'> 96 <para>The attribute <varname>config</varname> is a nested set of 97 <emphasis>option definitions</emphasis> (also described 98 below).</para> 99 </callout> 100</calloutlist> 101 102</para> 103 104<para><xref linkend='locate-example' /> shows a module that handles 105the regular update of the “locate” database, an index of all files in 106the file system. This module declares two options that can be defined 107by other modules (typically the user’s 108<filename>configuration.nix</filename>): 109<option>services.locate.enable</option> (whether the database should 110be updated) and <option>services.locate.interval</option> (when the 111update should be done). It implements its functionality by defining 112two options declared by other modules: 113<option>systemd.services</option> (the set of all systemd services) 114and <option>systemd.timers</option> (the list of commands to be 115executed periodically by <command>systemd</command>).</para> 116 117<example xml:id='locate-example'><title>NixOS Module for the “locate” Service</title> 118<programlisting> 119{ config, lib, pkgs, ... }: 120 121with lib; 122 123let 124 cfg = config.services.locate; 125in { 126 options.services.locate = { 127 enable = mkOption { 128 type = types.bool; 129 default = false; 130 description = '' 131 If enabled, NixOS will periodically update the database of 132 files used by the <command>locate</command> command. 133 ''; 134 }; 135 136 interval = mkOption { 137 type = types.str; 138 default = "02:15"; 139 example = "hourly"; 140 description = '' 141 Update the locate database at this interval. Updates by 142 default at 2:15 AM every day. 143 144 The format is described in 145 <citerefentry><refentrytitle>systemd.time</refentrytitle> 146 <manvolnum>7</manvolnum></citerefentry>. 147 ''; 148 }; 149 150 # Other options omitted for documentation 151 }; 152 153 config = { 154 systemd.services.update-locatedb = 155 { description = "Update Locate Database"; 156 path = [ pkgs.su ]; 157 script = 158 '' 159 mkdir -m 0755 -p $(dirname ${toString cfg.output}) 160 exec updatedb \ 161 --localuser=${cfg.localuser} \ 162 ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \ 163 --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags} 164 ''; 165 }; 166 167 systemd.timers.update-locatedb = mkIf cfg.enable 168 { description = "Update timer for locate database"; 169 partOf = [ "update-locatedb.service" ]; 170 wantedBy = [ "timers.target" ]; 171 timerConfig.OnCalendar = cfg.interval; 172 }; 173 }; 174} 175</programlisting> 176</example> 177 178<xi:include href="option-declarations.xml" /> 179<xi:include href="option-def.xml" /> 180<xi:include href="meta-attributes.xml" /> 181 182</chapter>