mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-12 04:35:41 +03:00

nixos-render-docs supports inline anchors, but not ids for blocks. it seems wise to reserve blocks for special cases that don't have other syntax already, like admonitions.
421 lines
14 KiB
XML
421 lines
14 KiB
XML
<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.javaProperties</literal> {
|
||
<emphasis><literal>comment</literal></emphasis> ?
|
||
<literal>"Generated with Nix"</literal> }
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
A function taking an attribute set with values
|
||
</para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>comment</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
A string to put at the start of the file in a comment.
|
||
It can have multiple lines.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
<para>
|
||
It returns the <literal>type</literal>:
|
||
<literal>attrsOf str</literal> and a function
|
||
<literal>generate</literal> to build a Java
|
||
<literal>.properties</literal> file, taking care of the
|
||
correct escaping, etc.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<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>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>pkgs.formats.elixirConf { elixir ? pkgs.elixir }</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
A function taking an attribute set with values
|
||
</para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>elixir</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
The Elixir package which will be used to format the
|
||
generated output
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
<para>
|
||
It returns a set with Elixir-Config-specific attributes
|
||
<literal>type</literal>, <literal>lib</literal>, and
|
||
<literal>generate</literal> as specified
|
||
<link linkend="pkgs-formats-result">below</link>.
|
||
</para>
|
||
<para>
|
||
The <literal>lib</literal> attribute contains functions to
|
||
be used in settings, for generating special Elixir values:
|
||
</para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>mkRaw elixirCode</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Outputs the given string as raw Elixir code
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>mkGetEnv { envVariable, fallback ? null }</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Makes the configuration fetch an environment variable
|
||
at runtime
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>mkAtom atom</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Outputs the given string as an Elixir atom, instead of
|
||
the default Elixir binary string. Note: lowercase
|
||
atoms still needs to be prefixed with
|
||
<literal>:</literal>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>mkTuple array</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Outputs the given array as an Elixir tuple, instead of
|
||
the default Elixir list
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>
|
||
<literal>mkMap attrset</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Outputs the given attribute set as an Elixir map,
|
||
instead of the default Elixir keyword list
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
<para>
|
||
<anchor 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>lib</literal>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
Utility functions for convenience, or special interactions
|
||
with the format. This attribute is optional. It may contain
|
||
inside a <literal>types</literal> attribute containing types
|
||
specific to this 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="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; };
|
||
|
||
# ...
|
||
};
|
||
}
|
||
</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="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.
|
||
'';
|
||
};
|
||
</programlisting>
|
||
</section>
|
||
</section>
|
||
</section>
|