<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-declarations"> <title>Option Declarations</title> <para> An option declaration specifies the name, type and description of a NixOS configuration option. It is invalid to define an option that hasn’t been declared in any module. An option declaration generally looks like this: </para> <programlisting language="bash"> options = { name = mkOption { type = type specification; default = default value; example = example value; description = "Description for use in the NixOS manual."; }; }; </programlisting> <para> The attribute names within the <literal>name</literal> attribute path must be camel cased in general but should, as an exception, match the <link xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming"> package attribute name</link> when referencing a Nixpkgs package. For example, the option <literal>services.nix-serve.bindAddress</literal> references the <literal>nix-serve</literal> Nixpkgs package. </para> <para> The function <literal>mkOption</literal> accepts the following arguments. </para> <variablelist> <varlistentry> <term> <literal>type</literal> </term> <listitem> <para> The type of the option (see <xref linkend="sec-option-types" />). It may be omitted, but that’s not advisable since it may lead to errors that are hard to diagnose. </para> </listitem> </varlistentry> <varlistentry> <term> <literal>default</literal> </term> <listitem> <para> The default value used if no value is defined by any module. A default is not required; but if a default is not given, then users of the module will have to define the value of the option, otherwise an error will be thrown. </para> </listitem> </varlistentry> <varlistentry> <term> <literal>defaultText</literal> </term> <listitem> <para> A textual representation of the default value to be rendered verbatim in the manual. Useful if the default value is a complex expression or depends on other values or packages. Use <literal>lib.literalExpression</literal> for a Nix expression, <literal>lib.literalDocBook</literal> for a plain English description in DocBook format. </para> </listitem> </varlistentry> <varlistentry> <term> <literal>example</literal> </term> <listitem> <para> An example value that will be shown in the NixOS manual. You can use <literal>lib.literalExpression</literal> and <literal>lib.literalDocBook</literal> in the same way as in <literal>defaultText</literal>. </para> </listitem> </varlistentry> <varlistentry> <term> <literal>description</literal> </term> <listitem> <para> A textual description of the option, in DocBook format, that will be included in the NixOS manual. </para> </listitem> </varlistentry> </variablelist> <section xml:id="sec-option-declarations-eot"> <title>Extensible Option Types</title> <para> Extensible option types is a feature that allow to extend certain types declaration through multiple module files. This feature only work with a restricted set of types, namely <literal>enum</literal> and <literal>submodules</literal> and any composed forms of them. </para> <para> Extensible option types can be used for <literal>enum</literal> options that affects multiple modules, or as an alternative to related <literal>enable</literal> options. </para> <para> As an example, we will take the case of display managers. There is a central display manager module for generic display manager options and a module file per display manager backend (sddm, gdm ...). </para> <para> There are two approach to this module structure: </para> <itemizedlist> <listitem> <para> Managing the display managers independently by adding an enable option to every display manager module backend. (NixOS) </para> </listitem> <listitem> <para> Managing the display managers in the central module by adding an option to select which display manager backend to use. </para> </listitem> </itemizedlist> <para> Both approaches have problems. </para> <para> Making backends independent can quickly become hard to manage. For display managers, there can be only one enabled at a time, but the type system can not enforce this restriction as there is no relation between each backend <literal>enable</literal> option. As a result, this restriction has to be done explicitely by adding assertions in each display manager backend module. </para> <para> On the other hand, managing the display managers backends in the central module will require to change the central module option every time a new backend is added or removed. </para> <para> By using extensible option types, it is possible to create a placeholder option in the central module (<link linkend="ex-option-declaration-eot-service">Example: Extensible type placeholder in the service module</link>), and to extend it in each backend module (<link linkend="ex-option-declaration-eot-backend-gdm">Example: Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>gdm</literal> module</link>, <link linkend="ex-option-declaration-eot-backend-sddm">Example: Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>sddm</literal> module</link>). </para> <para> As a result, <literal>displayManager.enable</literal> option values can be added without changing the main service module file and the type system automatically enforce that there can only be a single display manager enabled. </para> <anchor xml:id="ex-option-declaration-eot-service" /> <para> <emphasis role="strong">Example: Extensible type placeholder in the service module</emphasis> </para> <programlisting language="bash"> services.xserver.displayManager.enable = mkOption { description = "Display manager to use"; type = with types; nullOr (enum [ ]); }; </programlisting> <anchor xml:id="ex-option-declaration-eot-backend-gdm" /> <para> <emphasis role="strong">Example: Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>gdm</literal> module</emphasis> </para> <programlisting language="bash"> services.xserver.displayManager.enable = mkOption { type = with types; nullOr (enum [ "gdm" ]); }; </programlisting> <anchor xml:id="ex-option-declaration-eot-backend-sddm" /> <para> <emphasis role="strong">Example: Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>sddm</literal> module</emphasis> </para> <programlisting language="bash"> services.xserver.displayManager.enable = mkOption { type = with types; nullOr (enum [ "sddm" ]); }; </programlisting> <para> The placeholder declaration is a standard <literal>mkOption</literal> declaration, but it is important that extensible option declarations only use the <literal>type</literal> argument. </para> <para> Extensible option types work with any of the composed variants of <literal>enum</literal> such as <literal>with types; nullOr (enum [ "foo" "bar" ])</literal> or <literal>with types; listOf (enum [ "foo" "bar" ])</literal>. </para> </section> </section>