<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.)  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.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>
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 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>
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>
