Merge pull request #128885 from bobby285271/pr3

nixos/doc: convert "Chapter 5. Configuration Syntax" to CommonMark
This commit is contained in:
Jörg Thalheim 2021-09-07 03:56:34 +01:00 committed by GitHub
commit 6e17c53b98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1072 additions and 592 deletions

View file

@ -0,0 +1,175 @@
# NixOS Configuration File {#sec-configuration-file}
The NixOS configuration file generally looks like this:
```nix
{ config, pkgs, ... }:
{ option definitions
}
```
The first line (`{ config, pkgs, ... }:`) denotes that this is actually
a function that takes at least the two arguments `config` and `pkgs`.
(These are explained later, in chapter [](#sec-writing-modules)) The
function returns a *set* of option definitions (`{ ... }`).
These definitions have the form `name = value`, where `name` is the
name of an option and `value` is its value. For example,
```nix
{ config, pkgs, ... }:
{ services.httpd.enable = true;
services.httpd.adminAddr = "alice@example.org";
services.httpd.virtualHosts.localhost.documentRoot = "/webroot";
}
```
defines a configuration with three option definitions that together
enable the Apache HTTP Server with `/webroot` as the document root.
Sets can be nested, and in fact dots in option names are shorthand for
defining a set containing another set. For instance,
[](#opt-services.httpd.enable) defines a set named
`services` that contains a set named `httpd`, which in turn contains an
option definition named `enable` with value `true`. This means that the
example above can also be written as:
```nix
{ config, pkgs, ... }:
{ services = {
httpd = {
enable = true;
adminAddr = "alice@example.org";
virtualHosts = {
localhost = {
documentRoot = "/webroot";
};
};
};
};
}
```
which may be more convenient if you have lots of option definitions that
share the same prefix (such as `services.httpd`).
NixOS checks your option definitions for correctness. For instance, if
you try to define an option that doesn't exist (that is, doesn't have a
corresponding *option declaration*), `nixos-rebuild` will give an error
like:
```plain
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
```
Likewise, values in option definitions must have a correct type. For
instance, `services.httpd.enable` must be a Boolean (`true` or `false`).
Trying to give it a value of another type, such as a string, will cause
an error:
```plain
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
```
Options have various types of values. The most important are:
Strings
: Strings are enclosed in double quotes, e.g.
```nix
networking.hostName = "dexter";
```
Special characters can be escaped by prefixing them with a backslash
(e.g. `\"`).
Multi-line strings can be enclosed in *double single quotes*, e.g.
```nix
networking.extraHosts =
''
127.0.0.2 other-localhost
10.0.0.1 server
'';
```
The main difference is that it strips from each line a number of
spaces equal to the minimal indentation of the string as a whole
(disregarding the indentation of empty lines), and that characters
like `"` and `\` are not special (making it more convenient for
including things like shell code). See more info about this in the
Nix manual [here](https://nixos.org/nix/manual/#ssec-values).
Booleans
: These can be `true` or `false`, e.g.
```nix
networking.firewall.enable = true;
networking.firewall.allowPing = false;
```
Integers
: For example,
```nix
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
```
(Note that here the attribute name `net.ipv4.tcp_keepalive_time` is
enclosed in quotes to prevent it from being interpreted as a set
named `net` containing a set named `ipv4`, and so on. This is
because it's not a NixOS option but the literal name of a Linux
kernel setting.)
Sets
: Sets were introduced above. They are name/value pairs enclosed in
braces, as in the option definition
```nix
fileSystems."/boot" =
{ device = "/dev/sda1";
fsType = "ext4";
options = [ "rw" "data=ordered" "relatime" ];
};
```
Lists
: The important thing to note about lists is that list elements are
separated by whitespace, like this:
```nix
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
```
List elements can be any other type, e.g. sets:
```nix
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
```
Packages
: Usually, the packages you need are already part of the Nix Packages
collection, which is a set that can be accessed through the function
argument `pkgs`. Typical uses:
```nix
environment.systemPackages =
[ pkgs.thunderbird
pkgs.emacs
];
services.postgresql.package = pkgs.postgresql_10;
```
The latter option definition changes the default PostgreSQL package
used by NixOS's PostgreSQL service to 10.x. For more information on
packages, including how to add new ones, see
[](#sec-custom-packages).

View file

@ -1,216 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-configuration-file">
<title>NixOS Configuration File</title>
<para>
The NixOS configuration file generally looks like this:
<programlisting>
{ config, pkgs, ... }:
{ <replaceable>option definitions</replaceable>
}
</programlisting>
The first line (<literal>{ config, pkgs, ... }:</literal>) denotes that this
is actually a function that takes at least the two arguments
<varname>config</varname> and <varname>pkgs</varname>. (These are explained
later, in chapter <xref linkend="sec-writing-modules" />) The function returns
a <emphasis>set</emphasis> of option definitions (<literal>{
<replaceable>...</replaceable> }</literal>). These definitions have the form
<literal><replaceable>name</replaceable> =
<replaceable>value</replaceable></literal>, where
<replaceable>name</replaceable> is the name of an option and
<replaceable>value</replaceable> is its value. For example,
<programlisting>
{ config, pkgs, ... }:
{ <xref linkend="opt-services.httpd.enable"/> = true;
<xref linkend="opt-services.httpd.adminAddr"/> = "alice@example.org";
<link linkend="opt-services.httpd.virtualHosts">services.httpd.virtualHosts.localhost.documentRoot</link> = "/webroot";
}
</programlisting>
defines a configuration with three option definitions that together enable
the Apache HTTP Server with <filename>/webroot</filename> as the document
root.
</para>
<para>
Sets can be nested, and in fact dots in option names are shorthand for
defining a set containing another set. For instance,
<xref linkend="opt-services.httpd.enable"/> defines a set named
<varname>services</varname> that contains a set named
<varname>httpd</varname>, which in turn contains an option definition named
<varname>enable</varname> with value <literal>true</literal>. This means that
the example above can also be written as:
<programlisting>
{ config, pkgs, ... }:
{ services = {
httpd = {
enable = true;
adminAddr = "alice@example.org";
virtualHosts = {
localhost = {
documentRoot = "/webroot";
};
};
};
};
}
</programlisting>
which may be more convenient if you have lots of option definitions that
share the same prefix (such as <literal>services.httpd</literal>).
</para>
<para>
NixOS checks your option definitions for correctness. For instance, if you
try to define an option that doesnt exist (that is, doesnt have a
corresponding <emphasis>option declaration</emphasis>),
<command>nixos-rebuild</command> will give an error like:
<screen>
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
</screen>
Likewise, values in option definitions must have a correct type. For
instance, <option>services.httpd.enable</option> must be a Boolean
(<literal>true</literal> or <literal>false</literal>). Trying to give it a
value of another type, such as a string, will cause an error:
<screen>
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
</screen>
</para>
<para>
Options have various types of values. The most important are:
<variablelist>
<varlistentry>
<term>
Strings
</term>
<listitem>
<para>
Strings are enclosed in double quotes, e.g.
<programlisting>
<xref linkend="opt-networking.hostName"/> = "dexter";
</programlisting>
Special characters can be escaped by prefixing them with a backslash
(e.g. <literal>\"</literal>).
</para>
<para>
Multi-line strings can be enclosed in <emphasis>double single
quotes</emphasis>, e.g.
<programlisting>
<xref linkend="opt-networking.extraHosts"/> =
''
127.0.0.2 other-localhost
10.0.0.1 server
'';
</programlisting>
The main difference is that it strips from each line a number of spaces
equal to the minimal indentation of the string as a whole (disregarding
the indentation of empty lines), and that characters like
<literal>"</literal> and <literal>\</literal> are not special (making it
more convenient for including things like shell code). See more info
about this in the Nix manual
<link
xlink:href="https://nixos.org/nix/manual/#ssec-values">here</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Booleans
</term>
<listitem>
<para>
These can be <literal>true</literal> or <literal>false</literal>, e.g.
<programlisting>
<xref linkend="opt-networking.firewall.enable"/> = true;
<xref linkend="opt-networking.firewall.allowPing"/> = false;
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Integers
</term>
<listitem>
<para>
For example,
<programlisting>
<xref linkend="opt-boot.kernel.sysctl"/>."net.ipv4.tcp_keepalive_time" = 60;
</programlisting>
(Note that here the attribute name
<literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in quotes to
prevent it from being interpreted as a set named <literal>net</literal>
containing a set named <literal>ipv4</literal>, and so on. This is
because its not a NixOS option but the literal name of a Linux kernel
setting.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Sets
</term>
<listitem>
<para>
Sets were introduced above. They are name/value pairs enclosed in braces,
as in the option definition
<programlisting>
<xref linkend="opt-fileSystems"/>."/boot" =
{ device = "/dev/sda1";
fsType = "ext4";
options = [ "rw" "data=ordered" "relatime" ];
};
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Lists
</term>
<listitem>
<para>
The important thing to note about lists is that list elements are
separated by whitespace, like this:
<programlisting>
<xref linkend="opt-boot.kernelModules"/> = [ "fuse" "kvm-intel" "coretemp" ];
</programlisting>
List elements can be any other type, e.g. sets:
<programlisting>
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Packages
</term>
<listitem>
<para>
Usually, the packages you need are already part of the Nix Packages
collection, which is a set that can be accessed through the function
argument <varname>pkgs</varname>. Typical uses:
<programlisting>
<xref linkend="opt-environment.systemPackages"/> =
[ pkgs.thunderbird
pkgs.emacs
];
<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_10;
</programlisting>
The latter option definition changes the default PostgreSQL package used
by NixOSs PostgreSQL service to 10.x. For more information on
packages, including how to add new ones, see
<xref linkend="sec-custom-packages"/>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>

View file

@ -18,8 +18,8 @@ xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
manual</link>, but here we give a short overview of the most important
constructs useful in NixOS configuration files.
</para>
<xi:include href="config-file.xml" />
<xi:include href="../from_md/configuration/config-file.section.xml" />
<xi:include href="../from_md/configuration/abstractions.section.xml" />
<xi:include href="modularity.xml" />
<xi:include href="summary.xml" />
<xi:include href="../from_md/configuration/modularity.section.xml" />
<xi:include href="../from_md/configuration/summary.section.xml" />
</chapter>

View file

@ -0,0 +1,133 @@
# Modularity {#sec-modularity}
The NixOS configuration mechanism is modular. If your
`configuration.nix` becomes too big, you can split it into multiple
files. Likewise, if you have multiple NixOS configurations (e.g. for
different computers) with some commonality, you can move the common
configuration into a shared file.
Modules have exactly the same syntax as `configuration.nix`. In fact,
`configuration.nix` is itself a module. You can use other modules by
including them from `configuration.nix`, e.g.:
```nix
{ config, pkgs, ... }:
{ imports = [ ./vpn.nix ./kde.nix ];
services.httpd.enable = true;
environment.systemPackages = [ pkgs.emacs ];
...
}
```
Here, we include two modules from the same directory, `vpn.nix` and
`kde.nix`. The latter might look like this:
```nix
{ config, pkgs, ... }:
{ services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
environment.systemPackages = [ pkgs.vim ];
}
```
Note that both `configuration.nix` and `kde.nix` define the option
[](#opt-environment.systemPackages). When multiple modules define an
option, NixOS will try to *merge* the definitions. In the case of
[](#opt-environment.systemPackages), that's easy: the lists of
packages can simply be concatenated. The value in `configuration.nix` is
merged last, so for list-type options, it will appear at the end of the
merged list. If you want it to appear first, you can use `mkBefore`:
```nix
boot.kernelModules = mkBefore [ "kvm-intel" ];
```
This causes the `kvm-intel` kernel module to be loaded before any other
kernel modules.
For other types of options, a merge may not be possible. For instance,
if two modules define [](#opt-services.httpd.adminAddr),
`nixos-rebuild` will give an error:
```plain
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
```
When that happens, it's possible to force one definition take precedence
over the others:
```nix
services.httpd.adminAddr = pkgs.lib.mkForce "bob@example.org";
```
When using multiple modules, you may need to access configuration values
defined in other modules. This is what the `config` function argument is
for: it contains the complete, merged system configuration. That is,
`config` is the result of combining the configurations returned by every
module [^1] . For example, here is a module that adds some packages to
[](#opt-environment.systemPackages) only if
[](#opt-services.xserver.enable) is set to `true` somewhere else:
```nix
{ config, pkgs, ... }:
{ environment.systemPackages =
if config.services.xserver.enable then
[ pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
```
With multiple modules, it may not be obvious what the final value of a
configuration option is. The command `nixos-option` allows you to find
out:
```ShellSession
$ nixos-option services.xserver.enable
true
$ nixos-option boot.kernelModules
[ "tun" "ipv6" "loop" ... ]
```
Interactive exploration of the configuration is possible using `nix
repl`, a read-eval-print loop for Nix expressions. A typical use:
```ShellSession
$ nix repl '<nixpkgs/nixos>'
nix-repl> config.networking.hostName
"mandark"
nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
[ "example.org" "example.gov" ]
```
While abstracting your configuration, you may find it useful to generate
modules using code, instead of writing files. The example below would
have the same effect as importing a file which sets those options.
```nix
{ config, pkgs, ... }:
let netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{ imports = [ (netConfig "nixos.localdomain") ]; }
```
[^1]: If you're wondering how it's possible that the (indirect) *result*
of a function is passed as an *input* to that same function: that's
because Nix is a "lazy" language --- it only computes values when
they are needed. This works as long as no individual configuration
value depends on itself.

View file

@ -1,146 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-modularity">
<title>Modularity</title>
<para>
The NixOS configuration mechanism is modular. If your
<filename>configuration.nix</filename> becomes too big, you can split it into
multiple files. Likewise, if you have multiple NixOS configurations (e.g. for
different computers) with some commonality, you can move the common
configuration into a shared file.
</para>
<para>
Modules have exactly the same syntax as
<filename>configuration.nix</filename>. In fact,
<filename>configuration.nix</filename> is itself a module. You can use other
modules by including them from <filename>configuration.nix</filename>, e.g.:
<programlisting>
{ config, pkgs, ... }:
{ imports = [ ./vpn.nix ./kde.nix ];
<xref linkend="opt-services.httpd.enable"/> = true;
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.emacs ];
<replaceable>...</replaceable>
}
</programlisting>
Here, we include two modules from the same directory,
<filename>vpn.nix</filename> and <filename>kde.nix</filename>. The latter
might look like this:
<programlisting>
{ config, pkgs, ... }:
{ <xref linkend="opt-services.xserver.enable"/> = true;
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true;
<xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ];
}
</programlisting>
Note that both <filename>configuration.nix</filename> and
<filename>kde.nix</filename> define the option
<xref linkend="opt-environment.systemPackages"/>. When multiple modules
define an option, NixOS will try to <emphasis>merge</emphasis> the
definitions. In the case of <xref linkend="opt-environment.systemPackages"/>,
thats easy: the lists of packages can simply be concatenated. The value in
<filename>configuration.nix</filename> is merged last, so for list-type
options, it will appear at the end of the merged list. If you want it to
appear first, you can use <varname>mkBefore</varname>:
<programlisting>
<xref linkend="opt-boot.kernelModules"/> = mkBefore [ "kvm-intel" ];
</programlisting>
This causes the <literal>kvm-intel</literal> kernel module to be loaded
before any other kernel modules.
</para>
<para>
For other types of options, a merge may not be possible. For instance, if two
modules define <xref linkend="opt-services.httpd.adminAddr"/>,
<command>nixos-rebuild</command> will give an error:
<screen>
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
</screen>
When that happens, its possible to force one definition take precedence
over the others:
<programlisting>
<xref linkend="opt-services.httpd.adminAddr"/> = pkgs.lib.mkForce "bob@example.org";
</programlisting>
</para>
<para>
When using multiple modules, you may need to access configuration values
defined in other modules. This is what the <varname>config</varname> function
argument is for: it contains the complete, merged system configuration. That
is, <varname>config</varname> is the result of combining the configurations
returned by every module
<footnote xml:id="footnote-nix-is-lazy">
<para>
If youre wondering how its possible that the (indirect)
<emphasis>result</emphasis> of a function is passed as an
<emphasis>input</emphasis> to that same function: thats because Nix is a
“lazy” language — it only computes values when they are needed. This
works as long as no individual configuration value depends on itself.
</para>
</footnote>
. For example, here is a module that adds some packages to
<xref linkend="opt-environment.systemPackages"/> only if
<xref linkend="opt-services.xserver.enable"/> is set to
<literal>true</literal> somewhere else:
<programlisting>
{ config, pkgs, ... }:
{ <xref linkend="opt-environment.systemPackages"/> =
if config.<xref linkend="opt-services.xserver.enable"/> then
[ pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
</programlisting>
</para>
<para>
With multiple modules, it may not be obvious what the final value of a
configuration option is. The command <option>nixos-option</option> allows you
to find out:
<screen>
<prompt>$ </prompt>nixos-option <xref linkend="opt-services.xserver.enable"/>
true
<prompt>$ </prompt>nixos-option <xref linkend="opt-boot.kernelModules"/>
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
</screen>
Interactive exploration of the configuration is possible using <command>nix
repl</command>, a read-eval-print loop for Nix expressions. A typical use:
<screen>
<prompt>$ </prompt>nix repl '&lt;nixpkgs/nixos>'
<prompt>nix-repl> </prompt>config.<xref linkend="opt-networking.hostName"/>
"mandark"
<prompt>nix-repl> </prompt>map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHosts"/>
[ "example.org" "example.gov" ]
</screen>
</para>
<para>
While abstracting your configuration, you may find it useful to generate
modules using code, instead of writing files. The example below would have
the same effect as importing a file which sets those options.
<programlisting>
{ config, pkgs, ... }:
let netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{ imports = [ (netConfig "nixos.localdomain") ]; }
</programlisting>
</para>
</section>

View file

@ -0,0 +1,46 @@
# Syntax Summary {#sec-nix-syntax-summary}
Below is a summary of the most important syntactic constructs in the Nix
expression language. It's not complete. In particular, there are many
other built-in functions. See the [Nix
manual](https://nixos.org/nix/manual/#chap-writing-nix-expressions) for
the rest.
| Example | Description |
|-----------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| *Basic values* | |
| `"Hello world"` | A string |
| `"${pkgs.bash}/bin/sh"` | A string containing an expression (expands to `"/nix/store/hash-bash-version/bin/sh"`) |
| `true`, `false` | Booleans |
| `123` | An integer |
| `./foo.png` | A path (relative to the containing Nix expression) |
| *Compound values* | |
| `{ x = 1; y = 2; }` | A set with attributes named `x` and `y` |
| `{ foo.bar = 1; }` | A nested set, equivalent to `{ foo = { bar = 1; }; }` |
| `rec { x = "foo"; y = x + "bar"; }` | A recursive set, equivalent to `{ x = "foo"; y = "foobar"; }` |
| `[ "foo" "bar" ]` | A list with two elements |
| *Operators* | |
| `"foo" + "bar"` | String concatenation |
| `1 + 2` | Integer addition |
| `"foo" == "f" + "oo"` | Equality test (evaluates to `true`) |
| `"foo" != "bar"` | Inequality test (evaluates to `true`) |
| `!true` | Boolean negation |
| `{ x = 1; y = 2; }.x` | Attribute selection (evaluates to `1`) |
| `{ x = 1; y = 2; }.z or 3` | Attribute selection with default (evaluates to `3`) |
| `{ x = 1; y = 2; } // { z = 3; }` | Merge two sets (attributes in the right-hand set taking precedence) |
| *Control structures* | |
| `if 1 + 1 == 2 then "yes!" else "no!"` | Conditional expression |
| `assert 1 + 1 == 2; "yes!"` | Assertion check (evaluates to `"yes!"`). See [](#sec-assertions) for using assertions in modules |
| `let x = "foo"; y = "bar"; in x + y` | Variable definition |
| `with pkgs.lib; head [ 1 2 3 ]` | Add all attributes from the given set to the scope (evaluates to `1`) |
| *Functions (lambdas)* | |
| `x: x + 1` | A function that expects an integer and returns it increased by 1 |
| `(x: x + 1) 100` | A function call (evaluates to 101) |
| `let inc = x: x + 1; in inc (inc (inc 100))` | A function bound to a variable and subsequently called by name (evaluates to 103) |
| `{ x, y }: x + y` | A function that expects a set with required attributes `x` and `y` and concatenates them |
| `{ x, y ? "bar" }: x + y` | A function that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y` |
| `{ x, y, ... }: x + y` | A function that expects a set with required attributes `x` and `y` and ignores any other attributes |
| `{ x, y } @ args: x + y` | A function that expects a set with required attributes `x` and `y`, and binds the whole set to `args` |
| *Built-in functions* | |
| `import ./foo.nix` | Load and return Nix expression in given file |
| `map (x: x + x) [ 1 2 3 ]` | Apply a function to every element of a list (evaluates to `[ 2 4 6 ]`) |

View file

@ -1,227 +0,0 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-nix-syntax-summary">
<title>Syntax Summary</title>
<para>
Below is a summary of the most important syntactic constructs in the Nix
expression language. Its not complete. In particular, there are many other
built-in functions. See the
<link
xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
manual</link> for the rest.
</para>
<informaltable frame='none'>
<tgroup cols='2'>
<colspec colname='c1' rowsep='1' colsep='1' />
<colspec colname='c2' rowsep='1' />
<thead>
<row>
<entry>Example</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry namest="c1" nameend="c2"><emphasis>Basic values</emphasis>
</entry>
</row>
<row>
<entry><literal>"Hello world"</literal>
</entry>
<entry>A string</entry>
</row>
<row>
<entry><literal>"${pkgs.bash}/bin/sh"</literal>
</entry>
<entry>A string containing an expression (expands to <literal>"/nix/store/<replaceable>hash</replaceable>-bash-<replaceable>version</replaceable>/bin/sh"</literal>)</entry>
</row>
<row>
<entry><literal>true</literal>, <literal>false</literal>
</entry>
<entry>Booleans</entry>
</row>
<row>
<entry><literal>123</literal>
</entry>
<entry>An integer</entry>
</row>
<row>
<entry><literal>./foo.png</literal>
</entry>
<entry>A path (relative to the containing Nix expression)</entry>
</row>
<row>
<entry namest="c1" nameend="c2"><emphasis>Compound values</emphasis>
</entry>
</row>
<row>
<entry><literal>{ x = 1; y = 2; }</literal>
</entry>
<entry>A set with attributes named <literal>x</literal> and <literal>y</literal>
</entry>
</row>
<row>
<entry><literal>{ foo.bar = 1; }</literal>
</entry>
<entry>A nested set, equivalent to <literal>{ foo = { bar = 1; }; }</literal>
</entry>
</row>
<row>
<entry><literal>rec { x = "foo"; y = x + "bar"; }</literal>
</entry>
<entry>A recursive set, equivalent to <literal>{ x = "foo"; y = "foobar"; }</literal>
</entry>
</row>
<row>
<entry><literal>[ "foo" "bar" ]</literal>
</entry>
<entry>A list with two elements</entry>
</row>
<row>
<entry namest="c1" nameend="c2"><emphasis>Operators</emphasis>
</entry>
</row>
<row>
<entry><literal>"foo" + "bar"</literal>
</entry>
<entry>String concatenation</entry>
</row>
<row>
<entry><literal>1 + 2</literal>
</entry>
<entry>Integer addition</entry>
</row>
<row>
<entry><literal>"foo" == "f" + "oo"</literal>
</entry>
<entry>Equality test (evaluates to <literal>true</literal>)</entry>
</row>
<row>
<entry><literal>"foo" != "bar"</literal>
</entry>
<entry>Inequality test (evaluates to <literal>true</literal>)</entry>
</row>
<row>
<entry><literal>!true</literal>
</entry>
<entry>Boolean negation</entry>
</row>
<row>
<entry><literal>{ x = 1; y = 2; }.x</literal>
</entry>
<entry>Attribute selection (evaluates to <literal>1</literal>)</entry>
</row>
<row>
<entry><literal>{ x = 1; y = 2; }.z or 3</literal>
</entry>
<entry>Attribute selection with default (evaluates to <literal>3</literal>)</entry>
</row>
<row>
<entry><literal>{ x = 1; y = 2; } // { z = 3; }</literal>
</entry>
<entry>Merge two sets (attributes in the right-hand set taking precedence)</entry>
</row>
<row>
<entry namest="c1" nameend="c2"><emphasis>Control structures</emphasis>
</entry>
</row>
<row>
<entry><literal>if 1 + 1 == 2 then "yes!" else "no!"</literal>
</entry>
<entry>Conditional expression</entry>
</row>
<row>
<entry><literal>assert 1 + 1 == 2; "yes!"</literal>
</entry>
<entry>Assertion check (evaluates to <literal>"yes!"</literal>). See <xref
linkend="sec-assertions"/> for using assertions in modules</entry>
</row>
<row>
<entry><literal>let x = "foo"; y = "bar"; in x + y</literal>
</entry>
<entry>Variable definition</entry>
</row>
<row>
<entry><literal>with pkgs.lib; head [ 1 2 3 ]</literal>
</entry>
<entry>Add all attributes from the given set to the scope
(evaluates to <literal>1</literal>)</entry>
</row>
<row>
<entry namest="c1" nameend="c2"><emphasis>Functions (lambdas)</emphasis>
</entry>
</row>
<row>
<entry><literal>x: x + 1</literal>
</entry>
<entry>A function that expects an integer and returns it increased by 1</entry>
</row>
<row>
<entry><literal>(x: x + 1) 100</literal>
</entry>
<entry>A function call (evaluates to 101)</entry>
</row>
<row>
<entry><literal>let inc = x: x + 1; in inc (inc (inc 100))</literal>
</entry>
<entry>A function bound to a variable and subsequently called by name (evaluates to 103)</entry>
</row>
<row>
<entry><literal>{ x, y }: x + y</literal>
</entry>
<entry>A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal> and concatenates
them</entry>
</row>
<row>
<entry><literal>{ x, y ? "bar" }: x + y</literal>
</entry>
<entry>A function that expects a set with required attribute
<literal>x</literal> and optional <literal>y</literal>, using
<literal>"bar"</literal> as default value for
<literal>y</literal>
</entry>
</row>
<row>
<entry><literal>{ x, y, ... }: x + y</literal>
</entry>
<entry>A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal> and ignores any
other attributes</entry>
</row>
<row>
<entry><literal>{ x, y } @ args: x + y</literal>
</entry>
<entry>A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal>, and binds the
whole set to <literal>args</literal>
</entry>
</row>
<row>
<entry namest="c1" nameend="c2"><emphasis>Built-in functions</emphasis>
</entry>
</row>
<row>
<entry><literal>import ./foo.nix</literal>
</entry>
<entry>Load and return Nix expression in given file</entry>
</row>
<row>
<entry><literal>map (x: x + x) [ 1 2 3 ]</literal>
</entry>
<entry>Apply a function to every element of a list (evaluates to <literal>[ 2 4 6 ]</literal>)</entry>
</row>
<!--
<row>
<entry><literal>throw "Urgh"</literal></entry>
<entry>Raise an error condition</entry>
</row>
-->
</tbody>
</tgroup>
</informaltable>
</section>

View file

@ -0,0 +1,231 @@
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-configuration-file">
<title>NixOS Configuration File</title>
<para>
The NixOS configuration file generally looks like this:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ option definitions
}
</programlisting>
<para>
The first line (<literal>{ config, pkgs, ... }:</literal>) denotes
that this is actually a function that takes at least the two
arguments <literal>config</literal> and <literal>pkgs</literal>.
(These are explained later, in chapter
<xref linkend="sec-writing-modules" />) The function returns a
<emphasis>set</emphasis> of option definitions
(<literal>{ ... }</literal>). These definitions have the form
<literal>name = value</literal>, where <literal>name</literal> is
the name of an option and <literal>value</literal> is its value. For
example,
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ services.httpd.enable = true;
services.httpd.adminAddr = &quot;alice@example.org&quot;;
services.httpd.virtualHosts.localhost.documentRoot = &quot;/webroot&quot;;
}
</programlisting>
<para>
defines a configuration with three option definitions that together
enable the Apache HTTP Server with <literal>/webroot</literal> as
the document root.
</para>
<para>
Sets can be nested, and in fact dots in option names are shorthand
for defining a set containing another set. For instance,
<xref linkend="opt-services.httpd.enable" /> defines a set named
<literal>services</literal> that contains a set named
<literal>httpd</literal>, which in turn contains an option
definition named <literal>enable</literal> with value
<literal>true</literal>. This means that the example above can also
be written as:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ services = {
httpd = {
enable = true;
adminAddr = &quot;alice@example.org&quot;;
virtualHosts = {
localhost = {
documentRoot = &quot;/webroot&quot;;
};
};
};
};
}
</programlisting>
<para>
which may be more convenient if you have lots of option definitions
that share the same prefix (such as
<literal>services.httpd</literal>).
</para>
<para>
NixOS checks your option definitions for correctness. For instance,
if you try to define an option that doesnt exist (that is, doesnt
have a corresponding <emphasis>option declaration</emphasis>),
<literal>nixos-rebuild</literal> will give an error like:
</para>
<programlisting>
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
</programlisting>
<para>
Likewise, values in option definitions must have a correct type. For
instance, <literal>services.httpd.enable</literal> must be a Boolean
(<literal>true</literal> or <literal>false</literal>). Trying to
give it a value of another type, such as a string, will cause an
error:
</para>
<programlisting>
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
</programlisting>
<para>
Options have various types of values. The most important are:
</para>
<variablelist>
<varlistentry>
<term>
Strings
</term>
<listitem>
<para>
Strings are enclosed in double quotes, e.g.
</para>
<programlisting language="bash">
networking.hostName = &quot;dexter&quot;;
</programlisting>
<para>
Special characters can be escaped by prefixing them with a
backslash (e.g. <literal>\&quot;</literal>).
</para>
<para>
Multi-line strings can be enclosed in <emphasis>double single
quotes</emphasis>, e.g.
</para>
<programlisting language="bash">
networking.extraHosts =
''
127.0.0.2 other-localhost
10.0.0.1 server
'';
</programlisting>
<para>
The main difference is that it strips from each line a number
of spaces equal to the minimal indentation of the string as a
whole (disregarding the indentation of empty lines), and that
characters like <literal>&quot;</literal> and
<literal>\</literal> are not special (making it more
convenient for including things like shell code). See more
info about this in the Nix manual
<link xlink:href="https://nixos.org/nix/manual/#ssec-values">here</link>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Booleans
</term>
<listitem>
<para>
These can be <literal>true</literal> or
<literal>false</literal>, e.g.
</para>
<programlisting language="bash">
networking.firewall.enable = true;
networking.firewall.allowPing = false;
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
Integers
</term>
<listitem>
<para>
For example,
</para>
<programlisting language="bash">
boot.kernel.sysctl.&quot;net.ipv4.tcp_keepalive_time&quot; = 60;
</programlisting>
<para>
(Note that here the attribute name
<literal>net.ipv4.tcp_keepalive_time</literal> is enclosed in
quotes to prevent it from being interpreted as a set named
<literal>net</literal> containing a set named
<literal>ipv4</literal>, and so on. This is because its not a
NixOS option but the literal name of a Linux kernel setting.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
Sets
</term>
<listitem>
<para>
Sets were introduced above. They are name/value pairs enclosed
in braces, as in the option definition
</para>
<programlisting language="bash">
fileSystems.&quot;/boot&quot; =
{ device = &quot;/dev/sda1&quot;;
fsType = &quot;ext4&quot;;
options = [ &quot;rw&quot; &quot;data=ordered&quot; &quot;relatime&quot; ];
};
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
Lists
</term>
<listitem>
<para>
The important thing to note about lists is that list elements
are separated by whitespace, like this:
</para>
<programlisting language="bash">
boot.kernelModules = [ &quot;fuse&quot; &quot;kvm-intel&quot; &quot;coretemp&quot; ];
</programlisting>
<para>
List elements can be any other type, e.g. sets:
</para>
<programlisting language="bash">
swapDevices = [ { device = &quot;/dev/disk/by-label/swap&quot;; } ];
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
Packages
</term>
<listitem>
<para>
Usually, the packages you need are already part of the Nix
Packages collection, which is a set that can be accessed
through the function argument <literal>pkgs</literal>. Typical
uses:
</para>
<programlisting language="bash">
environment.systemPackages =
[ pkgs.thunderbird
pkgs.emacs
];
services.postgresql.package = pkgs.postgresql_10;
</programlisting>
<para>
The latter option definition changes the default PostgreSQL
package used by NixOSs PostgreSQL service to 10.x. For more
information on packages, including how to add new ones, see
<xref linkend="sec-custom-packages" />.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>

View file

@ -0,0 +1,152 @@
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-modularity">
<title>Modularity</title>
<para>
The NixOS configuration mechanism is modular. If your
<literal>configuration.nix</literal> becomes too big, you can split
it into multiple files. Likewise, if you have multiple NixOS
configurations (e.g. for different computers) with some commonality,
you can move the common configuration into a shared file.
</para>
<para>
Modules have exactly the same syntax as
<literal>configuration.nix</literal>. In fact,
<literal>configuration.nix</literal> is itself a module. You can use
other modules by including them from
<literal>configuration.nix</literal>, e.g.:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ imports = [ ./vpn.nix ./kde.nix ];
services.httpd.enable = true;
environment.systemPackages = [ pkgs.emacs ];
...
}
</programlisting>
<para>
Here, we include two modules from the same directory,
<literal>vpn.nix</literal> and <literal>kde.nix</literal>. The
latter might look like this:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ services.xserver.enable = true;
services.xserver.displayManager.sddm.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
environment.systemPackages = [ pkgs.vim ];
}
</programlisting>
<para>
Note that both <literal>configuration.nix</literal> and
<literal>kde.nix</literal> define the option
<xref linkend="opt-environment.systemPackages" />. When multiple
modules define an option, NixOS will try to
<emphasis>merge</emphasis> the definitions. In the case of
<xref linkend="opt-environment.systemPackages" />, thats easy: the
lists of packages can simply be concatenated. The value in
<literal>configuration.nix</literal> is merged last, so for
list-type options, it will appear at the end of the merged list. If
you want it to appear first, you can use
<literal>mkBefore</literal>:
</para>
<programlisting language="bash">
boot.kernelModules = mkBefore [ &quot;kvm-intel&quot; ];
</programlisting>
<para>
This causes the <literal>kvm-intel</literal> kernel module to be
loaded before any other kernel modules.
</para>
<para>
For other types of options, a merge may not be possible. For
instance, if two modules define
<xref linkend="opt-services.httpd.adminAddr" />,
<literal>nixos-rebuild</literal> will give an error:
</para>
<programlisting>
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
</programlisting>
<para>
When that happens, its possible to force one definition take
precedence over the others:
</para>
<programlisting language="bash">
services.httpd.adminAddr = pkgs.lib.mkForce &quot;bob@example.org&quot;;
</programlisting>
<para>
When using multiple modules, you may need to access configuration
values defined in other modules. This is what the
<literal>config</literal> function argument is for: it contains the
complete, merged system configuration. That is,
<literal>config</literal> is the result of combining the
configurations returned by every module <footnote>
<para>
If youre wondering how its possible that the (indirect)
<emphasis>result</emphasis> of a function is passed as an
<emphasis>input</emphasis> to that same function: thats because
Nix is a <quote>lazy</quote> language — it only computes values
when they are needed. This works as long as no individual
configuration value depends on itself.
</para>
</footnote> . For example, here is a module that adds some packages
to <xref linkend="opt-environment.systemPackages" /> only if
<xref linkend="opt-services.xserver.enable" /> is set to
<literal>true</literal> somewhere else:
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
{ environment.systemPackages =
if config.services.xserver.enable then
[ pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
</programlisting>
<para>
With multiple modules, it may not be obvious what the final value of
a configuration option is. The command
<literal>nixos-option</literal> allows you to find out:
</para>
<programlisting>
$ nixos-option services.xserver.enable
true
$ nixos-option boot.kernelModules
[ &quot;tun&quot; &quot;ipv6&quot; &quot;loop&quot; ... ]
</programlisting>
<para>
Interactive exploration of the configuration is possible using
<literal>nix repl</literal>, a read-eval-print loop for Nix
expressions. A typical use:
</para>
<programlisting>
$ nix repl '&lt;nixpkgs/nixos&gt;'
nix-repl&gt; config.networking.hostName
&quot;mandark&quot;
nix-repl&gt; map (x: x.hostName) config.services.httpd.virtualHosts
[ &quot;example.org&quot; &quot;example.gov&quot; ]
</programlisting>
<para>
While abstracting your configuration, you may find it useful to
generate modules using code, instead of writing files. The example
below would have the same effect as importing a file which sets
those options.
</para>
<programlisting language="bash">
{ config, pkgs, ... }:
let netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{ imports = [ (netConfig &quot;nixos.localdomain&quot;) ]; }
</programlisting>
</section>

View file

@ -0,0 +1,332 @@
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-nix-syntax-summary">
<title>Syntax Summary</title>
<para>
Below is a summary of the most important syntactic constructs in the
Nix expression language. Its not complete. In particular, there are
many other built-in functions. See the
<link xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix
manual</link> for the rest.
</para>
<informaltable>
<tgroup cols="2">
<colspec align="left" />
<colspec align="left" />
<thead>
<row>
<entry>
Example
</entry>
<entry>
Description
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<emphasis>Basic values</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>&quot;Hello world&quot;</literal>
</entry>
<entry>
A string
</entry>
</row>
<row>
<entry>
<literal>&quot;${pkgs.bash}/bin/sh&quot;</literal>
</entry>
<entry>
A string containing an expression (expands to
<literal>&quot;/nix/store/hash-bash-version/bin/sh&quot;</literal>)
</entry>
</row>
<row>
<entry>
<literal>true</literal>, <literal>false</literal>
</entry>
<entry>
Booleans
</entry>
</row>
<row>
<entry>
<literal>123</literal>
</entry>
<entry>
An integer
</entry>
</row>
<row>
<entry>
<literal>./foo.png</literal>
</entry>
<entry>
A path (relative to the containing Nix expression)
</entry>
</row>
<row>
<entry>
<emphasis>Compound values</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>{ x = 1; y = 2; }</literal>
</entry>
<entry>
A set with attributes named <literal>x</literal> and
<literal>y</literal>
</entry>
</row>
<row>
<entry>
<literal>{ foo.bar = 1; }</literal>
</entry>
<entry>
A nested set, equivalent to
<literal>{ foo = { bar = 1; }; }</literal>
</entry>
</row>
<row>
<entry>
<literal>rec { x = &quot;foo&quot;; y = x + &quot;bar&quot;; }</literal>
</entry>
<entry>
A recursive set, equivalent to
<literal>{ x = &quot;foo&quot;; y = &quot;foobar&quot;; }</literal>
</entry>
</row>
<row>
<entry>
<literal>[ &quot;foo&quot; &quot;bar&quot; ]</literal>
</entry>
<entry>
A list with two elements
</entry>
</row>
<row>
<entry>
<emphasis>Operators</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>&quot;foo&quot; + &quot;bar&quot;</literal>
</entry>
<entry>
String concatenation
</entry>
</row>
<row>
<entry>
<literal>1 + 2</literal>
</entry>
<entry>
Integer addition
</entry>
</row>
<row>
<entry>
<literal>&quot;foo&quot; == &quot;f&quot; + &quot;oo&quot;</literal>
</entry>
<entry>
Equality test (evaluates to <literal>true</literal>)
</entry>
</row>
<row>
<entry>
<literal>&quot;foo&quot; != &quot;bar&quot;</literal>
</entry>
<entry>
Inequality test (evaluates to <literal>true</literal>)
</entry>
</row>
<row>
<entry>
<literal>!true</literal>
</entry>
<entry>
Boolean negation
</entry>
</row>
<row>
<entry>
<literal>{ x = 1; y = 2; }.x</literal>
</entry>
<entry>
Attribute selection (evaluates to <literal>1</literal>)
</entry>
</row>
<row>
<entry>
<literal>{ x = 1; y = 2; }.z or 3</literal>
</entry>
<entry>
Attribute selection with default (evaluates to
<literal>3</literal>)
</entry>
</row>
<row>
<entry>
<literal>{ x = 1; y = 2; } // { z = 3; }</literal>
</entry>
<entry>
Merge two sets (attributes in the right-hand set taking
precedence)
</entry>
</row>
<row>
<entry>
<emphasis>Control structures</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>if 1 + 1 == 2 then &quot;yes!&quot; else &quot;no!&quot;</literal>
</entry>
<entry>
Conditional expression
</entry>
</row>
<row>
<entry>
<literal>assert 1 + 1 == 2; &quot;yes!&quot;</literal>
</entry>
<entry>
Assertion check (evaluates to
<literal>&quot;yes!&quot;</literal>). See
<xref linkend="sec-assertions" /> for using assertions in
modules
</entry>
</row>
<row>
<entry>
<literal>let x = &quot;foo&quot;; y = &quot;bar&quot;; in x + y</literal>
</entry>
<entry>
Variable definition
</entry>
</row>
<row>
<entry>
<literal>with pkgs.lib; head [ 1 2 3 ]</literal>
</entry>
<entry>
Add all attributes from the given set to the scope
(evaluates to <literal>1</literal>)
</entry>
</row>
<row>
<entry>
<emphasis>Functions (lambdas)</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>x: x + 1</literal>
</entry>
<entry>
A function that expects an integer and returns it increased
by 1
</entry>
</row>
<row>
<entry>
<literal>(x: x + 1) 100</literal>
</entry>
<entry>
A function call (evaluates to 101)
</entry>
</row>
<row>
<entry>
<literal>let inc = x: x + 1; in inc (inc (inc 100))</literal>
</entry>
<entry>
A function bound to a variable and subsequently called by
name (evaluates to 103)
</entry>
</row>
<row>
<entry>
<literal>{ x, y }: x + y</literal>
</entry>
<entry>
A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal> and
concatenates them
</entry>
</row>
<row>
<entry>
<literal>{ x, y ? &quot;bar&quot; }: x + y</literal>
</entry>
<entry>
A function that expects a set with required attribute
<literal>x</literal> and optional <literal>y</literal>,
using <literal>&quot;bar&quot;</literal> as default value
for <literal>y</literal>
</entry>
</row>
<row>
<entry>
<literal>{ x, y, ... }: x + y</literal>
</entry>
<entry>
A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal> and ignores
any other attributes
</entry>
</row>
<row>
<entry>
<literal>{ x, y } @ args: x + y</literal>
</entry>
<entry>
A function that expects a set with required attributes
<literal>x</literal> and <literal>y</literal>, and binds the
whole set to <literal>args</literal>
</entry>
</row>
<row>
<entry>
<emphasis>Built-in functions</emphasis>
</entry>
<entry>
</entry>
</row>
<row>
<entry>
<literal>import ./foo.nix</literal>
</entry>
<entry>
Load and return Nix expression in given file
</entry>
</row>
<row>
<entry>
<literal>map (x: x + x) [ 1 2 3 ]</literal>
</entry>
<entry>
Apply a function to every element of a list (evaluates to
<literal>[ 2 4 6 ]</literal>)
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>