diff options
Diffstat (limited to 'nixos/doc/manual/from_md/development/settings-options.section.xml')
-rw-r--r-- | nixos/doc/manual/from_md/development/settings-options.section.xml | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/nixos/doc/manual/from_md/development/settings-options.section.xml b/nixos/doc/manual/from_md/development/settings-options.section.xml new file mode 100644 index 00000000000..746011a2d07 --- /dev/null +++ b/nixos/doc/manual/from_md/development/settings-options.section.xml @@ -0,0 +1,389 @@ +<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> + <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 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="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> |