Many programs have configuration files where program-specific settings can be declared. File formats can be separated into two categories:
<itemizedlist>
<listitem>
<para>
Nix-representable ones: These can trivially be mapped to a subset of Nix syntax. E.g. JSON is an example, since its values like <literal>{"foo":{"bar":10}}</literal> can be mapped directly to Nix: <literal>{ foo = { bar = 10; }; }</literal>. Other examples are INI, YAML and TOML. The following section explains the convention for these settings.
</para>
</listitem>
<listitem>
<para>
Non-nix-representable ones: These can't be trivially mapped to a subset of Nix syntax. Most generic programming languages are in this group, e.g. bash, since the statement <literal>if true; then echo hi; fi</literal> doesn't have a trivial representation in Nix.
</para>
<para>
Currently there are no fixed conventions for these, but it is common to have a <literal>configFile</literal> option for setting the configuration file path directly. The default value of <literal>configFile</literal> can be an auto-generated file, with convenient options for controlling the contents. For example an option of type <literal>attrsOf str</literal> can be used for representing environment variables which generates a section like <literal>export FOO="foo"</literal>. Often it can also be useful to also include an <literal>extraConfig</literal> option of type <literal>lines</literal> to allow arbitrary text after the autogenerated part of the file.
</para>
</listitem>
</itemizedlist>
</para>
<sectionxml:id="sec-settings-nix-representable">
<title>Nix-representable Formats (JSON, YAML, TOML, INI, ...)</title>
<para>
By convention, formats like this are handled with a generic <literal>settings</literal> option, representing the full program configuration as a Nix value. The type of this option should represent the format. The most common formats have a predefined type and string generator already declared under <literal>pkgs.formats</literal>:
<variablelist>
<varlistentry>
<term>
<varname>pkgs.formats.json</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with JSON-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <linklinkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>pkgs.formats.yaml</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with YAML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <linklinkend='pkgs-formats-result'>below</link>.
It returns a set with INI-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <linklinkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>pkgs.formats.toml</varname> { }
</term>
<listitem>
<para>
A function taking an empty attribute set (for future extensibility) and returning a set with TOML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <linklinkend='pkgs-formats-result'>below</link>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<paraxml:id="pkgs-formats-result">
These functions all return an attribute set with these values:
<variablelist>
<varlistentry>
<term>
<varname>type</varname>
</term>
<listitem>
<para>
A module system type representing a value of the format
A function that can render a value of the format to a file. Returns a file path.
<note>
<para>
This function puts the value contents in the Nix store. So this should be avoided for secrets.
</para>
</note>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<examplexml:id="ex-settings-nix-representable">
<title>Module with conventional <literal>settings</literal> option</title>
<para>
The following shows a module for an example program that uses a JSON configuration file. It demonstrates how above values can be used, along with some other related best practices. See the comments for explanations.
</para>
<programlisting>
{ options, config, lib, pkgs, ... }:
let
cfg = config.services.foo;
# Define the settings format used for this program
settingsFormat = pkgs.formats.json {};
in {
options.services.foo = {
enable = lib.mkEnableOption "foo service";
settings = lib.mkOption {
# Setting this type allows for correct merging behavior
Some <literal>settings</literal> attributes may deserve some extra care. They may need a different type, default or merging behavior, or they are essential options that should show their documentation in the manual. This can be done using <xreflinkend='sec-freeform-modules'/>.
<examplexml:id="ex-settings-typed-attrs">
<title>Declaring a type-checked <literal>settings</literal> attribute</title>
<para>
We extend above example using freeform modules to declare an option for the port, which will enforce it to be a valid integer and make it show up in the manual.
</para>
<programlisting>
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = settingsFormat.type;
# Declare an option for the port such that the type is checked and this option