1526 lines
48 KiB
XML
1526 lines
48 KiB
XML
<chapter xmlns="http://docbook.org/ns/docbook"
|
||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||
xml:id="ch-configuration">
|
||
|
||
<title>Configuring NixOS</title>
|
||
|
||
<para>This chapter describes how to configure various aspects of a
|
||
NixOS machine through the configuration file
|
||
<filename>/etc/nixos/configuration.nix</filename>. As described in
|
||
<xref linkend="sec-changing-config" />, changes to this file only take
|
||
effect after you run <command>nixos-rebuild</command>.</para>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section xml:id="sec-configuration-syntax"><title>Configuration syntax</title>
|
||
|
||
<section><title>The basics</title>
|
||
|
||
<para>The NixOS configuration file
|
||
<filename>/etc/nixos/configuration.nix</filename> is actually a
|
||
<emphasis>Nix expression</emphasis>, which is the Nix package
|
||
manager’s purely functional language for describing how to build
|
||
packages and configurations. This means you have all the expressive
|
||
power of that language at your disposal, including the ability to
|
||
abstract over common patterns, which is very useful when managing
|
||
complex systems. The syntax and semantics of the Nix language are
|
||
fully described in the <link
|
||
xlink:href="http://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>
|
||
|
||
<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.) 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, ... }:
|
||
|
||
{ services.httpd.enable = true;
|
||
services.httpd.adminAddr = "alice@example.org";
|
||
services.httpd.documentRoot = "/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,
|
||
<option>services.httpd.enable</option> 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";
|
||
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 doesn’t exist (that is,
|
||
doesn’t have a corresponding <emphasis>option declaration</emphasis>),
|
||
<command>nixos-rebuild</command> will give an error like:
|
||
<screen>
|
||
The option `services.httpd.enabl' 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>
|
||
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>
|
||
networking.extraHosts =
|
||
''
|
||
127.0.0.2 other-localhost
|
||
10.0.0.1 server
|
||
'';
|
||
</programlisting>
|
||
|
||
The main difference is that preceding whitespace is
|
||
automatically stripped from each line, and that characters like
|
||
<literal>"</literal> and <literal>\</literal> are not special
|
||
(making it more convenient for including things like shell
|
||
code).</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Booleans</term>
|
||
<listitem>
|
||
<para>These can be <literal>true</literal> or
|
||
<literal>false</literal>, e.g.
|
||
|
||
<programlisting>
|
||
networking.firewall.enable = true;
|
||
networking.firewall.allowPing = false;
|
||
</programlisting>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
<varlistentry>
|
||
<term>Integers</term>
|
||
<listitem>
|
||
<para>For example,
|
||
|
||
<programlisting>
|
||
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 it’s 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>
|
||
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>
|
||
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>
|
||
environment.systemPackages =
|
||
[ pkgs.thunderbird
|
||
pkgs.emacs
|
||
];
|
||
|
||
postgresql.package = pkgs.postgresql90;
|
||
</programlisting>
|
||
|
||
The latter option definition changes the default PostgreSQL
|
||
package used by NixOS’s PostgreSQL service to 9.0. For more
|
||
information on packages, including how to add new ones, see
|
||
<xref linkend="sec-custom-packages"/>.</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
|
||
</variablelist>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Abstractions</title>
|
||
|
||
<para>If you find yourself repeating yourself over and over, it’s time
|
||
to abstract. Take, for instance, this Apache HTTP Server configuration:
|
||
|
||
<programlisting>
|
||
{
|
||
services.httpd.virtualHosts =
|
||
[ { hostName = "example.org";
|
||
documentRoot = "/webroot";
|
||
adminAddr = "alice@example.org";
|
||
enableUserDir = true;
|
||
}
|
||
{ hostName = "example.org";
|
||
documentRoot = "/webroot";
|
||
adminAddr = "alice@example.org";
|
||
enableUserDir = true;
|
||
enableSSL = true;
|
||
sslServerCert = "/root/ssl-example-org.crt";
|
||
sslServerKey = "/root/ssl-example-org.key";
|
||
}
|
||
];
|
||
}
|
||
</programlisting>
|
||
|
||
It defines two virtual hosts with nearly identical configuration; the
|
||
only difference is that the second one has SSL enabled. To prevent
|
||
this duplication, we can use a <literal>let</literal>:
|
||
|
||
<programlisting>
|
||
let
|
||
exampleOrgCommon =
|
||
{ hostName = "example.org";
|
||
documentRoot = "/webroot";
|
||
adminAddr = "alice@example.org";
|
||
enableUserDir = true;
|
||
};
|
||
in
|
||
{
|
||
services.httpd.virtualHosts =
|
||
[ exampleOrgCommon
|
||
(exampleOrgCommon // {
|
||
enableSSL = true;
|
||
sslServerCert = "/root/ssl-example-org.crt";
|
||
sslServerKey = "/root/ssl-example-org.key";
|
||
})
|
||
];
|
||
}
|
||
</programlisting>
|
||
|
||
The <literal>let exampleOrgCommon =
|
||
<replaceable>...</replaceable></literal> defines a variable named
|
||
<literal>exampleOrgCommon</literal>. The <literal>//</literal>
|
||
operator merges two attribute sets, so the configuration of the second
|
||
virtual host is the set <literal>exampleOrgCommon</literal> extended
|
||
with the SSL options.</para>
|
||
|
||
<para>You can write a <literal>let</literal> wherever an expression is
|
||
allowed. Thus, you also could have written:
|
||
|
||
<programlisting>
|
||
{
|
||
services.httpd.virtualHosts =
|
||
let exampleOrgCommon = <replaceable>...</replaceable>; in
|
||
[ exampleOrgCommon
|
||
(exampleOrgCommon // { <replaceable>...</replaceable> })
|
||
];
|
||
}
|
||
</programlisting>
|
||
|
||
but not <literal>{ let exampleOrgCommon =
|
||
<replaceable>...</replaceable>; in <replaceable>...</replaceable>;
|
||
}</literal> since attributes (as opposed to attribute values) are not
|
||
expressions.</para>
|
||
|
||
<para><emphasis>Functions</emphasis> provide another method of
|
||
abstraction. For instance, suppose that we want to generate lots of
|
||
different virtual hosts, all with identical configuration except for
|
||
the host name. This can be done as follows:
|
||
|
||
<programlisting>
|
||
{
|
||
services.httpd.virtualHosts =
|
||
let
|
||
makeVirtualHost = name:
|
||
{ hostName = name;
|
||
documentRoot = "/webroot";
|
||
adminAddr = "alice@example.org";
|
||
};
|
||
in
|
||
[ (makeVirtualHost "example.org")
|
||
(makeVirtualHost "example.com")
|
||
(makeVirtualHost "example.gov")
|
||
(makeVirtualHost "example.nl")
|
||
];
|
||
}
|
||
</programlisting>
|
||
|
||
Here, <varname>makeVirtualHost</varname> is a function that takes a
|
||
single argument <literal>name</literal> and returns the configuration
|
||
for a virtual host. That function is then called for several names to
|
||
produce the list of virtual host configurations.</para>
|
||
|
||
<para>We can further improve on this by using the function
|
||
<varname>map</varname>, which applies another function to every
|
||
element in a list:
|
||
|
||
<programlisting>
|
||
{
|
||
services.httpd.virtualHosts =
|
||
let
|
||
makeVirtualHost = <replaceable>...</replaceable>;
|
||
in map makeVirtualHost
|
||
[ "example.org" "example.com" "example.gov" "example.nl" ];
|
||
}
|
||
</programlisting>
|
||
|
||
(The function <literal>map</literal> is called a
|
||
<emphasis>higher-order function</emphasis> because it takes another
|
||
function as an argument.)</para>
|
||
|
||
<para>What if you need more than one argument, for instance, if we
|
||
want to use a different <literal>documentRoot</literal> for each
|
||
virtual host? Then we can make <varname>makeVirtualHost</varname> a
|
||
function that takes a <emphasis>set</emphasis> as its argument, like this:
|
||
|
||
<programlisting>
|
||
{
|
||
services.httpd.virtualHosts =
|
||
let
|
||
makeVirtualHost = { name, root }:
|
||
{ hostName = name;
|
||
documentRoot = root;
|
||
adminAddr = "alice@example.org";
|
||
};
|
||
in map makeVirtualHost
|
||
[ { name = "example.org"; root = "/sites/example.org"; }
|
||
{ name = "example.com"; root = "/sites/example.com"; }
|
||
{ name = "example.gov"; root = "/sites/example.gov"; }
|
||
{ name = "example.nl"; root = "/sites/example.nl"; }
|
||
];
|
||
}
|
||
</programlisting>
|
||
|
||
But in this case (where every root is a subdirectory of
|
||
<filename>/sites</filename> named after the virtual host), it would
|
||
have been shorter to define <varname>makeVirtualHost</varname> as
|
||
<programlisting>
|
||
makeVirtualHost = name:
|
||
{ hostName = name;
|
||
documentRoot = "/sites/${name}";
|
||
adminAddr = "alice@example.org";
|
||
};
|
||
</programlisting>
|
||
|
||
Here, the construct
|
||
<literal>${<replaceable>...</replaceable>}</literal> allows the result
|
||
of an expression to be spliced into a string.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><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 ];
|
||
services.httpd.enable = true;
|
||
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, ... }:
|
||
|
||
{ services.xserver.enable = true;
|
||
services.xserver.displayManager.kdm.enable = true;
|
||
services.xserver.desktopManager.kde4.enable = true;
|
||
environment.systemPackages = [ pkgs.kde4.kscreensaver ];
|
||
}
|
||
</programlisting>
|
||
|
||
Note that both <filename>configuration.nix</filename> and
|
||
<filename>kde.nix</filename> define the option
|
||
<option>environment.systemPackages</option>. When multiple modules
|
||
define an option, NixOS will try to <emphasis>merge</emphasis> the
|
||
definitions. In the case of
|
||
<option>environment.systemPackages</option>, that’s 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>
|
||
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
|
||
<option>services.httpd.adminAddr</option>,
|
||
<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, it’s possible to force one definition take
|
||
precedence over the others:
|
||
|
||
<programlisting>
|
||
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><para>If you’re
|
||
wondering how it’s possible that the (indirect)
|
||
<emphasis>result</emphasis> of a function is passed as an
|
||
<emphasis>input</emphasis> 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.</para></footnote>. For example, here is a module that adds
|
||
some packages to <option>environment.systemPackages</option> only if
|
||
<option>services.xserver.enable</option> is set to
|
||
<literal>true</literal> somewhere else:
|
||
|
||
<programlisting>
|
||
{ config, pkgs, ... }:
|
||
|
||
{ environment.systemPackages =
|
||
if config.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>
|
||
$ nixos-option services.xserver.enable
|
||
true
|
||
|
||
$ nixos-option boot.kernelModules
|
||
[ "tun" "ipv6" "loop" <replaceable>...</replaceable> ]
|
||
</screen>
|
||
|
||
Interactive exploration of the configuration is possible using
|
||
<command
|
||
xlink:href="https://github.com/edolstra/nix-repl">nix-repl</command>,
|
||
a read-eval-print loop for Nix expressions. It’s not installed by
|
||
default; run <literal>nix-env -i nix-repl</literal> to get it. A
|
||
typical use:
|
||
|
||
<screen>
|
||
$ nix-repl '<nixos>'
|
||
|
||
nix-repl> config.networking.hostName
|
||
"mandark"
|
||
|
||
nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
|
||
[ "example.org" "example.gov" ]
|
||
</screen>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Syntax summary</title>
|
||
|
||
<para>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 <link
|
||
xlink:href="http://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>An set with attributes names <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 = "bla"; 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>)</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>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section><title>Package management</title>
|
||
|
||
<para>This section describes how to add additional packages to your
|
||
system. NixOS has two distinct styles of package management:
|
||
|
||
<itemizedlist>
|
||
|
||
<listitem><para><emphasis>Declarative</emphasis>, where you declare
|
||
what packages you want in your
|
||
<filename>configuration.nix</filename>. Every time you run
|
||
<command>nixos-rebuild</command>, NixOS will ensure that you get a
|
||
consistent set of binaries corresponding to your
|
||
specification.</para></listitem>
|
||
|
||
<listitem><para><emphasis>Ad hoc</emphasis>, where you install,
|
||
upgrade and uninstall packages via the <command>nix-env</command>
|
||
command. This style allows mixing packages from different Nixpkgs
|
||
versions. It’s the only choice for non-root
|
||
users.</para></listitem>
|
||
|
||
</itemizedlist>
|
||
|
||
</para>
|
||
|
||
<para>The next two sections describe these two styles.</para>
|
||
|
||
|
||
<section><title>Declarative package management</title>
|
||
|
||
<para>With declarative package management, you specify which packages
|
||
you want on your system by setting the option
|
||
<option>environment.systemPackages</option>. For instance, adding the
|
||
following line to <filename>configuration.nix</filename> enables the
|
||
Mozilla Thunderbird email application:
|
||
|
||
<programlisting>
|
||
environment.systemPackages = [ pkgs.thunderbird ];
|
||
</programlisting>
|
||
|
||
The effect of this specification is that the Thunderbird package from
|
||
Nixpkgs will be built or downloaded as part of the system when you run
|
||
<command>nixos-rebuild switch</command>.</para>
|
||
|
||
<para>You can get a list of the available packages as follows:
|
||
<screen>
|
||
$ nix-env -qaP '*' --description
|
||
nixos.pkgs.firefox firefox-23.0 Mozilla Firefox - the browser, reloaded
|
||
<replaceable>...</replaceable>
|
||
</screen>
|
||
|
||
The first column in the output is the <emphasis>attribute
|
||
name</emphasis>, such as
|
||
<literal>nixos.pkgs.thunderbird</literal>. (The
|
||
<literal>nixos</literal> prefix allows distinguishing between
|
||
different channels that you might have.)</para>
|
||
|
||
<para>To “uninstall” a package, simply remove it from
|
||
<option>environment.systemPackages</option> and run
|
||
<command>nixos-rebuild switch</command>.</para>
|
||
|
||
|
||
<section xml:id="sec-customising-packages"><title>Customising packages</title>
|
||
|
||
<para>Some packages in Nixpkgs have options to enable or disable
|
||
optional functionality or change other aspects of the package. For
|
||
instance, the Firefox wrapper package (which provides Firefox with a
|
||
set of plugins such as the Adobe Flash player) has an option to enable
|
||
the Google Talk plugin. It can be set in
|
||
<filename>configuration.nix</filename> as follows:
|
||
|
||
<filename>
|
||
nixpkgs.config.firefox.enableGoogleTalkPlugin = true;
|
||
</filename>
|
||
</para>
|
||
|
||
<warning><para>Unfortunately, Nixpkgs currently lacks a way to query
|
||
available configuration options.</para></warning>
|
||
|
||
<para>Apart from high-level options, it’s possible to tweak a package
|
||
in almost arbitrary ways, such as changing or disabling dependencies
|
||
of a package. For instance, the Emacs package in Nixpkgs by default
|
||
has a dependency on GTK+ 2. If you want to build it against GTK+ 3,
|
||
you can specify that as follows:
|
||
|
||
<programlisting>
|
||
environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];
|
||
</programlisting>
|
||
|
||
The function <varname>override</varname> performs the call to the Nix
|
||
function that produces Emacs, with the original arguments amended by
|
||
the set of arguments specified by you. So here the function argument
|
||
<varname>gtk</varname> gets the value <literal>pkgs.gtk3</literal>,
|
||
causing Emacs to depend on GTK+ 3. (The parentheses are necessary
|
||
because in Nix, function application binds more weakly than list
|
||
construction, so without them,
|
||
<literal>environment.systemPackages</literal> would be a list with two
|
||
elements.)</para>
|
||
|
||
<para>Even greater customisation is possible using the function
|
||
<varname>overrideDerivation</varname>. While the
|
||
<varname>override</varname> mechanism above overrides the arguments of
|
||
a package function, <varname>overrideDerivation</varname> allows
|
||
changing the <emphasis>result</emphasis> of the function. This
|
||
permits changing any aspect of the package, such as the source code.
|
||
For instance, if you want to override the source code of Emacs, you
|
||
can say:
|
||
|
||
<programlisting>
|
||
environment.systemPackages =
|
||
[ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: {
|
||
name = "emacs-25.0-pre";
|
||
src = /path/to/my/emacs/tree;
|
||
}))
|
||
];
|
||
</programlisting>
|
||
|
||
Here, <varname>overrideDerivation</varname> takes the Nix derivation
|
||
specified by <varname>pkgs.emacs</varname> and produces a new
|
||
derivation in which the original’s <literal>name</literal> and
|
||
<literal>src</literal> attribute have been replaced by the given
|
||
values. The original attributes are accessible via
|
||
<varname>attrs</varname>.</para>
|
||
|
||
<para>The overrides shown above are not global. They do not affect
|
||
the original package; other packages in Nixpkgs continue to depend on
|
||
the original rather than the customised package. This means that if
|
||
another package in your system depends on the original package, you
|
||
end up with two instances of the package. If you want to have
|
||
everything depend on your customised instance, you can apply a
|
||
<emphasis>global</emphasis> override as follows:
|
||
|
||
<screen>
|
||
nixpkgs.config.packageOverrides = pkgs:
|
||
{ emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
|
||
};
|
||
</screen>
|
||
|
||
The effect of this definition is essentially equivalent to modifying
|
||
the <literal>emacs</literal> attribute in the Nixpkgs source tree.
|
||
Any package in Nixpkgs that depends on <literal>emacs</literal> will
|
||
be passed your customised instance. (However, the value
|
||
<literal>pkgs.emacs</literal> in
|
||
<varname>nixpkgs.config.packageOverrides</varname> refers to the
|
||
original rather than overriden instance, to prevent an infinite
|
||
recursion.)</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="sec-custom-packages"><title>Adding custom packages</title>
|
||
|
||
<para>It’s possible that a package you need is not available in NixOS.
|
||
In that case, you can do two things. First, you can clone the Nixpkgs
|
||
repository, add the package to your clone, and (optionally) submit a
|
||
patch or pull request to have it accepted into the main Nixpkgs
|
||
repository. This is described in detail in the <link
|
||
xlink:href="http://nixos.org/nixpkgs/manual">Nixpkgs manual</link>.
|
||
In short, you clone Nixpkgs:
|
||
|
||
<screen>
|
||
$ git clone git://github.com/NixOS/nixpkgs.git
|
||
$ cd nixpkgs
|
||
</screen>
|
||
|
||
Then you write and test the package as described in the Nixpkgs
|
||
manual. Finally, you add it to
|
||
<literal>environment.systemPackages</literal>, e.g.
|
||
|
||
<programlisting>
|
||
environment.systemPackages = [ pkgs.my-package ];
|
||
</programlisting>
|
||
|
||
and you run <command>nixos-rebuild</command>, specifying your own
|
||
Nixpkgs tree:
|
||
|
||
<screen>
|
||
$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen>
|
||
|
||
</para>
|
||
|
||
<para>The second possibility is to add the package outside of the
|
||
Nixpkgs tree. For instance, here is how you specify a build of the
|
||
<link xlink:href="http://www.gnu.org/software/hello/">GNU Hello</link>
|
||
package directly in <filename>configuration.nix</filename>:
|
||
|
||
<programlisting>
|
||
environment.systemPackages =
|
||
let
|
||
my-hello = with pkgs; stdenv.mkDerivation rec {
|
||
name = "hello-2.8";
|
||
src = fetchurl {
|
||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
|
||
};
|
||
};
|
||
in
|
||
[ my-hello ];
|
||
</programlisting>
|
||
|
||
Of course, you can also move the definition of
|
||
<literal>my-hello</literal> into a separate Nix expression, e.g.
|
||
<programlisting>
|
||
environment.systemPackages = [ (import ./my-hello.nix) ];
|
||
</programlisting>
|
||
where <filename>my-hello.nix</filename> contains:
|
||
<programlisting>
|
||
with <nixpkgs> {}; # bring all of Nixpkgs into scope
|
||
|
||
stdenv.mkDerivation rec {
|
||
name = "hello-2.8";
|
||
src = fetchurl {
|
||
url = "mirror://gnu/hello/${name}.tar.gz";
|
||
sha256 = "0wqd8sjmxfskrflaxywc7gqw7sfawrfvdxd9skxawzfgyy0pzdz6";
|
||
};
|
||
}
|
||
</programlisting>
|
||
|
||
This allows testing the package easily:
|
||
<screen>
|
||
$ nix-build my-hello.nix
|
||
$ ./result/bin/hello
|
||
Hello, world!
|
||
</screen>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Ad hoc package management</title>
|
||
|
||
<para>With the command <command>nix-env</command>, you can install and
|
||
uninstall packages from the command line. For instance, to install
|
||
Mozilla Thunderbird:
|
||
|
||
<screen>
|
||
$ nix-env -iA nixos.pkgs.thunderbird</screen>
|
||
|
||
If you invoke this as root, the package is installed in the Nix
|
||
profile <filename>/nix/var/nix/profiles/default</filename> and visible
|
||
to all users of the system; otherwise, the package ends up in
|
||
<filename>/nix/var/nix/profiles/per-user/<replaceable>username</replaceable>/profile</filename>
|
||
and is not visible to other users. The <option>-A</option> flag
|
||
specifies the package by its attribute name; without it, the package
|
||
is installed by matching against its package name
|
||
(e.g. <literal>thunderbird</literal>). The latter is slower because
|
||
it requires matching against all available Nix packages, and is
|
||
ambiguous if there are multiple matching packages.</para>
|
||
|
||
<para>Packages come from the NixOS channel. You typically upgrade a
|
||
package by updating to the latest version of the NixOS channel:
|
||
<screen>
|
||
$ nix-channel --update nixos
|
||
</screen>
|
||
and then running <literal>nix-env -i</literal> again. Other packages
|
||
in the profile are <emphasis>not</emphasis> affected; this is the
|
||
crucial difference with the declarative style of package management,
|
||
where running <command>nixos-rebuild switch</command> causes all
|
||
packages to be updated to their current versions in the NixOS channel.
|
||
You can however upgrade all packages for which there is a newer
|
||
version by doing:
|
||
<screen>
|
||
$ nix-env -u '*'
|
||
</screen>
|
||
</para>
|
||
|
||
<para>A package can be uninstalled using the <option>-e</option>
|
||
flag:
|
||
<screen>
|
||
$ nix-env -e thunderbird
|
||
</screen>
|
||
</para>
|
||
|
||
<para>Finally, you can roll back an undesirable
|
||
<command>nix-env</command> action:
|
||
<screen>
|
||
$ nix-env --rollback
|
||
</screen>
|
||
</para>
|
||
|
||
<para><command>nix-env</command> has many more flags. For details,
|
||
see the
|
||
<citerefentry><refentrytitle>nix-env</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||
manpage or the Nix manual.</para>
|
||
|
||
</section>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section xml:id="sec-user-management"><title>User management</title>
|
||
|
||
<para>NixOS supports both declarative and imperative styles of user
|
||
management. In the declarative style, users are specified in
|
||
<filename>configuration.nix</filename>. For instance, the following
|
||
states that a user account named <literal>alice</literal> shall exist:
|
||
|
||
<programlisting>
|
||
users.extraUsers.alice =
|
||
{ createHome = true;
|
||
home = "/home/alice";
|
||
description = "Alice Foobar";
|
||
extraGroups = [ "wheel" ];
|
||
useDefaultShell = true;
|
||
openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
|
||
};
|
||
</programlisting>
|
||
|
||
Note that <literal>alice</literal> is a member of the
|
||
<literal>wheel</literal> group, which allows her to use
|
||
<command>sudo</command> to execute commands as
|
||
<literal>root</literal>. Also note the SSH public key that allows
|
||
remote logins with the corresponding private key. Users created in
|
||
this way do not have a password by default, so they cannot log in via
|
||
mechanisms that require a password. However, you can use the
|
||
<command>passwd</command> program to set a password, which is retained
|
||
across invocations of <command>nixos-rebuild</command>.</para>
|
||
|
||
<para>A user ID (uid) is assigned automatically. You can also specify
|
||
a uid manually by adding
|
||
|
||
<programlisting>
|
||
uid = 1000;
|
||
</programlisting>
|
||
|
||
to the user specification.</para>
|
||
|
||
<para>Groups can be specified similarly. The following states that a
|
||
group named <literal>students</literal> shall exist:
|
||
|
||
<programlisting>
|
||
users.extraGroups.students.gid = 1000;
|
||
</programlisting>
|
||
|
||
As with users, the group ID (gid) is optional and will be assigned
|
||
automatically if it’s missing.</para>
|
||
|
||
<warning><para>Currently declarative user management is not perfect:
|
||
<command>nixos-rebuild</command> does not know how to realise certain
|
||
configuration changes. This includes removing a user or group, and
|
||
removing group membership from a user.</para></warning>
|
||
|
||
<para>In the imperative style, users and groups are managed by
|
||
commands such as <command>useradd</command>,
|
||
<command>groupmod</command> and so on. For instance, to create a user
|
||
account named <literal>alice</literal>:
|
||
|
||
<screen>
|
||
$ useradd -m alice</screen>
|
||
|
||
The flag <option>-m</option> causes the creation of a home directory
|
||
for the new user, which is generally what you want. The user does not
|
||
have an initial password and therefore cannot log in. A password can
|
||
be set using the <command>passwd</command> utility:
|
||
|
||
<screen>
|
||
$ passwd alice
|
||
Enter new UNIX password: ***
|
||
Retype new UNIX password: ***
|
||
</screen>
|
||
|
||
A user can be deleted using <command>userdel</command>:
|
||
|
||
<screen>
|
||
$ userdel -r alice</screen>
|
||
|
||
The flag <option>-r</option> deletes the user’s home directory.
|
||
Accounts can be modified using <command>usermod</command>. Unix
|
||
groups can be managed using <command>groupadd</command>,
|
||
<command>groupmod</command> and <command>groupdel</command>.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section><title>File systems</title>
|
||
|
||
<para>You can define file systems using the
|
||
<option>fileSystems</option> configuration option. For instance, the
|
||
following definition causes NixOS to mount the Ext4 file system on
|
||
device <filename>/dev/disk/by-label/data</filename> onto the mount
|
||
point <filename>/data</filename>:
|
||
|
||
<programlisting>
|
||
fileSystems."/data" =
|
||
{ device = "/dev/disk/by-label/data";
|
||
fsType = "ext4";
|
||
};
|
||
</programlisting>
|
||
|
||
Mount points are created automatically if they don’t already exist.
|
||
For <option>device</option>, it’s best to use the topology-independent
|
||
device aliases in <filename>/dev/disk/by-label</filename> and
|
||
<filename>/dev/disk/by-uuid</filename>, as these don’t change if the
|
||
topology changes (e.g. if a disk is moved to another IDE
|
||
controller).</para>
|
||
|
||
<para>You can usually omit the file system type
|
||
(<option>fsType</option>), since <command>mount</command> can usually
|
||
detect the type and load the necessary kernel module automatically.
|
||
However, if the file system is needed at early boot (in the initial
|
||
ramdisk) and is not <literal>ext2</literal>, <literal>ext3</literal>
|
||
or <literal>ext4</literal>, then it’s best to specify
|
||
<option>fsType</option> to ensure that the kernel module is
|
||
available.</para>
|
||
|
||
<section><title>LUKS-encrypted file systems</title>
|
||
|
||
<para>NixOS supports file systems that are encrypted using
|
||
<emphasis>LUKS</emphasis> (Linux Unified Key Setup). For example,
|
||
here is how you create an encrypted Ext4 file system on the device
|
||
<filename>/dev/sda2</filename>:
|
||
|
||
<screen>
|
||
$ cryptsetup luksFormat /dev/sda2
|
||
|
||
WARNING!
|
||
========
|
||
This will overwrite data on /dev/sda2 irrevocably.
|
||
|
||
Are you sure? (Type uppercase yes): YES
|
||
Enter LUKS passphrase: ***
|
||
Verify passphrase: ***
|
||
|
||
$ cryptsetup luksOpen /dev/sda2 crypted
|
||
Enter passphrase for /dev/sda2: ***
|
||
|
||
$ mkfs.ext4 /dev/mapper/crypted
|
||
</screen>
|
||
|
||
To ensure that this file system is automatically mounted at boot time
|
||
as <filename>/</filename>, add the following to
|
||
<filename>configuration.nix</filename>:
|
||
|
||
<programlisting>
|
||
boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ];
|
||
fileSystems."/".device = "/dev/mapper/crypted";
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section><title>X Window System</title>
|
||
|
||
<para>The X Window System (X11) provides the basis of NixOS’ graphical
|
||
user interface. It can be enabled as follows:
|
||
<programlisting>
|
||
services.xserver.enable = true;
|
||
</programlisting>
|
||
The X server will automatically detect and use the appropriate video
|
||
driver from a set of X.org drivers (such as <literal>vesa</literal>
|
||
and <literal>intel</literal>). You can also specify a driver
|
||
manually, e.g.
|
||
<programlisting>
|
||
hardware.opengl.videoDrivers = [ "r128" ];
|
||
</programlisting>
|
||
to enable X.org’s <literal>xf86-video-r128</literal> driver.</para>
|
||
|
||
<para>You also need to enable at least one desktop or window manager.
|
||
Otherwise, you can only log into a plain undecorated
|
||
<command>xterm</command> window. Thus you should pick one or more of
|
||
the following lines:
|
||
<programlisting>
|
||
services.xserver.desktopManager.kde4.enable = true;
|
||
services.xserver.desktopManager.xfce.enable = true;
|
||
services.xserver.windowManager.xmonad.enable = true;
|
||
services.xserver.windowManager.twm.enable = true;
|
||
services.xserver.windowManager.icewm.enable = true;
|
||
</programlisting>
|
||
</para>
|
||
|
||
<para>NixOS’s default <emphasis>display manager</emphasis> (the
|
||
program that provides a graphical login prompt and manages the X
|
||
server) is SLiM. You can select KDE’s <command>kdm</command> instead:
|
||
<programlisting>
|
||
services.xserver.displayManager.kdm.enable = true;
|
||
</programlisting>
|
||
</para>
|
||
|
||
<para>The X server is started automatically at boot time. If you
|
||
don’t want this to happen, you can set:
|
||
<programlisting>
|
||
services.xserver.autorun = false;
|
||
</programlisting>
|
||
The X server can then be started manually:
|
||
<screen>
|
||
$ systemctl start display-manager.service
|
||
</screen>
|
||
</para>
|
||
|
||
|
||
<section><title>NVIDIA graphics cards</title>
|
||
|
||
<para>NVIDIA provides a proprietary driver for its graphics cards that
|
||
has better 3D performance than the X.org drivers. It is not enabled
|
||
by default because it’s not free software. You can enable it as follows:
|
||
<programlisting>
|
||
hardware.opengl.videoDrivers = [ "nvidia" ];
|
||
</programlisting>
|
||
You may need to reboot after enabling this driver to prevent a clash
|
||
with other kernel modules.</para>
|
||
|
||
<para>On 64-bit systems, if you want full acceleration for 32-bit
|
||
programs such as Wine, you should also set the following:
|
||
<programlisting>
|
||
services.xserver.driSupport32Bit = true;
|
||
</programlisting>
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Touchpads</title>
|
||
|
||
<para>Support for Synaptics touchpads (found in many laptops such as
|
||
the Dell Latitude series) can be enabled as follows:
|
||
<programlisting>
|
||
services.xserver.synaptics.enable = true;
|
||
</programlisting>
|
||
The driver has many options (see <xref linkend="ch-options"/>). For
|
||
instance, the following enables two-finger scrolling:
|
||
<programlisting>
|
||
services.xserver.synaptics.twoFingerScroll = true;
|
||
</programlisting>
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section><title>Networking</title>
|
||
|
||
<section><title>Secure shell access</title>
|
||
|
||
<para>Secure shell (SSH) access to your machine can be enabled by
|
||
setting:
|
||
|
||
<programlisting>
|
||
services.openssh.enable = true;
|
||
</programlisting>
|
||
|
||
By default, root logins using a password are disallowed. They can be
|
||
disabled entirely by setting
|
||
<literal>services.openssh.permitRootLogin</literal> to
|
||
<literal>"no"</literal>.</para>
|
||
|
||
<para>You can declaratively specify authorised RSA/DSA public keys for
|
||
a user as follows:
|
||
|
||
<!-- FIXME: this might not work if the user is unmanaged. -->
|
||
<programlisting>
|
||
users.extraUsers.alice.openssh.authorizedKeys.keys =
|
||
[ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>IPv4 configuration</title>
|
||
|
||
<para>By default, NixOS uses DHCP (specifically,
|
||
<command>dhcpcd</command>) to automatically configure network
|
||
interfaces. However, you can configure an interface manually as
|
||
follows:
|
||
|
||
<programlisting>
|
||
networking.interfaces.eth0 = { ipAddress = "192.168.1.2"; prefixLength = 24; };
|
||
</programlisting>
|
||
|
||
(The network prefix can also be specified using the option
|
||
<literal>subnetMask</literal>,
|
||
e.g. <literal>"255.255.255.0"</literal>, but this is deprecated.)
|
||
Typically you’ll also want to set a default gateway and set of name
|
||
servers:
|
||
|
||
<programlisting>
|
||
networking.defaultGateway = "192.168.1.1";
|
||
networking.nameservers = [ "8.8.8.8" ];
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
<note><para>Statically configured interfaces are set up by the systemd
|
||
service
|
||
<replaceable>interface-name</replaceable><literal>-cfg.service</literal>.
|
||
The default gateway and name server configuration is performed by
|
||
<literal>network-setup.service</literal>.</para></note>
|
||
|
||
<para>The host name is set using <option>networking.hostName</option>:
|
||
|
||
<programlisting>
|
||
networking.hostName = "cartman";
|
||
</programlisting>
|
||
|
||
The default host name is <literal>nixos</literal>. Set it to the
|
||
empty string (<literal>""</literal>) to allow the DHCP server to
|
||
provide the host name.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>IPv6 configuration</title>
|
||
|
||
<para>IPv6 is enabled by default. Stateless address autoconfiguration
|
||
is used to automatically assign IPv6 addresses to all interfaces. You
|
||
can disable IPv6 support globally by setting:
|
||
|
||
<programlisting>
|
||
networking.enableIPv6 = false;
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Firewall</title>
|
||
|
||
<para>NixOS has a simple stateful firewall that blocks incoming
|
||
connections and other unexpected packets. The firewall applies to
|
||
both IPv4 and IPv6 traffic. It can be enabled as follows:
|
||
|
||
<programlisting>
|
||
networking.firewall.enable = true;
|
||
</programlisting>
|
||
|
||
You can open specific TCP ports to the outside world:
|
||
|
||
<programlisting>
|
||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||
</programlisting>
|
||
|
||
Note that TCP port 22 (ssh) is opened automatically if the SSH daemon
|
||
is enabled (<option>services.openssh.enable = true</option>). UDP
|
||
ports can be opened through
|
||
<option>networking.firewall.allowedUDPPorts</option>. Also of
|
||
interest is
|
||
|
||
<programlisting>
|
||
networking.firewall.allowPing = true;
|
||
</programlisting>
|
||
|
||
to allow the machine to respond to ping requests. (ICMPv6 pings are
|
||
always allowed.)</para>
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Wireless networks</title>
|
||
|
||
<para>
|
||
NixOS will start wpa_supplicant for you if you enable this setting:
|
||
|
||
<programlisting>
|
||
networking.wireless.enable = true;
|
||
</programlisting>
|
||
|
||
NixOS currently does not generate wpa_supplicant's
|
||
configuration file, <literal>/etc/wpa_supplicant.conf</literal>. You should edit this file
|
||
yourself to define wireless networks, WPA keys and so on (see
|
||
wpa_supplicant.conf(5)).
|
||
</para>
|
||
|
||
<para>
|
||
If you are using WPA2 the <command>wpa_passphrase</command> tool might be useful
|
||
to generate the <literal>wpa_supplicant.conf</literal>.
|
||
|
||
<screen>
|
||
$ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen>
|
||
|
||
After you have edited the <literal>wpa_supplicant.conf</literal>,
|
||
you need to restart the wpa_supplicant service.
|
||
|
||
<screen>
|
||
$ systemctl restart wpa_supplicant.service</screen>
|
||
</para>
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<section><title>Ad-hoc configuration</title>
|
||
|
||
<para>You can use <option>networking.localCommands</option> to specify
|
||
shell commands to be run at the end of
|
||
<literal>network-setup.service</literal>. This is useful for doing
|
||
network configuration not covered by the existing NixOS modules. For
|
||
instance, to statically configure an IPv6 address:
|
||
|
||
<programlisting>
|
||
networking.localCommands =
|
||
''
|
||
ip -6 addr add 2001:610:685:1::1/64 dev eth0
|
||
'';
|
||
</programlisting>
|
||
|
||
</para>
|
||
|
||
</section>
|
||
|
||
|
||
<!-- TODO: OpenVPN, NAT -->
|
||
|
||
|
||
</section>
|
||
|
||
|
||
<!--===============================================================-->
|
||
|
||
<section><title>Linux kernel</title>
|
||
|
||
<para>You can override the Linux kernel and associated packages using
|
||
the option <option>boot.kernelPackages</option>. For instance, this
|
||
selects the Linux 3.10 kernel:
|
||
<programlisting>
|
||
boot.kernelPackages = pkgs.linuxPackages_3_10;
|
||
</programlisting>
|
||
Note that this not only replaces the kernel, but also packages that
|
||
are specific to the kernel version, such as the NVIDIA video drivers.
|
||
This ensures that driver packages are consistent with the
|
||
kernel.</para>
|
||
|
||
<para>The default Linux kernel configuration should be fine for most
|
||
users. You can see the configuration of your current kernel in
|
||
<filename>/run/booted-system/kernel-modules/config</filename>. If you
|
||
want to change the kernel configuration, you can use the
|
||
<option>packageOverrides</option> feature (see <xref
|
||
linkend="sec-customising-packages" />). For instance, to enable
|
||
support for the kernel debugger KGDB:
|
||
|
||
<programlisting>
|
||
nixpkgs.config.packageOverrides = pkgs:
|
||
{ linux_3_4 = pkgs.linux_3_4.override {
|
||
extraConfig =
|
||
''
|
||
KGDB y
|
||
'';
|
||
};
|
||
};
|
||
</programlisting>
|
||
|
||
<varname>extraConfig</varname> takes a list of Linux kernel
|
||
configuration options, one per line. The name of the option should
|
||
not include the prefix <literal>CONFIG_</literal>. The option value
|
||
is typically <literal>y</literal>, <literal>n</literal> or
|
||
<literal>m</literal> (to build something as a kernel module).</para>
|
||
|
||
<para>Kernel modules for hardware devices are generally loaded
|
||
automatically by <command>udev</command>. You can force a module to
|
||
be loaded via <option>boot.kernelModules</option>, e.g.
|
||
<programlisting>
|
||
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
|
||
</programlisting>
|
||
If the module is required early during the boot (e.g. to mount the
|
||
root file system), you can use
|
||
<option>boot.initrd.extraKernelModules</option>:
|
||
<programlisting>
|
||
boot.initrd.extraKernelModules = [ "cifs" ];
|
||
</programlisting>
|
||
This causes the specified modules and their dependencies to be added
|
||
to the initial ramdark.</para>
|
||
|
||
<para>Kernel runtime parameters can be set through
|
||
<option>boot.kernel.sysctl</option>, e.g.
|
||
<programlisting>
|
||
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;
|
||
</programlisting>
|
||
sets the kernel’s TCP keepalive time to 120 seconds. To see the
|
||
available parameters, run <command>sysctl -a</command>.</para>
|
||
|
||
</section>
|
||
|
||
|
||
<!-- Apache; libvirtd virtualisation -->
|
||
|
||
|
||
</chapter>
|