nixos: nixos/doc/manual/development/settings-options.xml to CommonMark
This commit is contained in:
parent
31be0b922d
commit
165d6bd20c
4 changed files with 479 additions and 228 deletions
192
nixos/doc/manual/development/settings-options.section.md
Normal file
192
nixos/doc/manual/development/settings-options.section.md
Normal file
|
@ -0,0 +1,192 @@
|
|||
# Options for Program Settings {#sec-settings-options}
|
||||
|
||||
Many programs have configuration files where program-specific settings
|
||||
can be declared. File formats can be separated into two categories:
|
||||
|
||||
- Nix-representable ones: These can trivially be mapped to a subset of
|
||||
Nix syntax. E.g. JSON is an example, since its values like
|
||||
`{"foo":{"bar":10}}` can be mapped directly to Nix:
|
||||
`{ foo = { bar = 10; }; }`. Other examples are INI, YAML and TOML.
|
||||
The following section explains the convention for these settings.
|
||||
|
||||
- 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 `if true; then echo hi; fi`
|
||||
doesn\'t have a trivial representation in Nix.
|
||||
|
||||
Currently there are no fixed conventions for these, but it is common
|
||||
to have a `configFile` option for setting the configuration file
|
||||
path directly. The default value of `configFile` can be an
|
||||
auto-generated file, with convenient options for controlling the
|
||||
contents. For example an option of type `attrsOf str` can be used
|
||||
for representing environment variables which generates a section
|
||||
like `export FOO="foo"`. Often it can also be useful to also include
|
||||
an `extraConfig` option of type `lines` to allow arbitrary text
|
||||
after the autogenerated part of the file.
|
||||
|
||||
## Nix-representable Formats (JSON, YAML, TOML, INI, \...) {#sec-settings-nix-representable}
|
||||
|
||||
By convention, formats like this are handled with a generic `settings`
|
||||
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
|
||||
`pkgs.formats`:
|
||||
|
||||
`pkgs.formats.json` { }
|
||||
|
||||
: A function taking an empty attribute set (for future extensibility)
|
||||
and returning a set with JSON-specific attributes `type` and
|
||||
`generate` as specified [below](#pkgs-formats-result).
|
||||
|
||||
`pkgs.formats.yaml` { }
|
||||
|
||||
: A function taking an empty attribute set (for future extensibility)
|
||||
and returning a set with YAML-specific attributes `type` and
|
||||
`generate` as specified [below](#pkgs-formats-result).
|
||||
|
||||
`pkgs.formats.ini` { *`listsAsDuplicateKeys`* ? false, *`listToValue`* ? null, \... }
|
||||
|
||||
: A function taking an attribute set with values
|
||||
|
||||
`listsAsDuplicateKeys`
|
||||
|
||||
: A boolean for controlling whether list values can be used to
|
||||
represent duplicate INI keys
|
||||
|
||||
`listToValue`
|
||||
|
||||
: A function for turning a list of values into a single value.
|
||||
|
||||
It returns a set with INI-specific attributes `type` and `generate`
|
||||
as specified [below](#pkgs-formats-result).
|
||||
|
||||
`pkgs.formats.toml` { }
|
||||
|
||||
: A function taking an empty attribute set (for future extensibility)
|
||||
and returning a set with TOML-specific attributes `type` and
|
||||
`generate` as specified [below](#pkgs-formats-result).
|
||||
|
||||
::: {#pkgs-formats-result}
|
||||
These functions all return an attribute set with these values:
|
||||
:::
|
||||
|
||||
`type`
|
||||
|
||||
: A module system type representing a value of the format
|
||||
|
||||
`generate` *`filename jsonValue`*
|
||||
|
||||
: A function that can render a value of the format to a file. Returns
|
||||
a file path.
|
||||
|
||||
::: {.note}
|
||||
This function puts the value contents in the Nix store. So this
|
||||
should be avoided for secrets.
|
||||
:::
|
||||
|
||||
::: {#ex-settings-nix-representable .example}
|
||||
::: {.title}
|
||||
**Example: Module with conventional `settings` option**
|
||||
:::
|
||||
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.
|
||||
|
||||
```nix
|
||||
{ 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
|
||||
type = settingsFormat.type;
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# We can assign some default settings here to make the service work by just
|
||||
# enabling it. We use `mkDefault` for values that can be changed without
|
||||
# problems
|
||||
services.foo.settings = {
|
||||
# Fails at runtime without any value set
|
||||
log_level = lib.mkDefault "WARN";
|
||||
|
||||
# We assume systemd's `StateDirectory` is used, so we require this value,
|
||||
# therefore no mkDefault
|
||||
data_path = "/var/lib/foo";
|
||||
|
||||
# Since we use this to create a user we need to know the default value at
|
||||
# eval time
|
||||
user = lib.mkDefault "foo";
|
||||
};
|
||||
|
||||
environment.etc."foo.json".source =
|
||||
# The formats generator function takes a filename and the Nix value
|
||||
# representing the format value and produces a filepath with that value
|
||||
# rendered in the format
|
||||
settingsFormat.generate "foo-config.json" cfg.settings;
|
||||
|
||||
# We know that the `user` attribute exists because we set a default value
|
||||
# for it above, allowing us to use it without worries here
|
||||
users.users.${cfg.settings.user} = { isSystemUser = true; };
|
||||
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
### Option declarations for attributes {#sec-settings-attrs-options}
|
||||
|
||||
Some `settings` 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 [](#sec-freeform-modules).
|
||||
|
||||
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.
|
||||
|
||||
::: {#ex-settings-typed-attrs .example}
|
||||
::: {.title}
|
||||
**Example: Declaring a type-checked `settings` attribute**
|
||||
:::
|
||||
```nix
|
||||
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
|
||||
# is shown in the manual.
|
||||
options.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Which port this service should listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for Foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
```
|
||||
:::
|
|
@ -1,226 +0,0 @@
|
|||
<section 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-settings-options">
|
||||
<title>Options for Program Settings</title>
|
||||
|
||||
<para>
|
||||
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>
|
||||
<section xml: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 <link linkend='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 <link linkend='pkgs-formats-result'>below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>pkgs.formats.ini</varname> { <replaceable>listsAsDuplicateKeys</replaceable> ? false, <replaceable>listToValue</replaceable> ? null, ... }
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an attribute set with values
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>listsAsDuplicateKeys</varname>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A boolean for controlling whether list values can be used to represent duplicate INI keys
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>listToValue</varname>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function for turning a list of values into a single value.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
It returns a set with INI-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='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 <link linkend='pkgs-formats-result'>below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
<para xml: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
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<varname>generate</varname> <replaceable>filename</replaceable> <replaceable>jsonValue</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
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>
|
||||
<example xml: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
|
||||
type = settingsFormat.type;
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# We can assign some default settings here to make the service work by just
|
||||
# enabling it. We use `mkDefault` for values that can be changed without
|
||||
# problems
|
||||
services.foo.settings = {
|
||||
# Fails at runtime without any value set
|
||||
log_level = lib.mkDefault "WARN";
|
||||
|
||||
# We assume systemd's `StateDirectory` is used, so we require this value,
|
||||
# therefore no mkDefault
|
||||
data_path = "/var/lib/foo";
|
||||
|
||||
# Since we use this to create a user we need to know the default value at
|
||||
# eval time
|
||||
user = lib.mkDefault "foo";
|
||||
};
|
||||
|
||||
environment.etc."foo.json".source =
|
||||
# The formats generator function takes a filename and the Nix value
|
||||
# representing the format value and produces a filepath with that value
|
||||
# rendered in the format
|
||||
settingsFormat.generate "foo-config.json" cfg.settings;
|
||||
|
||||
# We know that the `user` attribute exists because we set a default value
|
||||
# for it above, allowing us to use it without worries here
|
||||
users.users.${cfg.settings.user} = { isSystemUser = true; };
|
||||
|
||||
# ...
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
<section xml:id="sec-settings-attrs-options">
|
||||
<title>Option declarations for attributes</title>
|
||||
<para>
|
||||
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 <xref linkend='sec-freeform-modules'/>.
|
||||
<example xml: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
|
||||
# is shown in the manual.
|
||||
options.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Which port this service should listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for Foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</section>
|
|
@ -186,6 +186,6 @@ in {
|
|||
<xi:include href="../from_md/development/meta-attributes.section.xml" />
|
||||
<xi:include href="../from_md/development/importing-modules.section.xml" />
|
||||
<xi:include href="../from_md/development/replace-modules.section.xml" />
|
||||
<xi:include href="freeform-modules.xml" />
|
||||
<xi:include href="settings-options.xml" />
|
||||
<xi:include href="../from_md/development/freeform-modules.section.xml" />
|
||||
<xi:include href="../from_md/development/settings-options.section.xml" />
|
||||
</chapter>
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-settings-options">
|
||||
<title>Options for Program Settings</title>
|
||||
<para>
|
||||
Many programs have configuration files where program-specific
|
||||
settings can be declared. File formats can be separated into two
|
||||
categories:
|
||||
</para>
|
||||
<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>
|
||||
<section xml: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>:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>pkgs.formats.json</literal> { }
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an empty attribute set (for future
|
||||
extensibility) and returning a set with JSON-specific
|
||||
attributes <literal>type</literal> and
|
||||
<literal>generate</literal> as specified
|
||||
<link linkend="pkgs-formats-result">below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>pkgs.formats.yaml</literal> { }
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an empty attribute set (for future
|
||||
extensibility) and returning a set with YAML-specific
|
||||
attributes <literal>type</literal> and
|
||||
<literal>generate</literal> as specified
|
||||
<link linkend="pkgs-formats-result">below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>pkgs.formats.ini</literal> {
|
||||
<emphasis><literal>listsAsDuplicateKeys</literal></emphasis> ?
|
||||
false, <emphasis><literal>listToValue</literal></emphasis> ?
|
||||
null, ... }
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an attribute set with values
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>listsAsDuplicateKeys</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A boolean for controlling whether list values can be
|
||||
used to represent duplicate INI keys
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>listToValue</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function for turning a list of values into a single
|
||||
value.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
It returns a set with INI-specific attributes
|
||||
<literal>type</literal> and <literal>generate</literal> as
|
||||
specified <link linkend="pkgs-formats-result">below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>pkgs.formats.toml</literal> { }
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function taking an empty attribute set (for future
|
||||
extensibility) and returning a set with TOML-specific
|
||||
attributes <literal>type</literal> and
|
||||
<literal>generate</literal> as specified
|
||||
<link linkend="pkgs-formats-result">below</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para xml:id="pkgs-formats-result">
|
||||
These functions all return an attribute set with these values:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>type</literal>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A module system type representing a value of the format
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>generate</literal>
|
||||
<emphasis><literal>filename jsonValue</literal></emphasis>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
A function that can render a value of the format to a file.
|
||||
Returns a file path.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This function puts the value contents in the Nix store. So
|
||||
this should be avoided for secrets.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<anchor xml:id="ex-settings-nix-representable" />
|
||||
<para>
|
||||
<emphasis role="strong">Example: Module with conventional
|
||||
<literal>settings</literal> option</emphasis>
|
||||
</para>
|
||||
<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 language="bash">
|
||||
{ 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
|
||||
type = settingsFormat.type;
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# We can assign some default settings here to make the service work by just
|
||||
# enabling it. We use `mkDefault` for values that can be changed without
|
||||
# problems
|
||||
services.foo.settings = {
|
||||
# Fails at runtime without any value set
|
||||
log_level = lib.mkDefault "WARN";
|
||||
|
||||
# We assume systemd's `StateDirectory` is used, so we require this value,
|
||||
# therefore no mkDefault
|
||||
data_path = "/var/lib/foo";
|
||||
|
||||
# Since we use this to create a user we need to know the default value at
|
||||
# eval time
|
||||
user = lib.mkDefault "foo";
|
||||
};
|
||||
|
||||
environment.etc."foo.json".source =
|
||||
# The formats generator function takes a filename and the Nix value
|
||||
# representing the format value and produces a filepath with that value
|
||||
# rendered in the format
|
||||
settingsFormat.generate "foo-config.json" cfg.settings;
|
||||
|
||||
# We know that the `user` attribute exists because we set a default value
|
||||
# for it above, allowing us to use it without worries here
|
||||
users.users.${cfg.settings.user} = { isSystemUser = true; };
|
||||
|
||||
# ...
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
<section xml:id="sec-settings-attrs-options">
|
||||
<title>Option declarations for attributes</title>
|
||||
<para>
|
||||
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
|
||||
<xref linkend="sec-freeform-modules" />.
|
||||
</para>
|
||||
<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>
|
||||
<anchor xml:id="ex-settings-typed-attrs" />
|
||||
<para>
|
||||
<emphasis role="strong">Example: Declaring a type-checked
|
||||
<literal>settings</literal> attribute</emphasis>
|
||||
</para>
|
||||
<programlisting language="bash">
|
||||
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
|
||||
# is shown in the manual.
|
||||
options.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = ''
|
||||
Which port this service should listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
default = {};
|
||||
description = ''
|
||||
Configuration for Foo, see
|
||||
<link xlink:href="https://example.com/docs/foo"/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
Loading…
Reference in a new issue