diff options
Diffstat (limited to 'nixpkgs/nixos/doc/manual/development')
19 files changed, 2751 insertions, 0 deletions
diff --git a/nixpkgs/nixos/doc/manual/development/assertions.xml b/nixpkgs/nixos/doc/manual/development/assertions.xml new file mode 100644 index 000000000000..32f90cf2e7c4 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/assertions.xml @@ -0,0 +1,74 @@ +<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-assertions"> + <title>Warnings and Assertions</title> + + <para> + When configuration problems are detectable in a module, it is a good idea to + write an assertion or warning. Doing so provides clear feedback to the user + and prevents errors after the build. + </para> + + <para> + Although Nix has the <literal>abort</literal> and + <literal>builtins.trace</literal> + <link xlink:href="https://nixos.org/nix/manual/#ssec-builtins">functions</link> + to perform such tasks, they are not ideally suited for NixOS modules. Instead + of these functions, you can declare your warnings and assertions using the + NixOS module system. + </para> + + <section xml:id="sec-assertions-warnings"> + <title>Warnings</title> + + <para> + This is an example of using <literal>warnings</literal>. + </para> + +<programlisting> +<![CDATA[ +{ config, lib, ... }: +{ + config = lib.mkIf config.services.foo.enable { + warnings = + if config.services.foo.bar + then [ ''You have enabled the bar feature of the foo service. + This is known to cause some specific problems in certain situations. + '' ] + else []; + } +} +]]> +</programlisting> + </section> + + <section xml:id="sec-assertions-assertions"> + <title>Assertions</title> + + <para> + This example, extracted from the + <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-17.09/nixos/modules/services/logging/syslogd.nix"> + <literal>syslogd</literal> module </link> shows how to use + <literal>assertions</literal>. Since there can only be one active syslog + daemon at a time, an assertion is useful to prevent such a broken system + from being built. + </para> + +<programlisting> +<![CDATA[ +{ config, lib, ... }: +{ + config = lib.mkIf config.services.syslogd.enable { + assertions = + [ { assertion = !config.services.rsyslogd.enable; + message = "rsyslogd conflicts with syslogd"; + } + ]; + } +} +]]> +</programlisting> + </section> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/building-nixos.xml b/nixpkgs/nixos/doc/manual/development/building-nixos.xml new file mode 100644 index 000000000000..56a596baed00 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/building-nixos.xml @@ -0,0 +1,27 @@ +<chapter 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-building-cd"> + <title>Building Your Own NixOS CD</title> + <para> + Building a NixOS CD is as easy as configuring your own computer. The idea is + to use another module which will replace your + <filename>configuration.nix</filename> to configure the system that would be + installed on the CD. + </para> + <para> + Default CD/DVD configurations are available inside + <filename>nixos/modules/installer/cd-dvd</filename>. +<screen> +<prompt>$ </prompt>git clone https://github.com/NixOS/nixpkgs.git +<prompt>$ </prompt>cd nixpkgs/nixos +<prompt>$ </prompt>nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix default.nix</screen> + </para> + <para> + Before burning your CD/DVD, you can check the content of the image by + mounting anywhere like suggested by the following command: +<screen> +<prompt># </prompt>mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen> + </para> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/building-parts.xml b/nixpkgs/nixos/doc/manual/development/building-parts.xml new file mode 100644 index 000000000000..88369fb891b3 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/building-parts.xml @@ -0,0 +1,121 @@ +<chapter 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-building-parts"> + <title>Building Specific Parts of NixOS</title> + <para> + With the command <command>nix-build</command>, you can build specific parts + of your NixOS configuration. This is done as follows: +<screen> +<prompt>$ </prompt>cd <replaceable>/path/to/nixpkgs/nixos</replaceable> +<prompt>$ </prompt>nix-build -A config.<replaceable>option</replaceable></screen> + where <replaceable>option</replaceable> is a NixOS option with type + “derivation” (i.e. something that can be built). Attributes of interest + include: + <variablelist> + <varlistentry> + <term> + <varname>system.build.toplevel</varname> + </term> + <listitem> + <para> + The top-level option that builds the entire NixOS system. Everything else + in your configuration is indirectly pulled in by this option. This is + what <command>nixos-rebuild</command> builds and what + <filename>/run/current-system</filename> points to afterwards. + </para> + <para> + A shortcut to build this is: +<screen> +<prompt>$ </prompt>nix-build -A system</screen> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>system.build.manual.manualHTML</varname> + </term> + <listitem> + <para> + The NixOS manual. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>system.build.etc</varname> + </term> + <listitem> + <para> + A tree of symlinks that form the static parts of + <filename>/etc</filename>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>system.build.initialRamdisk</varname> + </term> + <term> + <varname>system.build.kernel</varname> + </term> + <listitem> + <para> + The initial ramdisk and kernel of the system. This allows a quick way to + test whether the kernel and the initial ramdisk boot correctly, by using + QEMU’s <option>-kernel</option> and <option>-initrd</option> options: +<screen> +<prompt>$ </prompt>nix-build -A config.system.build.initialRamdisk -o initrd +<prompt>$ </prompt>nix-build -A config.system.build.kernel -o kernel +<prompt>$ </prompt>qemu-system-x86_64 -kernel ./kernel/bzImage -initrd ./initrd/initrd -hda /dev/null +</screen> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>system.build.nixos-rebuild</varname> + </term> + <term> + <varname>system.build.nixos-install</varname> + </term> + <term> + <varname>system.build.nixos-generate-config</varname> + </term> + <listitem> + <para> + These build the corresponding NixOS commands. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>systemd.units.<replaceable>unit-name</replaceable>.unit</varname> + </term> + <listitem> + <para> + This builds the unit with the specified name. Note that since unit names + contain dots (e.g. <literal>httpd.service</literal>), you need to put + them between quotes, like this: +<screen> +<prompt>$ </prompt>nix-build -A 'config.systemd.units."httpd.service".unit' +</screen> + You can also test individual units, without rebuilding the whole system, + by putting them in <filename>/run/systemd/system</filename>: +<screen> +<prompt>$ </prompt>cp $(nix-build -A 'config.systemd.units."httpd.service".unit')/httpd.service \ + /run/systemd/system/tmp-httpd.service +<prompt># </prompt>systemctl daemon-reload +<prompt># </prompt>systemctl start tmp-httpd.service +</screen> + Note that the unit must not have the same name as any unit in + <filename>/etc/systemd/system</filename> since those take precedence over + <filename>/run/systemd/system</filename>. That’s why the unit is + installed as <filename>tmp-httpd.service</filename> here. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/development.xml b/nixpkgs/nixos/doc/manual/development/development.xml new file mode 100644 index 000000000000..43f511b3e96b --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/development.xml @@ -0,0 +1,20 @@ +<part 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="ch-development"> + <title>Development</title> + <partintro xml:id="ch-development-intro"> + <para> + This chapter describes how you can modify and extend NixOS. + </para> + </partintro> + <xi:include href="sources.xml" /> + <xi:include href="writing-modules.xml" /> + <xi:include href="building-parts.xml" /> + <xi:include href="writing-documentation.xml" /> + <xi:include href="building-nixos.xml" /> + <xi:include href="nixos-tests.xml" /> + <xi:include href="testing-installer.xml" /> + <xi:include href="releases.xml" /> +</part> diff --git a/nixpkgs/nixos/doc/manual/development/importing-modules.xml b/nixpkgs/nixos/doc/manual/development/importing-modules.xml new file mode 100644 index 000000000000..1c6a5671eda8 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/importing-modules.xml @@ -0,0 +1,56 @@ +<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-importing-modules"> + <title>Importing Modules</title> + + <para> + Sometimes NixOS modules need to be used in configuration but exist outside of + Nixpkgs. These modules can be imported: + </para> + +<programlisting> +{ config, lib, pkgs, ... }: + +{ + imports = + [ # Use a locally-available module definition in + # ./example-module/default.nix + ./example-module + ]; + + services.exampleModule.enable = true; +} +</programlisting> + + <para> + The environment variable <literal>NIXOS_EXTRA_MODULE_PATH</literal> is an + absolute path to a NixOS module that is included alongside the Nixpkgs NixOS + modules. Like any NixOS module, this module can import additional modules: + </para> + +<programlisting> +# ./module-list/default.nix +[ + ./example-module1 + ./example-module2 +] +</programlisting> + +<programlisting> +# ./extra-module/default.nix +{ imports = import ./module-list.nix; } +</programlisting> + +<programlisting> +# NIXOS_EXTRA_MODULE_PATH=/absolute/path/to/extra-module +{ config, lib, pkgs, ... }: + +{ + # No `imports` needed + + services.exampleModule1.enable = true; +} +</programlisting> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/meta-attributes.xml b/nixpkgs/nixos/doc/manual/development/meta-attributes.xml new file mode 100644 index 000000000000..3d019a4987e1 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/meta-attributes.xml @@ -0,0 +1,63 @@ +<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-meta-attributes"> + <title>Meta Attributes</title> + + <para> + Like Nix packages, NixOS modules can declare meta-attributes to provide extra + information. Module meta attributes are defined in the + <filename + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/misc/meta.nix">meta.nix</filename> + special module. + </para> + + <para> + <literal>meta</literal> is a top level attribute like + <literal>options</literal> and <literal>config</literal>. Available + meta-attributes are <literal>maintainers</literal> and + <literal>doc</literal>. + </para> + + <para> + Each of the meta-attributes must be defined at most once per module file. + </para> + +<programlisting> +{ config, lib, pkgs, ... }: +{ + options = { + ... + }; + + config = { + ... + }; + + meta = { + maintainers = with lib.maintainers; [ ericsagnes ]; <co + xml:id='modules-meta-1' /> + doc = ./default.xml; <co xml:id='modules-meta-2' /> + }; +} +</programlisting> + + <calloutlist> + <callout arearefs='modules-meta-1'> + <para> + <varname>maintainers</varname> contains a list of the module maintainers. + </para> + </callout> + <callout arearefs='modules-meta-2'> + <para> + <varname>doc</varname> points to a valid DocBook file containing the module + documentation. Its contents is automatically added to + <xref + linkend="ch-configuration"/>. Changes to a module documentation + have to be checked to not break building the NixOS manual: + </para> +<programlisting>$ nix-build nixos/release.nix -A manual</programlisting> + </callout> + </calloutlist> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/nixos-tests.xml b/nixpkgs/nixos/doc/manual/development/nixos-tests.xml new file mode 100644 index 000000000000..2695082e3867 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/nixos-tests.xml @@ -0,0 +1,19 @@ +<chapter 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-nixos-tests"> + <title>NixOS Tests</title> + <para> + When you add some feature to NixOS, you should write a test for it. NixOS + tests are kept in the directory + <filename +xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/tests">nixos/tests</filename>, + and are executed (using Nix) by a testing framework that automatically starts + one or more virtual machines containing the NixOS system(s) required for the + test. + </para> + <xi:include href="writing-nixos-tests.xml" /> + <xi:include href="running-nixos-tests.xml" /> + <xi:include href="running-nixos-tests-interactively.xml" /> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/option-declarations.xml b/nixpkgs/nixos/doc/manual/development/option-declarations.xml new file mode 100644 index 000000000000..eee81bf64263 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/option-declarations.xml @@ -0,0 +1,199 @@ +<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-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: +<programlisting> +options = { + <replaceable>name</replaceable> = mkOption { + type = <replaceable>type specification</replaceable>; + default = <replaceable>default value</replaceable>; + example = <replaceable>example value</replaceable>; + description = "<replaceable>Description for use in the NixOS manual.</replaceable>"; + }; +}; +</programlisting> + The attribute names within the <replaceable>name</replaceable> 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 <varname>services.nix-serve.bindAddress</varname> + references the <varname>nix-serve</varname> Nixpkgs package. + </para> + + <para> + The function <varname>mkOption</varname> accepts the following arguments. + <variablelist> + <varlistentry> + <term> + <varname>type</varname> + </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> + <varname>default</varname> + </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> + <varname>example</varname> + </term> + <listitem> + <para> + An example value that will be shown in the NixOS manual. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>description</varname> + </term> + <listitem> + <para> + A textual description of the option, in DocBook format, that will be + included in the NixOS manual. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <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 (slim, sddm, gdm ...). + </para> + + <para> + There are two approach to this module structure: + <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> + + <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 + (<xref linkend='ex-option-declaration-eot-service' + />), and to extend + it in each backend module + (<xref + linkend='ex-option-declaration-eot-backend-slim' />, + <xref + linkend='ex-option-declaration-eot-backend-sddm' />). + </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> + + <example xml:id='ex-option-declaration-eot-service'> + <title>Extensible type placeholder in the service module</title> +<screen> +services.xserver.displayManager.enable = mkOption { + description = "Display manager to use"; + type = with types; nullOr (enum [ ]); +};</screen> + </example> + + <example xml:id='ex-option-declaration-eot-backend-slim'> + <title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>slim</literal> module</title> +<screen> +services.xserver.displayManager.enable = mkOption { + type = with types; nullOr (enum [ "slim" ]); +};</screen> + </example> + + <example xml:id='ex-option-declaration-eot-backend-sddm'> + <title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>sddm</literal> module</title> +<screen> +services.xserver.displayManager.enable = mkOption { + type = with types; nullOr (enum [ "sddm" ]); +};</screen> + </example> + + <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> diff --git a/nixpkgs/nixos/doc/manual/development/option-def.xml b/nixpkgs/nixos/doc/manual/development/option-def.xml new file mode 100644 index 000000000000..50a705d0cb8e --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/option-def.xml @@ -0,0 +1,99 @@ +<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-option-definitions"> + <title>Option Definitions</title> + + <para> + Option definitions are generally straight-forward bindings of values to + option names, like +<programlisting> +config = { + services.httpd.enable = true; +}; +</programlisting> + However, sometimes you need to wrap an option definition or set of option + definitions in a <emphasis>property</emphasis> to achieve certain effects: + </para> + + <simplesect xml:id="sec-option-definitions-delaying-conditionals"> + <title>Delaying Conditionals</title> + <para> + If a set of option definitions is conditional on the value of another + option, you may need to use <varname>mkIf</varname>. Consider, for instance: +<programlisting> +config = if config.services.httpd.enable then { + environment.systemPackages = [ <replaceable>...</replaceable> ]; + <replaceable>...</replaceable> +} else {}; +</programlisting> + This definition will cause Nix to fail with an “infinite recursion” + error. Why? Because the value of + <option>config.services.httpd.enable</option> depends on the value being + constructed here. After all, you could also write the clearly circular and + contradictory: +<programlisting> +config = if config.services.httpd.enable then { + services.httpd.enable = false; +} else { + services.httpd.enable = true; +}; +</programlisting> + The solution is to write: +<programlisting> +config = mkIf config.services.httpd.enable { + environment.systemPackages = [ <replaceable>...</replaceable> ]; + <replaceable>...</replaceable> +}; +</programlisting> + The special function <varname>mkIf</varname> causes the evaluation of the + conditional to be “pushed down” into the individual definitions, as if + you had written: +<programlisting> +config = { + environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else []; + <replaceable>...</replaceable> +}; +</programlisting> + </para> + </simplesect> + + <simplesect xml:id="sec-option-definitions-setting-priorities"> + <title>Setting Priorities</title> + <para> + A module can override the definitions of an option in other modules by + setting a <emphasis>priority</emphasis>. All option definitions that do not + have the lowest priority value are discarded. By default, option definitions + have priority 1000. You can specify an explicit priority by using + <varname>mkOverride</varname>, e.g. +<programlisting> +services.openssh.enable = mkOverride 10 false; +</programlisting> + This definition causes all other definitions with priorities above 10 to be + discarded. The function <varname>mkForce</varname> is equal to + <varname>mkOverride 50</varname>. + </para> + </simplesect> + + <simplesect xml:id="sec-option-definitions-merging"> + <title>Merging Configurations</title> + <para> + In conjunction with <literal>mkIf</literal>, it is sometimes useful for a + module to return multiple sets of option definitions, to be merged together + as if they were declared in separate modules. This can be done using + <varname>mkMerge</varname>: +<programlisting> +config = mkMerge + [ # Unconditional stuff. + { environment.systemPackages = [ <replaceable>...</replaceable> ]; + } + # Conditional stuff. + (mkIf config.services.bla.enable { + environment.systemPackages = [ <replaceable>...</replaceable> ]; + }) + ]; +</programlisting> + </para> + </simplesect> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/option-types.xml b/nixpkgs/nixos/doc/manual/development/option-types.xml new file mode 100644 index 000000000000..069cc36573d8 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/option-types.xml @@ -0,0 +1,781 @@ +<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-option-types"> + <title>Options Types</title> + + <para> + Option types are a way to put constraints on the values a module option can + take. Types are also responsible of how values are merged in case of multiple + value definitions. + </para> + + <section xml:id="sec-option-types-basic"> + <title>Basic Types</title> + + <para> + Basic types are the simplest available types in the module system. Basic + types include multiple string types that mainly differ in how definition + merging is handled. + </para> + + <variablelist> + <varlistentry> + <term> + <varname>types.attrs</varname> + </term> + <listitem> + <para> + A free-form attribute set. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.bool</varname> + </term> + <listitem> + <para> + A boolean, its values can be <literal>true</literal> or + <literal>false</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.path</varname> + </term> + <listitem> + <para> + A filesystem path, defined as anything that when coerced to a string + starts with a slash. Even if derivations can be considered as path, the + more specific <literal>types.package</literal> should be preferred. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.package</varname> + </term> + <listitem> + <para> + A derivation or a store path. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Integer-related types: + </para> + + <variablelist> + <varlistentry> + <term> + <varname>types.int</varname> + </term> + <listitem> + <para> + A signed integer. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.ints.{s8, s16, s32}</varname> + </term> + <listitem> + <para> + Signed integers with a fixed length (8, 16 or 32 bits). They go from + <inlineequation><mathphrase>−2<superscript>n</superscript>/2</mathphrase> + </inlineequation> to <inlineequation> + <mathphrase>2<superscript>n</superscript>/2−1</mathphrase> + </inlineequation> respectively (e.g. <literal>−128</literal> to + <literal>127</literal> for 8 bits). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.ints.unsigned</varname> + </term> + <listitem> + <para> + An unsigned integer (that is >= 0). + </para> + </listitem> + </varlistentry> + <varlistentry xml:id='types.ints.ux'> + <term> + <varname>types.ints.{u8, u16, u32}</varname> + </term> + <listitem> + <para> + Unsigned integers with a fixed length (8, 16 or 32 bits). They go from + <inlineequation><mathphrase>0</mathphrase></inlineequation> to + <inlineequation> + <mathphrase>2<superscript>n</superscript>−1</mathphrase> + </inlineequation> respectively (e.g. <literal>0</literal> to + <literal>255</literal> for 8 bits). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.ints.positive</varname> + </term> + <listitem> + <para> + A positive integer (that is > 0). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.port</varname> + </term> + <listitem> + <para> + A port number. This type is an alias to + <link linkend='types.ints.ux'><varname>types.ints.u16</varname></link>. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + String-related types: + </para> + + <variablelist> + <varlistentry> + <term> + <varname>types.str</varname> + </term> + <listitem> + <para> + A string. Multiple definitions cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.lines</varname> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a new line + <literal>"\n"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.commas</varname> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a comma + <literal>","</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.envVar</varname> + </term> + <listitem> + <para> + A string. Multiple definitions are concatenated with a collon + <literal>":"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.strMatching</varname> + </term> + <listitem> + <para> + A string matching a specific regular expression. Multiple definitions + cannot be merged. The regular expression is processed using + <literal>builtins.match</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + + <section xml:id="sec-option-types-value"> + <title>Value Types</title> + + <para> + Value types are types that take a value parameter. + </para> + + <variablelist> + <varlistentry> + <term> + <varname>types.enum</varname> <replaceable>l</replaceable> + </term> + <listitem> + <para> + One element of the list <replaceable>l</replaceable>, e.g. + <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions + cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.separatedString</varname> <replaceable>sep</replaceable> + </term> + <listitem> + <para> + A string with a custom separator <replaceable>sep</replaceable>, e.g. + <literal>types.separatedString "|"</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.ints.between</varname> <replaceable>lowest</replaceable> <replaceable>highest</replaceable> + </term> + <listitem> + <para> + An integer between <replaceable>lowest</replaceable> and + <replaceable>highest</replaceable> (both inclusive). Useful for creating + types like <literal>types.port</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.submodule</varname> <replaceable>o</replaceable> + </term> + <listitem> + <para> + A set of sub options <replaceable>o</replaceable>. + <replaceable>o</replaceable> can be an attribute set or a function + returning an attribute set. Submodules are used in composed types to + create modular options. Submodule are detailed in + <xref + linkend='section-option-types-submodule' />. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + + <section xml:id="sec-option-types-composed"> + <title>Composed Types</title> + + <para> + Composed types are types that take a type as parameter. <literal>listOf + int</literal> and <literal>either int str</literal> are examples of composed + types. + </para> + + <variablelist> + <varlistentry> + <term> + <varname>types.listOf</varname> <replaceable>t</replaceable> + </term> + <listitem> + <para> + A list of <replaceable>t</replaceable> type, e.g. <literal>types.listOf + int</literal>. Multiple definitions are merged with list concatenation. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.attrsOf</varname> <replaceable>t</replaceable> + </term> + <listitem> + <para> + An attribute set of where all the values are of + <replaceable>t</replaceable> type. Multiple definitions result in the + joined attribute set. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.loaOf</varname> <replaceable>t</replaceable> + </term> + <listitem> + <para> + An attribute set or a list of <replaceable>t</replaceable> type. Multiple + definitions are merged according to the value. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.nullOr</varname> <replaceable>t</replaceable> + </term> + <listitem> + <para> + <literal>null</literal> or type <replaceable>t</replaceable>. Multiple + definitions are merged according to type <replaceable>t</replaceable>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.uniq</varname> <replaceable>t</replaceable> + </term> + <listitem> + <para> + Ensures that type <replaceable>t</replaceable> cannot be merged. It is + used to ensure option definitions are declared only once. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.either</varname> <replaceable>t1</replaceable> <replaceable>t2</replaceable> + </term> + <listitem> + <para> + Type <replaceable>t1</replaceable> or type <replaceable>t2</replaceable>, + e.g. <literal>with types; either int str</literal>. Multiple definitions + cannot be merged. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>types.coercedTo</varname> <replaceable>from</replaceable> <replaceable>f</replaceable> <replaceable>to</replaceable> + </term> + <listitem> + <para> + Type <replaceable>to</replaceable> or type + <replaceable>from</replaceable> which will be coerced to type + <replaceable>to</replaceable> using function <replaceable>f</replaceable> + which takes an argument of type <replaceable>from</replaceable> and + return a value of type <replaceable>to</replaceable>. Can be used to + preserve backwards compatibility of an option if its type was changed. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + + <section xml:id='section-option-types-submodule'> + <title>Submodule</title> + + <para> + <literal>submodule</literal> is a very powerful type that defines a set of + sub-options that are handled like a separate module. + </para> + + <para> + It takes a parameter <replaceable>o</replaceable>, that should be a set, or + a function returning a set with an <literal>options</literal> key defining + the sub-options. Submodule option definitions are type-checked accordingly + to the <literal>options</literal> declarations. Of course, you can nest + submodule option definitons for even higher modularity. + </para> + + <para> + The option set can be defined directly + (<xref linkend='ex-submodule-direct' />) or as reference + (<xref linkend='ex-submodule-reference' />). + </para> + + <example xml:id='ex-submodule-direct'> + <title>Directly defined submodule</title> +<screen> +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }; +};</screen> + </example> + + <example xml:id='ex-submodule-reference'> + <title>Submodule defined as a reference</title> +<screen> +let + modOptions = { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = int; + }; + }; + }; +in +options.mod = mkOption { + description = "submodule example"; + type = with types; submodule modOptions; +};</screen> + </example> + + <para> + The <literal>submodule</literal> type is especially interesting when used + with composed types like <literal>attrsOf</literal> or + <literal>listOf</literal>. When composed with <literal>listOf</literal> + (<xref linkend='ex-submodule-listof-declaration' />), + <literal>submodule</literal> allows multiple definitions of the submodule + option set (<xref linkend='ex-submodule-listof-definition' />). + </para> + + <example xml:id='ex-submodule-listof-declaration'> + <title>Declaration of a list of submodules</title> +<screen> +options.mod = mkOption { + description = "submodule example"; + type = with types; listOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +};</screen> + </example> + + <example xml:id='ex-submodule-listof-definition'> + <title>Definition of a list of submodules</title> +<screen> +config.mod = [ + { foo = 1; bar = "one"; } + { foo = 2; bar = "two"; } +];</screen> + </example> + + <para> + When composed with <literal>attrsOf</literal> + (<xref linkend='ex-submodule-attrsof-declaration' />), + <literal>submodule</literal> allows multiple named definitions of the + submodule option set (<xref linkend='ex-submodule-attrsof-definition' />). + </para> + + <example xml:id='ex-submodule-attrsof-declaration'> + <title>Declaration of attribute sets of submodules</title> +<screen> +options.mod = mkOption { + description = "submodule example"; + type = with types; attrsOf (submodule { + options = { + foo = mkOption { + type = int; + }; + bar = mkOption { + type = str; + }; + }; + }); +};</screen> + </example> + + <example xml:id='ex-submodule-attrsof-definition'> + <title>Declaration of attribute sets of submodules</title> +<screen> +config.mod.one = { foo = 1; bar = "one"; }; +config.mod.two = { foo = 2; bar = "two"; };</screen> + </example> + </section> + + <section xml:id="sec-option-types-extending"> + <title>Extending types</title> + + <para> + Types are mainly characterized by their <literal>check</literal> and + <literal>merge</literal> functions. + </para> + + <variablelist> + <varlistentry> + <term> + <varname>check</varname> + </term> + <listitem> + <para> + The function to type check the value. Takes a value as parameter and + return a boolean. It is possible to extend a type check with the + <literal>addCheck</literal> function + (<xref + linkend='ex-extending-type-check-1' />), or to fully + override the check function + (<xref linkend='ex-extending-type-check-2' />). + </para> + <example xml:id='ex-extending-type-check-1'> + <title>Adding a type check</title> +<screen> +byte = mkOption { + description = "An integer between 0 and 255."; + type = types.addCheck types.int (x: x >= 0 && x <= 255); +};</screen> + </example> + <example xml:id='ex-extending-type-check-2'> + <title>Overriding a type check</title> +<screen> +nixThings = mkOption { + description = "words that start with 'nix'"; + type = types.str // { + check = (x: lib.hasPrefix "nix" x) + }; +};</screen> + </example> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>merge</varname> + </term> + <listitem> + <para> + Function to merge the options values when multiple values are set. The + function takes two parameters, <literal>loc</literal> the option path as + a list of strings, and <literal>defs</literal> the list of defined values + as a list. It is possible to override a type merge function for custom + needs. + </para> + </listitem> + </varlistentry> + </variablelist> + </section> + + <section xml:id="sec-option-types-custom"> + <title>Custom Types</title> + + <para> + Custom types can be created with the <literal>mkOptionType</literal> + function. As type creation includes some more complex topics such as + submodule handling, it is recommended to get familiar with + <filename + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/types.nix">types.nix</filename> + code before creating a new type. + </para> + + <para> + The only required parameter is <literal>name</literal>. + </para> + + <variablelist> + <varlistentry> + <term> + <varname>name</varname> + </term> + <listitem> + <para> + A string representation of the type function name. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>definition</varname> + </term> + <listitem> + <para> + Description of the type used in documentation. Give information of the + type and any of its arguments. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>check</varname> + </term> + <listitem> + <para> + A function to type check the definition value. Takes the definition value + as a parameter and returns a boolean indicating the type check result, + <literal>true</literal> for success and <literal>false</literal> for + failure. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>merge</varname> + </term> + <listitem> + <para> + A function to merge multiple definitions values. Takes two parameters: + </para> + <variablelist> + <varlistentry> + <term> + <replaceable>loc</replaceable> + </term> + <listitem> + <para> + The option path as a list of strings, e.g. <literal>["boot" "loader + "grub" "enable"]</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <replaceable>defs</replaceable> + </term> + <listitem> + <para> + The list of sets of defined <literal>value</literal> and + <literal>file</literal> where the value was defined, e.g. <literal>[ { + file = "/foo.nix"; value = 1; } { file = "/bar.nix"; value = 2 } + ]</literal>. The <literal>merge</literal> function should return the + merged value or throw an error in case the values are impossible or + not meant to be merged. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>getSubOptions</varname> + </term> + <listitem> + <para> + For composed types that can take a submodule as type parameter, this + function generate sub-options documentation. It takes the current option + prefix as a list and return the set of sub-options. Usually defined in a + recursive manner by adding a term to the prefix, e.g. <literal>prefix: + elemType.getSubOptions (prefix ++ + [<replaceable>"prefix"</replaceable>])</literal> where + <replaceable>"prefix"</replaceable> is the newly added prefix. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>getSubModules</varname> + </term> + <listitem> + <para> + For composed types that can take a submodule as type parameter, this + function should return the type parameters submodules. If the type + parameter is called <literal>elemType</literal>, the function should just + recursively look into submodules by returning + <literal>elemType.getSubModules;</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>substSubModules</varname> + </term> + <listitem> + <para> + For composed types that can take a submodule as type parameter, this + function can be used to substitute the parameter of a submodule type. It + takes a module as parameter and return the type with the submodule + options substituted. It is usually defined as a type function call with a + recursive call to <literal>substSubModules</literal>, e.g for a type + <literal>composedType</literal> that take an <literal>elemtype</literal> + type parameter, this function should be defined as <literal>m: + composedType (elemType.substSubModules m)</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>typeMerge</varname> + </term> + <listitem> + <para> + A function to merge multiple type declarations. Takes the type to merge + <literal>functor</literal> as parameter. A <literal>null</literal> return + value means that type cannot be merged. + </para> + <variablelist> + <varlistentry> + <term> + <replaceable>f</replaceable> + </term> + <listitem> + <para> + The type to merge <literal>functor</literal>. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Note: There is a generic <literal>defaultTypeMerge</literal> that work + with most of value and composed types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>functor</varname> + </term> + <listitem> + <para> + An attribute set representing the type. It is used for type operations + and has the following keys: + </para> + <variablelist> + <varlistentry> + <term> + <varname>type</varname> + </term> + <listitem> + <para> + The type function. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>wrapped</varname> + </term> + <listitem> + <para> + Holds the type parameter for composed types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>payload</varname> + </term> + <listitem> + <para> + Holds the value parameter for value types. The types that have a + <literal>payload</literal> are the <literal>enum</literal>, + <literal>separatedString</literal> and <literal>submodule</literal> + types. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <varname>binOp</varname> + </term> + <listitem> + <para> + A binary operation that can merge the payloads of two same types. + Defined as a function that take two payloads as parameters and return + the payloads merged. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + </variablelist> + </section> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/releases.xml b/nixpkgs/nixos/doc/manual/development/releases.xml new file mode 100755 index 000000000000..3cb16d33cd48 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/releases.xml @@ -0,0 +1,269 @@ +<chapter 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="ch-releases"> + <title>Releases</title> + <section xml:id="release-process"> + <title>Release process</title> + + <para> + Going through an example of releasing NixOS 17.09: + </para> + + <section xml:id="one-month-before-the-beta"> + <title>One month before the beta</title> + + <itemizedlist spacing="compact"> + <listitem> + <para> + Send an email to the nix-devel mailinglist as a warning about upcoming + beta "feature freeze" in a month. + </para> + </listitem> + <listitem> + <para> + Discuss with Eelco Dolstra and the community (via IRC, ML) about what + will reach the deadline. Any issue or Pull Request targeting the release + should be included in the release milestone. + </para> + </listitem> + </itemizedlist> + </section> + + <section xml:id="at-beta-release-time"> + <title>At beta release time</title> + + <itemizedlist spacing="compact"> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixpkgs/issues/13559">Create + an issue for tracking Zero Hydra Failures progress. ZHF is an effort to + get build failures down to zero.</link> + </para> + </listitem> + <listitem> + <para> + <literal>git tag -a -s -m "Release 17.09-beta" 17.09-beta + && git push --tags</literal> + </para> + </listitem> + <listitem> + <para> + From the master branch run <literal>git checkout -B + release-17.09</literal>. + </para> + </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixos-org-configurations/pull/18"> + Make sure a channel is created at http://nixos.org/channels/. </link> + </para> + </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixpkgs/compare/bdf161ed8d21...6b63c4616790"> + Bump the <literal>system.defaultChannel</literal> attribute in + <literal>nixos/modules/misc/version.nix</literal> </link> + </para> + </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixpkgs/commit/d6b08acd1ccac0d9d502c4b635e00b04d3387f06"> + Update <literal>versionSuffix</literal> in + <literal>nixos/release.nix</literal></link>, use <literal>git log + --format=%an|wc -l</literal> to get the commit count + </para> + </listitem> + <listitem> + <para> + <literal>echo -n "18.03" > .version</literal> on master. + </para> + </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixpkgs/commit/b8a4095003e27659092892a4708bb3698231a842"> + Pick a new name for the unstable branch. </link> + </para> + </listitem> + <listitem> + <para> + Create a new release notes file for the upcoming release + 1, in this + case <literal>rl-1803.xml</literal>. + </para> + </listitem> + <listitem> + <para> + Create two Hydra jobsets: release-17.09 and release-17.09-small with + <literal>stableBranch</literal> set to false. + </para> + </listitem> + <listitem> + <para> + Remove attributes that we know we will not be able to support, + especially if there is a stable alternative. E.g. Check that our + Linux kernels' + <link xlink:href="https://www.kernel.org/category/releases.html"> + projected end-of-life</link> are after our release projected + end-of-life + </para> + </listitem> + <listitem> + <para> + Edit changelog at + <literal>nixos/doc/manual/release-notes/rl-1709.xml</literal> (double + check desktop versions are noted) + </para> + <itemizedlist spacing="compact"> + <listitem> + <para> + Get all new NixOS modules <literal>git diff + release-17.03..release-17.09 nixos/modules/module-list.nix|grep + ^+</literal> + </para> + </listitem> + <listitem> + <para> + Note systemd, kernel, glibc and Nix upgrades. + </para> + </listitem> + </itemizedlist> + </listitem> + </itemizedlist> + </section> + + <section xml:id="during-beta"> + <title>During Beta</title> + + <itemizedlist spacing="compact"> + <listitem> + <para> + Monitor the master branch for bugfixes and minor updates and cherry-pick + them to the release branch. + </para> + </listitem> + </itemizedlist> + </section> + + <section xml:id="before-the-final-release"> + <title>Before the final release</title> + + <itemizedlist spacing="compact"> + <listitem> + <para> + Re-check that the release notes are complete. + </para> + </listitem> + <listitem> + <para> + Release Nix (currently only Eelco Dolstra can do that). + <link xlink:href="https://github.com/NixOS/nixpkgs/commit/53710c752a85f00658882531bc90a23a3d1287e4"> + Make sure fallback is updated. </link> + </para> + </listitem> + <listitem> + <para> + <link xlink:href="https://github.com/NixOS/nixpkgs/commit/40fd9ae3ac8048758abdcfc7d28a78b5f22fe97e"> + Update README.md with new stable NixOS version information. </link> + </para> + </listitem> + <listitem> + <para> + Change <literal>stableBranch</literal> to true and wait for channel to + update. + </para> + </listitem> + </itemizedlist> + </section> + + <section xml:id="at-final-release-time"> + <title>At final release time</title> + + <itemizedlist spacing="compact"> + <listitem> + <para> + <literal>git tag -s -a -m "Release 15.09" 15.09</literal> + </para> + </listitem> + <listitem> + <para> + Update "Chapter 4. Upgrading NixOS" section of the manual to match + new stable release version. + </para> + </listitem> + <listitem> + <para> + Update http://nixos.org/nixos/download.html and + http://nixos.org/nixos/manual in + https://github.com/NixOS/nixos-org-configurations + </para> + </listitem> + <listitem> + <para> + Get number of commits for the release: <literal>git log + release-14.04..release-14.12 --format=%an|wc -l</literal> + </para> + </listitem> + <listitem> + <para> + Commits by contributor: <literal>git log release-14.04..release-14.12 + --format=%an|sort|uniq -c|sort -rn</literal> + </para> + </listitem> + <listitem> + <para> + Send an email to nix-dev to announce the release with above information. + Best to check how previous email was formulated to see what needs to be + included. + </para> + </listitem> + </itemizedlist> + </section> + </section> + <section xml:id="release-schedule"> + <title>Release schedule</title> + + <informaltable> + <tgroup cols="2"> + <colspec align="left" /> + <colspec align="left" /> + <thead> + <row> + <entry> + Date + </entry> + <entry> + Event + </entry> + </row> + </thead> + <tbody> + <row> + <entry> + 2016-07-25 + </entry> + <entry> + Send email to nix-dev about upcoming branch-off + </entry> + </row> + <row> + <entry> + 2016-09-01 + </entry> + <entry><literal>release-16.09</literal> branch and corresponding jobsets are created, + change freeze + </entry> + </row> + <row> + <entry> + 2016-09-30 + </entry> + <entry> + NixOS 16.09 released + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </section> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/replace-modules.xml b/nixpkgs/nixos/doc/manual/development/replace-modules.xml new file mode 100644 index 000000000000..7b103c36d907 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/replace-modules.xml @@ -0,0 +1,79 @@ +<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-replace-modules"> + <title>Replace Modules</title> + + <para> + Modules that are imported can also be disabled. The option declarations and + config implementation of a disabled module will be ignored, allowing another + to take it's place. This can be used to import a set of modules from another + channel while keeping the rest of the system on a stable release. + </para> + + <para> + <literal>disabledModules</literal> is a top level attribute like + <literal>imports</literal>, <literal>options</literal> and + <literal>config</literal>. It contains a list of modules that will be + disabled. This can either be the full path to the module or a string with the + filename relative to the modules path (eg. <nixpkgs/nixos/modules> for + nixos). + </para> + + <para> + This example will replace the existing postgresql module with the version + defined in the nixos-unstable channel while keeping the rest of the modules + and packages from the original nixos channel. This only overrides the module + definition, this won't use postgresql from nixos-unstable unless explicitly + configured to do so. + </para> + +<programlisting> +{ config, lib, pkgs, ... }: + +{ + disabledModules = [ "services/databases/postgresql.nix" ]; + + imports = + [ # Use postgresql service from nixos-unstable channel. + # sudo nix-channel --add http://nixos.org/channels/nixos-unstable nixos-unstable + <nixos-unstable/nixos/modules/services/databases/postgresql.nix> + ]; + + services.postgresql.enable = true; +} +</programlisting> + + <para> + This example shows how to define a custom module as a replacement for an + existing module. Importing this module will disable the original module + without having to know it's implementation details. + </para> + +<programlisting> +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.man; +in + +{ + disabledModules = [ "services/programs/man.nix" ]; + + options = { + programs.man.enable = mkOption { + type = types.bool; + default = true; + description = "Whether to enable manual pages."; + }; + }; + + config = mkIf cfg.enabled { + warnings = [ "disabled manpages for production deployments." ]; + }; +} +</programlisting> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml b/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml new file mode 100644 index 000000000000..e390d62fde2f --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml @@ -0,0 +1,44 @@ +<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-running-nixos-tests"> + <title>Running Tests interactively</title> + + <para> + The test itself can be run interactively. This is particularly useful when + developing or debugging a test: +<screen> +<prompt>$ </prompt>nix-build nixos/tests/login.nix -A driver +<prompt>$ </prompt>./result/bin/nixos-test-driver +starting VDE switch for network 1 +<prompt>></prompt> +</screen> + You can then take any Perl statement, e.g. +<screen> +<prompt>></prompt> startAll +<prompt>></prompt> testScript +<prompt>></prompt> $machine->succeed("touch /tmp/foo") +<prompt>></prompt> print($machine->succeed("pwd")) # Show stdout of command +</screen> + The function <command>testScript</command> executes the entire test script + and drops you back into the test driver command line upon its completion. + This allows you to inspect the state of the VMs after the test (e.g. to debug + the test script). + </para> + + <para> + To just start and experiment with the VMs, run: +<screen> +<prompt>$ </prompt>nix-build nixos/tests/login.nix -A driver +<prompt>$ </prompt>./result/bin/nixos-run-vms +</screen> + The script <command>nixos-run-vms</command> starts the virtual machines + defined by test. + </para> + + <para> + The machine state is kept across VM restarts in + <filename>/tmp/vm-state-</filename><varname>machinename</varname>. + </para> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/running-nixos-tests.xml b/nixpkgs/nixos/doc/manual/development/running-nixos-tests.xml new file mode 100644 index 000000000000..13ae1ed93699 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/running-nixos-tests.xml @@ -0,0 +1,36 @@ +<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-running-nixos-tests-interactively"> + <title>Running Tests</title> + + <para> + You can run tests using <command>nix-build</command>. For example, to run the + test + <filename +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename>, + you just do: +<screen> +<prompt>$ </prompt>nix-build '<nixpkgs/nixos/tests/login.nix>' +</screen> + or, if you don’t want to rely on <envar>NIX_PATH</envar>: +<screen> +<prompt>$ </prompt>cd /my/nixpkgs/nixos/tests +<prompt>$ </prompt>nix-build login.nix +… +running the VM test script +machine: QEMU running (pid 8841) +… +6 out of 6 tests succeeded +</screen> + After building/downloading all required dependencies, this will perform a + build that starts a QEMU/KVM virtual machine containing a NixOS system. The + virtual machine mounts the Nix store of the host; this makes VM creation very + fast, as no disk image needs to be created. Afterwards, you can view a + pretty-printed log of the test: +<screen> +<prompt>$ </prompt>firefox result/log.html +</screen> + </para> +</section> diff --git a/nixpkgs/nixos/doc/manual/development/sources.xml b/nixpkgs/nixos/doc/manual/development/sources.xml new file mode 100644 index 000000000000..3c30c782746d --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/sources.xml @@ -0,0 +1,86 @@ +<chapter 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-getting-sources"> + <title>Getting the Sources</title> + <para> + By default, NixOS’s <command>nixos-rebuild</command> command uses the NixOS + and Nixpkgs sources provided by the <literal>nixos</literal> channel (kept in + <filename>/nix/var/nix/profiles/per-user/root/channels/nixos</filename>). To + modify NixOS, however, you should check out the latest sources from Git. This + is as follows: +<screen> +<prompt>$ </prompt>git clone https://github.com/NixOS/nixpkgs +<prompt>$ </prompt>cd nixpkgs +<prompt>$ </prompt>git remote add channels https://github.com/NixOS/nixpkgs-channels +<prompt>$ </prompt>git remote update channels +</screen> + This will check out the latest Nixpkgs sources to + <filename>./nixpkgs</filename> the NixOS sources to + <filename>./nixpkgs/nixos</filename>. (The NixOS source tree lives in a + subdirectory of the Nixpkgs repository.) The remote + <literal>channels</literal> refers to a read-only repository that tracks the + Nixpkgs/NixOS channels (see <xref linkend="sec-upgrading"/> for more + information about channels). Thus, the Git branch + <literal>channels/nixos-17.03</literal> will contain the latest built and + tested version available in the <literal>nixos-17.03</literal> channel. + </para> + <para> + It’s often inconvenient to develop directly on the master branch, since if + somebody has just committed (say) a change to GCC, then the binary cache may + not have caught up yet and you’ll have to rebuild everything from source. + So you may want to create a local branch based on your current NixOS version: +<screen> +<prompt>$ </prompt>nixos-version +17.09pre104379.6e0b727 (Hummingbird) + +<prompt>$ </prompt>git checkout -b local 6e0b727 +</screen> + Or, to base your local branch on the latest version available in a NixOS + channel: +<screen> +<prompt>$ </prompt>git remote update channels +<prompt>$ </prompt>git checkout -b local channels/nixos-17.03 +</screen> + (Replace <literal>nixos-17.03</literal> with the name of the channel you want + to use.) You can use <command>git merge</command> or <command>git + rebase</command> to keep your local branch in sync with the channel, e.g. +<screen> +<prompt>$ </prompt>git remote update channels +<prompt>$ </prompt>git merge channels/nixos-17.03 +</screen> + You can use <command>git cherry-pick</command> to copy commits from your + local branch to the upstream branch. + </para> + <para> + If you want to rebuild your system using your (modified) sources, you need to + tell <command>nixos-rebuild</command> about them using the + <option>-I</option> flag: +<screen> +<prompt># </prompt>nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs +</screen> + </para> + <para> + If you want <command>nix-env</command> to use the expressions in + <replaceable>/my/sources</replaceable>, use <command>nix-env -f + <replaceable>/my/sources</replaceable>/nixpkgs</command>, or change the + default by adding a symlink in <filename>~/.nix-defexpr</filename>: +<screen> +<prompt>$ </prompt>ln -s <replaceable>/my/sources</replaceable>/nixpkgs ~/.nix-defexpr/nixpkgs +</screen> + You may want to delete the symlink + <filename>~/.nix-defexpr/channels_root</filename> to prevent root’s NixOS + channel from clashing with your own tree (this may break the + command-not-found utility though). If you want to go back to the default + state, you may just remove the <filename>~/.nix-defexpr</filename> directory + completely, log out and log in again and it should have been recreated with a + link to the root channels. + </para> +<!-- FIXME: not sure what this means. +<para>You should not pass the base directory +<filename><replaceable>/my/sources</replaceable></filename> +to <command>nix-env</command>, as it will break after interpreting expressions +in <filename>nixos/</filename> as packages.</para> +--> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/testing-installer.xml b/nixpkgs/nixos/doc/manual/development/testing-installer.xml new file mode 100644 index 000000000000..902f995fbc1b --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/testing-installer.xml @@ -0,0 +1,22 @@ +<chapter 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="ch-testing-installer"> + <title>Testing the Installer</title> + <para> + Building, burning, and booting from an installation CD is rather tedious, so + here is a quick way to see if the installer works properly: +<screen> +<prompt># </prompt>mount -t tmpfs none /mnt +<prompt># </prompt>nixos-generate-config --root /mnt +<prompt>$ </prompt>nix-build '<nixpkgs/nixos>' -A config.system.build.nixos-install +<prompt># </prompt>./result/bin/nixos-install</screen> + To start a login shell in the new NixOS installation in + <filename>/mnt</filename>: +<screen> +<prompt>$ </prompt>nix-build '<nixpkgs/nixos>' -A config.system.build.nixos-enter +<prompt># </prompt>./result/bin/nixos-enter +</screen> + </para> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/writing-documentation.xml b/nixpkgs/nixos/doc/manual/development/writing-documentation.xml new file mode 100644 index 000000000000..2183937ad0da --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/writing-documentation.xml @@ -0,0 +1,149 @@ +<chapter 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-writing-documentation"> + <title>Writing NixOS Documentation</title> + <para> + As NixOS grows, so too does the need for a catalogue and explanation of its + extensive functionality. Collecting pertinent information from disparate + sources and presenting it in an accessible style would be a worthy + contribution to the project. + </para> + <section xml:id="sec-writing-docs-building-the-manual"> + <title>Building the Manual</title> + + <para> + The DocBook sources of the <xref linkend="book-nixos-manual"/> are in the + <link xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/doc/manual"><filename>nixos/doc/manual</filename></link> + subdirectory of the Nixpkgs repository. + </para> + + <para> + You can quickly validate your edits with <command>make</command>: + </para> + +<screen> + $ cd /path/to/nixpkgs/nixos/doc/manual + $ make +</screen> + + <para> + Once you are done making modifications to the manual, it's important to + build it before committing. You can do that as follows: + </para> + +<screen>nix-build nixos/release.nix -A manual.x86_64-linux</screen> + + <para> + When this command successfully finishes, it will tell you where the manual + got generated. The HTML will be accessible through the + <filename>result</filename> symlink at + <filename>./result/share/doc/nixos/index.html</filename>. + </para> + </section> + <section xml:id="sec-writing-docs-editing-docbook-xml"> + <title>Editing DocBook XML</title> + + <para> + For general information on how to write in DocBook, see + <link xlink:href="http://www.docbook.org/tdg5/en/html/docbook.html"> DocBook + 5: The Definitive Guide</link>. + </para> + + <para> + Emacs nXML Mode is very helpful for editing DocBook XML because it validates + the document as you write, and precisely locates errors. To use it, see + <xref linkend="sec-emacs-docbook-xml"/>. + </para> + + <para> + <link xlink:href="http://pandoc.org">Pandoc</link> can generate DocBook XML + from a multitude of formats, which makes a good starting point. + <example xml:id="ex-pandoc-xml-conv"> + <title>Pandoc invocation to convert GitHub-Flavoured MarkDown to DocBook 5 XML</title> +<screen>pandoc -f markdown_github -t docbook5 docs.md -o my-section.md</screen> + </example> + Pandoc can also quickly convert a single <filename>section.xml</filename> to + HTML, which is helpful when drafting. + </para> + + <para> + Sometimes writing valid DocBook is simply too difficult. In this case, + submit your documentation updates in a + <link + xlink:href="https://github.com/NixOS/nixpkgs/issues/new">GitHub + Issue</link> and someone will handle the conversion to XML for you. + </para> + </section> + <section xml:id="sec-writing-docs-creating-a-topic"> + <title>Creating a Topic</title> + + <para> + You can use an existing topic as a basis for the new topic or create a topic + from scratch. + </para> + + <para> + Keep the following guidelines in mind when you create and add a topic: + <itemizedlist> + <listitem> + <para> + The NixOS + <link xlink:href="http://www.docbook.org/tdg5/en/html/book.html"><tag>book</tag></link> + element is in <filename>nixos/doc/manual/manual.xml</filename>. It + includes several + <link xlink:href="http://www.docbook.org/tdg5/en/html/book.html"><tag>part</tag>s</link> + which are in subdirectories. + </para> + </listitem> + <listitem> + <para> + Store the topic file in the same directory as the <tag>part</tag> to + which it belongs. If your topic is about configuring a NixOS module, then + the XML file can be stored alongside the module definition + <filename>nix</filename> file. + </para> + </listitem> + <listitem> + <para> + If you include multiple words in the file name, separate the words with a + dash. For example: <filename>ipv6-config.xml</filename>. + </para> + </listitem> + <listitem> + <para> + Make sure that the <tag>xml:id</tag> value is unique. You can use + abbreviations if the ID is too long. For example: + <varname>nixos-config</varname>. + </para> + </listitem> + <listitem> + <para> + Determine whether your topic is a chapter or a section. If you are + unsure, open an existing topic file and check whether the main element is + chapter or section. + </para> + </listitem> + </itemizedlist> + </para> + </section> + <section xml:id="sec-writing-docs-adding-a-topic"> + <title>Adding a Topic to the Book</title> + + <para> + Open the parent XML file and add an <varname>xi:include</varname> element to + the list of chapters with the file name of the topic that you created. If + you created a <tag>section</tag>, you add the file to the <tag>chapter</tag> + file. If you created a <tag>chapter</tag>, you add the file to the + <tag>part</tag> file. + </para> + + <para> + If the topic is about configuring a NixOS module, it can be automatically + included in the manual by using the <varname>meta.doc</varname> attribute. + See <xref + linkend="sec-meta-attributes"/> for an explanation. + </para> + </section> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/writing-modules.xml b/nixpkgs/nixos/doc/manual/development/writing-modules.xml new file mode 100644 index 000000000000..bbf793bb0be9 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/writing-modules.xml @@ -0,0 +1,186 @@ +<chapter 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-writing-modules"> + <title>Writing NixOS Modules</title> + <para> + NixOS has a modular system for declarative configuration. This system + combines multiple <emphasis>modules</emphasis> to produce the full system + configuration. One of the modules that constitute the configuration is + <filename>/etc/nixos/configuration.nix</filename>. Most of the others live in + the + <link +xlink:href="https://github.com/NixOS/nixpkgs/tree/master/nixos/modules"><filename>nixos/modules</filename></link> + subdirectory of the Nixpkgs tree. + </para> + <para> + Each NixOS module is a file that handles one logical aspect of the + configuration, such as a specific kind of hardware, a service, or network + settings. A module configuration does not have to handle everything from + scratch; it can use the functionality provided by other modules for its + implementation. Thus a module can <emphasis>declare</emphasis> options that + can be used by other modules, and conversely can <emphasis>define</emphasis> + options provided by other modules in its own implementation. For example, the + module + <link +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/pam.nix"><filename>pam.nix</filename></link> + declares the option <option>security.pam.services</option> that allows other + modules (e.g. + <link +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/ssh/sshd.nix"><filename>sshd.nix</filename></link>) + to define PAM services; and it defines the option + <option>environment.etc</option> (declared by + <link +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/etc/etc.nix"><filename>etc.nix</filename></link>) + to cause files to be created in <filename>/etc/pam.d</filename>. + </para> + <para xml:id="para-module-syn"> + In <xref +linkend="sec-configuration-syntax"/>, we saw the following structure + of NixOS modules: +<programlisting> +{ config, pkgs, ... }: + +{ <replaceable>option definitions</replaceable> +} +</programlisting> + This is actually an <emphasis>abbreviated</emphasis> form of module that only + defines options, but does not declare any. The structure of full NixOS + modules is shown in <xref linkend='ex-module-syntax' />. + </para> + <example xml:id='ex-module-syntax'> + <title>Structure of NixOS Modules</title> +<programlisting> +{ config, pkgs, ... }: <co xml:id='module-syntax-1' /> + +{ + imports = + [ <replaceable>paths of other modules</replaceable> <co xml:id='module-syntax-2' /> + ]; + + options = { + <replaceable>option declarations</replaceable> <co xml:id='module-syntax-3' /> + }; + + config = { + <replaceable>option definitions</replaceable> <co xml:id='module-syntax-4' /> + }; +}</programlisting> + </example> + <para> + The meaning of each part is as follows. + <calloutlist> + <callout arearefs='module-syntax-1'> + <para> + This line makes the current Nix expression a function. The variable + <varname>pkgs</varname> contains Nixpkgs, while <varname>config</varname> + contains the full system configuration. This line can be omitted if there + is no reference to <varname>pkgs</varname> and <varname>config</varname> + inside the module. + </para> + </callout> + <callout arearefs='module-syntax-2'> + <para> + This list enumerates the paths to other NixOS modules that should be + included in the evaluation of the system configuration. A default set of + modules is defined in the file + <filename>modules/module-list.nix</filename>. These don't need to be added + in the import list. + </para> + </callout> + <callout arearefs='module-syntax-3'> + <para> + The attribute <varname>options</varname> is a nested set of + <emphasis>option declarations</emphasis> (described below). + </para> + </callout> + <callout arearefs='module-syntax-4'> + <para> + The attribute <varname>config</varname> is a nested set of + <emphasis>option definitions</emphasis> (also described below). + </para> + </callout> + </calloutlist> + </para> + <para> + <xref linkend='locate-example' /> shows a module that handles the regular + update of the “locate” database, an index of all files in the file + system. This module declares two options that can be defined by other modules + (typically the user’s <filename>configuration.nix</filename>): + <option>services.locate.enable</option> (whether the database should be + updated) and <option>services.locate.interval</option> (when the update + should be done). It implements its functionality by defining two options + declared by other modules: <option>systemd.services</option> (the set of all + systemd services) and <option>systemd.timers</option> (the list of commands + to be executed periodically by <command>systemd</command>). + </para> + <example xml:id='locate-example'> + <title>NixOS Module for the “locate” Service</title> +<programlisting> +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.locate; +in { + options.services.locate = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, NixOS will periodically update the database of + files used by the <command>locate</command> command. + ''; + }; + + interval = mkOption { + type = types.str; + default = "02:15"; + example = "hourly"; + description = '' + Update the locate database at this interval. Updates by + default at 2:15 AM every day. + + The format is described in + <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry>. + ''; + }; + + # Other options omitted for documentation + }; + + config = { + systemd.services.update-locatedb = + { description = "Update Locate Database"; + path = [ pkgs.su ]; + script = + '' + mkdir -m 0755 -p $(dirname ${toString cfg.output}) + exec updatedb \ + --localuser=${cfg.localuser} \ + ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \ + --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags} + ''; + }; + + systemd.timers.update-locatedb = mkIf cfg.enable + { description = "Update timer for locate database"; + partOf = [ "update-locatedb.service" ]; + wantedBy = [ "timers.target" ]; + timerConfig.OnCalendar = cfg.interval; + }; + }; +} +</programlisting> + </example> + <xi:include href="option-declarations.xml" /> + <xi:include href="option-types.xml" /> + <xi:include href="option-def.xml" /> + <xi:include href="assertions.xml" /> + <xi:include href="meta-attributes.xml" /> + <xi:include href="importing-modules.xml" /> + <xi:include href="replace-modules.xml" /> +</chapter> diff --git a/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml b/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml new file mode 100644 index 000000000000..6be2d0a4d231 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml @@ -0,0 +1,421 @@ +<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-writing-nixos-tests"> + <title>Writing Tests</title> + + <para> + A NixOS test is a Nix expression that has the following structure: +<programlisting> +import ./make-test.nix { + + # Either the configuration of a single machine: + machine = + { config, pkgs, ... }: + { <replaceable>configuration…</replaceable> + }; + + # Or a set of machines: + nodes = + { <replaceable>machine1</replaceable> = + { config, pkgs, ... }: { <replaceable>…</replaceable> }; + <replaceable>machine2</replaceable> = + { config, pkgs, ... }: { <replaceable>…</replaceable> }; + … + }; + + testScript = + '' + <replaceable>Perl code…</replaceable> + ''; +} +</programlisting> + The attribute <literal>testScript</literal> is a bit of Perl code that + executes the test (described below). During the test, it will start one or + more virtual machines, the configuration of which is described by the + attribute <literal>machine</literal> (if you need only one machine in your + test) or by the attribute <literal>nodes</literal> (if you need multiple + machines). For instance, + <filename +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">login.nix</filename> + only needs a single machine to test whether users can log in on the virtual + console, whether device ownership is correctly maintained when switching + between consoles, and so on. On the other hand, + <filename +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs.nix">nfs.nix</filename>, + which tests NFS client and server functionality in the Linux kernel + (including whether locks are maintained across server crashes), requires + three machines: a server and two clients. + </para> + + <para> + There are a few special NixOS configuration options for test VMs: +<!-- FIXME: would be nice to generate this automatically. --> + <variablelist> + <varlistentry> + <term> + <option>virtualisation.memorySize</option> + </term> + <listitem> + <para> + The memory of the VM in megabytes. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <option>virtualisation.vlans</option> + </term> + <listitem> + <para> + The virtual networks to which the VM is connected. See + <filename + xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nat.nix">nat.nix</filename> + for an example. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <option>virtualisation.writableStore</option> + </term> + <listitem> + <para> + By default, the Nix store in the VM is not writable. If you enable this + option, a writable union file system is mounted on top of the Nix store + to make it appear writable. This is necessary for tests that run Nix + operations that modify the store. + </para> + </listitem> + </varlistentry> + </variablelist> + For more options, see the module + <filename +xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/qemu-vm.nix">qemu-vm.nix</filename>. + </para> + + <para> + The test script is a sequence of Perl statements that perform various + actions, such as starting VMs, executing commands in the VMs, and so on. Each + virtual machine is represented as an object stored in the variable + <literal>$<replaceable>name</replaceable></literal>, where + <replaceable>name</replaceable> is the identifier of the machine (which is + just <literal>machine</literal> if you didn’t specify multiple machines + using the <literal>nodes</literal> attribute). For instance, the following + starts the machine, waits until it has finished booting, then executes a + command and checks that the output is more-or-less correct: +<programlisting> +$machine->start; +$machine->waitForUnit("default.target"); +$machine->succeed("uname") =~ /Linux/ or die; +</programlisting> + The first line is actually unnecessary; machines are implicitly started when + you first execute an action on them (such as <literal>waitForUnit</literal> + or <literal>succeed</literal>). If you have multiple machines, you can speed + up the test by starting them in parallel: +<programlisting> +startAll; +</programlisting> + </para> + + <para> + The following methods are available on machine objects: + <variablelist> + <varlistentry> + <term> + <methodname>start</methodname> + </term> + <listitem> + <para> + Start the virtual machine. This method is asynchronous — it does not + wait for the machine to finish booting. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>shutdown</methodname> + </term> + <listitem> + <para> + Shut down the machine, waiting for the VM to exit. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>crash</methodname> + </term> + <listitem> + <para> + Simulate a sudden power failure, by telling the VM to exit immediately. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>block</methodname> + </term> + <listitem> + <para> + Simulate unplugging the Ethernet cable that connects the machine to the + other machines. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>unblock</methodname> + </term> + <listitem> + <para> + Undo the effect of <methodname>block</methodname>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>screenshot</methodname> + </term> + <listitem> + <para> + Take a picture of the display of the virtual machine, in PNG format. The + screenshot is linked from the HTML log. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>getScreenText</methodname> + </term> + <listitem> + <para> + Return a textual representation of what is currently visible on the + machine's screen using optical character recognition. + </para> + <note> + <para> + This requires passing <option>enableOCR</option> to the test attribute + set. + </para> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>sendMonitorCommand</methodname> + </term> + <listitem> + <para> + Send a command to the QEMU monitor. This is rarely used, but allows doing + stuff such as attaching virtual USB disks to a running machine. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>sendKeys</methodname> + </term> + <listitem> + <para> + Simulate pressing keys on the virtual keyboard, e.g., + <literal>sendKeys("ctrl-alt-delete")</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>sendChars</methodname> + </term> + <listitem> + <para> + Simulate typing a sequence of characters on the virtual keyboard, e.g., + <literal>sendKeys("foobar\n")</literal> will type the string + <literal>foobar</literal> followed by the Enter key. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>execute</methodname> + </term> + <listitem> + <para> + Execute a shell command, returning a list + <literal>(<replaceable>status</replaceable>, + <replaceable>stdout</replaceable>)</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>succeed</methodname> + </term> + <listitem> + <para> + Execute a shell command, raising an exception if the exit status is not + zero, otherwise returning the standard output. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>fail</methodname> + </term> + <listitem> + <para> + Like <methodname>succeed</methodname>, but raising an exception if the + command returns a zero status. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitUntilSucceeds</methodname> + </term> + <listitem> + <para> + Repeat a shell command with 1-second intervals until it succeeds. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitUntilFails</methodname> + </term> + <listitem> + <para> + Repeat a shell command with 1-second intervals until it fails. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForUnit</methodname> + </term> + <listitem> + <para> + Wait until the specified systemd unit has reached the “active” state. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForFile</methodname> + </term> + <listitem> + <para> + Wait until the specified file exists. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForOpenPort</methodname> + </term> + <listitem> + <para> + Wait until a process is listening on the given TCP port (on + <literal>localhost</literal>, at least). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForClosedPort</methodname> + </term> + <listitem> + <para> + Wait until nobody is listening on the given TCP port. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForX</methodname> + </term> + <listitem> + <para> + Wait until the X11 server is accepting connections. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForText</methodname> + </term> + <listitem> + <para> + Wait until the supplied regular expressions matches the textual contents + of the screen by using optical character recognition (see + <methodname>getScreenText</methodname>). + </para> + <note> + <para> + This requires passing <option>enableOCR</option> to the test attribute + set. + </para> + </note> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>waitForWindow</methodname> + </term> + <listitem> + <para> + Wait until an X11 window has appeared whose name matches the given + regular expression, e.g., <literal>waitForWindow(qr/Terminal/)</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>copyFileFromHost</methodname> + </term> + <listitem> + <para> + Copies a file from host to machine, e.g., + <literal>copyFileFromHost("myfile", "/etc/my/important/file")</literal>. + </para> + <para> + The first argument is the file on the host. The file needs to be + accessible while building the nix derivation. The second argument is the + location of the file on the machine. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <methodname>systemctl</methodname> + </term> + <listitem> + <para> + Runs <literal>systemctl</literal> commands with optional support for + <literal>systemctl --user</literal> + </para> + <para> +<programlisting> +$machine->systemctl("list-jobs --no-pager"); // runs `systemctl list-jobs --no-pager` +$machine->systemctl("list-jobs --no-pager", "any-user"); // spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager` +</programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + + <para> + To test user units declared by <literal>systemd.user.services</literal> the + optional <literal>$user</literal> argument can be used: +<programlisting> +$machine->start; +$machine->waitForX; +$machine->waitForUnit("xautolock.service", "x-session-user"); +</programlisting> + This applies to <literal>systemctl</literal>, <literal>getUnitInfo</literal>, + <literal>waitForUnit</literal>, <literal>startJob</literal> and + <literal>stopJob</literal>. + </para> +</section> |