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