# Configuring NixOS

This chapter describes how to configure various aspects of a NixOS machine through the configuration file `/etc/nixos/configuration.nix`. As described in , changes to this file only take effect after you run `nixos-rebuild`.

## Configuration syntax

### The basics

The NixOS configuration file `/etc/nixos/configuration.nix` is actually a Nix expression, 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 Nix manual, but here we give a short overview of the most important constructs useful in NixOS configuration files.

The NixOS configuration file generally looks like this:

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

    { config, pkgs, ... }:

    { services.httpd.enable = true;
      services.httpd.adminAddr = "alice@example.org";
      services.httpd.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, `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:

    { config, pkgs, ... }:

    { services = {
        httpd = {
          enable = true;
          adminAddr = "alice@example.org";
          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:

    The option `services.httpd.enabl' 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:

    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.

      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.

      networking.extraHosts =
        ''
          127.0.0.2 other-localhost
          10.0.0.1 server
        '';

  The main difference is that preceding whitespace is automatically stripped from each line, and that characters like `"` and `\` are not special (making it more convenient for including things like shell code).
Booleans

  These can be `true` or `false`, e.g.

      networking.firewall.enable = true;
      networking.firewall.allowPing = false;

Integers

  For example,

      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

      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:

      boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];

  List elements can be any other type, e.g. sets:

      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:

      environment.systemPackages =
        [ pkgs.thunderbird
          pkgs.emacs
        ];

      postgresql.package = pkgs.postgresql90;

  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 .

### Abstractions

If you find yourself repeating yourself over and over, it’s time to abstract. Take, for instance, this Apache HTTP Server configuration:

    {
      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";
          }
        ];
    }

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 `let`:

    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";
          })
        ];
    }

The `let exampleOrgCommon = ...` defines a variable named `exampleOrgCommon`. The `//` operator merges two attribute sets, so the configuration of the second virtual host is the set `exampleOrgCommon` extended with the SSL options.

You can write a `let` wherever an expression is allowed. Thus, you also could have written:

    {
      services.httpd.virtualHosts =
        let exampleOrgCommon = ...; in
        [ exampleOrgCommon
          (exampleOrgCommon // { ... })
        ];
    }

but not `{ let exampleOrgCommon = ...; in ...; }` since attributes (as opposed to attribute values) are not expressions.

Functions 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:

    {
      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")
          ];
    }

Here, `makeVirtualHost` is a function that takes a single argument `name` and returns the configuration for a virtual host. That function is then called for several names to produce the list of virtual host configurations.

We can further improve on this by using the function `map`, which applies another function to every element in a list:

    {
      services.httpd.virtualHosts =
        let
          makeVirtualHost = ...;
        in map makeVirtualHost
          [ "example.org" "example.com" "example.gov" "example.nl" ];
    }

(The function `map` is called a higher-order function because it takes another function as an argument.)

What if you need more than one argument, for instance, if we want to use a different `documentRoot` for each virtual host? Then we can make `makeVirtualHost` a function that takes a set as its argument, like this:

    {
      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"; }
          ];
    }

But in this case (where every root is a subdirectory of `/sites` named after the virtual host), it would have been shorter to define `makeVirtualHost` as

    makeVirtualHost = name:
      { hostName = name;
        documentRoot = "/sites/${name}";
        adminAddr = "alice@example.org";
      };

Here, the construct `${...}` allows the result of an expression to be spliced into a string.

### 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.:

    { 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:

    { config, pkgs, ... }:

    { services.xserver.enable = true;
      services.xserver.displayManager.kdm.enable = true;
      services.xserver.desktopManager.kde4.enable = true;
      environment.systemPackages = [ pkgs.kde4.kscreensaver ];
    }

Note that both `configuration.nix` and `kde.nix` define the option `environment.systemPackages`. When multiple modules define an option, NixOS will try to merge the definitions. In the case of `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`:

    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 `services.httpd.adminAddr`, `nixos-rebuild` will give an error:

    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:

    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 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.. For example, here is a module that adds some packages to `environment.systemPackages` only if `services.xserver.enable` is set to `true` somewhere else:

    { 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:

    $ 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. It’s not installed by default; run `nix-env -i nix-repl` to get it. A typical use:

    $ nix-repl '<nixos>'

    nix-repl> config.networking.hostName
    "mandark"

    nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
    [ "example.org" "example.gov" ]

### 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 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; }` | An set with attributes names `x` and `y`
`{ foo.bar = 1; }` | A nested set, equivalent to `{ foo = { bar = 1; }; }`
`rec { x = "bla"; 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!"`)
`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 ]`)

## Package management

This section describes how to add additional packages to your system. NixOS has two distinct styles of package management:

- Declarative, where you declare what packages you want in your `configuration.nix`. Every time you run `nixos-rebuild`, NixOS will ensure that you get a consistent set of binaries corresponding to your specification.

- Ad hoc, where you install, upgrade and uninstall packages via the `nix-env` command. This style allows mixing packages from different Nixpkgs versions. It’s the only choice for non-root users.

The next two sections describe these two styles.

### Declarative package management

With declarative package management, you specify which packages you want on your system by setting the option `environment.systemPackages`. For instance, adding the following line to `configuration.nix` enables the Mozilla Thunderbird email application:

    environment.systemPackages = [ pkgs.thunderbird ];

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 `nixos-rebuild switch`.

You can get a list of the available packages as follows:

    $ nix-env -qaP '*' --description
    nixos.pkgs.firefox   firefox-23.0   Mozilla Firefox - the browser, reloaded
    ...

The first column in the output is the attribute name, such as `nixos.pkgs.thunderbird`. (The `nixos` prefix allows distinguishing between different channels that you might have.)

To “uninstall” a package, simply remove it from `environment.systemPackages` and run `nixos-rebuild switch`.

#### Customising packages

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 `configuration.nix` as follows:

`nixpkgs.config.firefox.enableGoogleTalkPlugin = true;`

Unfortunately, Nixpkgs currently lacks a way to query available configuration options.

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:

    environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ];

The function `override` 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 `gtk` gets the value `pkgs.gtk3`, 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, `environment.systemPackages` would be a list with two elements.)

Even greater customisation is possible using the function `overrideDerivation`. While the `override` mechanism above overrides the arguments of a package function, `overrideDerivation` allows changing the result 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:

    environment.systemPackages =
      [ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: {
          name = "emacs-25.0-pre";
          src = /path/to/my/emacs/tree;
        }))
      ];

Here, `overrideDerivation` takes the Nix derivation specified by `pkgs.emacs` and produces a new derivation in which the original’s `name` and `src` attribute have been replaced by the given values. The original attributes are accessible via `attrs`.

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 global override as follows:

    nixpkgs.config.packageOverrides = pkgs:
      { emacs = pkgs.emacs.override { gtk = pkgs.gtk3; };
      };

The effect of this definition is essentially equivalent to modifying the `emacs` attribute in the Nixpkgs source tree. Any package in Nixpkgs that depends on `emacs` will be passed your customised instance. (However, the value `pkgs.emacs` in `nixpkgs.config.packageOverrides` refers to the original rather than overriden instance, to prevent an infinite recursion.)

#### Adding custom packages

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 Nixpkgs manual. In short, you clone Nixpkgs:

    $ git clone git://github.com/NixOS/nixpkgs.git
    $ cd nixpkgs

Then you write and test the package as described in the Nixpkgs manual. Finally, you add it to `environment.systemPackages`, e.g.

    environment.systemPackages = [ pkgs.my-package ];

and you run `nixos-rebuild`, specifying your own Nixpkgs tree:

    $ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs

The second possibility is to add the package outside of the Nixpkgs tree. For instance, here is how you specify a build of the GNU Hello package directly in `configuration.nix`:

    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 ];

Of course, you can also move the definition of `my-hello` into a separate Nix expression, e.g.

    environment.systemPackages = [ (import ./my-hello.nix) ];

where `my-hello.nix` contains:

    with import <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";
      };
    }

This allows testing the package easily:

    $ nix-build my-hello.nix
    $ ./result/bin/hello
    Hello, world!

### Ad hoc package management

With the command `nix-env`, you can install and uninstall packages from the command line. For instance, to install Mozilla Thunderbird:

    $ nix-env -iA nixos.pkgs.thunderbird

If you invoke this as root, the package is installed in the Nix profile `/nix/var/nix/profiles/default` and visible to all users of the system; otherwise, the package ends up in `/nix/var/nix/profiles/per-user/username/profile` and is not visible to other users. The `-A` flag specifies the package by its attribute name; without it, the package is installed by matching against its package name (e.g. `thunderbird`). The latter is slower because it requires matching against all available Nix packages, and is ambiguous if there are multiple matching packages.

Packages come from the NixOS channel. You typically upgrade a package by updating to the latest version of the NixOS channel:

    $ nix-channel --update nixos

and then running `nix-env -i` again. Other packages in the profile are not affected; this is the crucial difference with the declarative style of package management, where running `nixos-rebuild switch` 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:

    $ nix-env -u '*'

A package can be uninstalled using the `-e` flag:

    $ nix-env -e thunderbird

Finally, you can roll back an undesirable `nix-env` action:

    $ nix-env --rollback

`nix-env` has many more flags. For details, see the nix-env 1 manpage or the Nix manual.

## User management

NixOS supports both declarative and imperative styles of user management. In the declarative style, users are specified in `configuration.nix`. For instance, the following states that a user account named `alice` shall exist:

    users.extraUsers.alice =
      { createHome = true;
        home = "/home/alice";
        description = "Alice Foobar";
        extraGroups = [ "wheel" ];
        useDefaultShell = true;
        openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
      };

Note that `alice` is a member of the `wheel` group, which allows her to use `sudo` to execute commands as `root`. 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 `passwd` program to set a password, which is retained across invocations of `nixos-rebuild`.

A user ID (uid) is assigned automatically. You can also specify a uid manually by adding

        uid = 1000;

to the user specification.

Groups can be specified similarly. The following states that a group named `students` shall exist:

    users.extraGroups.students.gid = 1000;

As with users, the group ID (gid) is optional and will be assigned automatically if it’s missing.

Currently declarative user management is not perfect: `nixos-rebuild` does not know how to realise certain configuration changes. This includes removing a user or group, and removing group membership from a user.

In the imperative style, users and groups are managed by commands such as `useradd`, `groupmod` and so on. For instance, to create a user account named `alice`:

    $ useradd -m alice

The flag `-m` 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 `passwd` utility:

    $ passwd alice
    Enter new UNIX password: ***
    Retype new UNIX password: ***

A user can be deleted using `userdel`:

    $ userdel -r alice

The flag `-r` deletes the user’s home directory. Accounts can be modified using `usermod`. Unix groups can be managed using `groupadd`, `groupmod` and `groupdel`.

## File systems

You can define file systems using the `fileSystems` configuration option. For instance, the following definition causes NixOS to mount the Ext4 file system on device `/dev/disk/by-label/data` onto the mount point `/data`:

    fileSystems."/data" =
      { device = "/dev/disk/by-label/data";
        fsType = "ext4";
      };

Mount points are created automatically if they don’t already exist. For `device`, it’s best to use the topology-independent device aliases in `/dev/disk/by-label` and `/dev/disk/by-uuid`, as these don’t change if the topology changes (e.g. if a disk is moved to another IDE controller).

You can usually omit the file system type (`fsType`), since `mount` 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 `ext2`, `ext3` or `ext4`, then it’s best to specify `fsType` to ensure that the kernel module is available.

### LUKS-encrypted file systems

NixOS supports file systems that are encrypted using LUKS (Linux Unified Key Setup). For example, here is how you create an encrypted Ext4 file system on the device `/dev/sda2`:

    $ 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

To ensure that this file system is automatically mounted at boot time as `/`, add the following to `configuration.nix`:

    boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ];
    fileSystems."/".device = "/dev/mapper/crypted";

## X Window System

The X Window System (X11) provides the basis of NixOS’ graphical user interface. It can be enabled as follows:

    services.xserver.enable = true;

The X server will automatically detect and use the appropriate video driver from a set of X.org drivers (such as `vesa` and `intel`). You can also specify a driver manually, e.g.

    services.xserver.videoDrivers = [ "r128" ];

to enable X.org’s `xf86-video-r128` driver.

You also need to enable at least one desktop or window manager. Otherwise, you can only log into a plain undecorated `xterm` window. Thus you should pick one or more of the following lines:

    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;

NixOS’s default display manager (the program that provides a graphical login prompt and manages the X server) is SLiM. You can select KDE’s `kdm` instead:

    services.xserver.displayManager.kdm.enable = true;

The X server is started automatically at boot time. If you don’t want this to happen, you can set:

    services.xserver.autorun = false;

The X server can then be started manually:

    $ systemctl start display-manager.service

### NVIDIA graphics cards

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:

    services.xserver.videoDrivers = [ "nvidia" ];

You may need to reboot after enabling this driver to prevent a clash with other kernel modules.

On 64-bit systems, if you want full acceleration for 32-bit programs such as Wine, you should also set the following:

    services.xserver.driSupport32Bit = true;

### Touchpads

Support for Synaptics touchpads (found in many laptops such as the Dell Latitude series) can be enabled as follows:

    services.xserver.synaptics.enable = true;

The driver has many options (see ). For instance, the following enables two-finger scrolling:

    services.xserver.synaptics.twoFingerScroll = true;

## Networking

### Secure shell access

Secure shell (SSH) access to your machine can be enabled by setting:

    services.openssh.enable = true;

By default, root logins using a password are disallowed. They can be disabled entirely by setting `services.openssh.permitRootLogin` to `"no"`.

You can declaratively specify authorised RSA/DSA public keys for a user as follows:

    users.extraUsers.alice.openssh.authorizedKeys.keys =
      [ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];

### IPv4 configuration

By default, NixOS uses DHCP (specifically, `dhcpcd`) to automatically configure network interfaces. However, you can configure an interface manually as follows:

    networking.interfaces.eth0 = { ipAddress = "192.168.1.2"; prefixLength = 24; };

(The network prefix can also be specified using the option `subnetMask`, e.g. `"255.255.255.0"`, but this is deprecated.) Typically you’ll also want to set a default gateway and set of name servers:

    networking.defaultGateway = "192.168.1.1";
    networking.nameservers = [ "8.8.8.8" ];

Statically configured interfaces are set up by the systemd service interface-name`-cfg.service`. The default gateway and name server configuration is performed by `network-setup.service`.

The host name is set using `networking.hostName`:

    networking.hostName = "cartman";

The default host name is `nixos`. Set it to the empty string (`""`) to allow the DHCP server to provide the host name.

### IPv6 configuration

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:

    networking.enableIPv6 = false;

### Firewall

NixOS has a simple stateful firewall that blocks incoming connections and other unexpected packets. The firewall applies to both IPv4 and IPv6 traffic. It is enabled by default. It can be disabled as follows:

    networking.firewall.enable = false;

If the firewall is enabled, you can open specific TCP ports to the outside world:

    networking.firewall.allowedTCPPorts = [ 80 443 ];

Note that TCP port 22 (ssh) is opened automatically if the SSH daemon is enabled (`services.openssh.enable = true`). UDP ports can be opened through `networking.firewall.allowedUDPPorts`. Also of interest is

    networking.firewall.allowPing = true;

to allow the machine to respond to ping requests. (ICMPv6 pings are always allowed.)

### Wireless networks

NixOS will start wpa_supplicant for you if you enable this setting:

    networking.wireless.enable = true;

NixOS currently does not generate wpa_supplicant's configuration file, `/etc/wpa_supplicant.conf`. You should edit this file yourself to define wireless networks, WPA keys and so on (see wpa_supplicant.conf(5)).

If you are using WPA2 the `wpa_passphrase` tool might be useful to generate the `wpa_supplicant.conf`.

    $ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf

After you have edited the `wpa_supplicant.conf`, you need to restart the wpa_supplicant service.

    $ systemctl restart wpa_supplicant.service

### Ad-hoc configuration

You can use `networking.localCommands` to specify shell commands to be run at the end of `network-setup.service`. This is useful for doing network configuration not covered by the existing NixOS modules. For instance, to statically configure an IPv6 address:

    networking.localCommands =
      ''
        ip -6 addr add 2001:610:685:1::1/64 dev eth0
      '';

## Linux kernel

You can override the Linux kernel and associated packages using the option `boot.kernelPackages`. For instance, this selects the Linux 3.10 kernel:

    boot.kernelPackages = pkgs.linuxPackages_3_10;

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.

The default Linux kernel configuration should be fine for most users. You can see the configuration of your current kernel in `/run/booted-system/kernel-modules/config`. If you want to change the kernel configuration, you can use the `packageOverrides` feature (see ). For instance, to enable support for the kernel debugger KGDB:

    nixpkgs.config.packageOverrides = pkgs:
      { linux_3_4 = pkgs.linux_3_4.override {
          extraConfig =
            ''
              KGDB y
            '';
        };
      };

`extraConfig` takes a list of Linux kernel configuration options, one per line. The name of the option should not include the prefix `CONFIG_`. The option value is typically `y`, `n` or `m` (to build something as a kernel module).

Kernel modules for hardware devices are generally loaded automatically by `udev`. You can force a module to be loaded via `boot.kernelModules`, e.g.

    boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];

If the module is required early during the boot (e.g. to mount the root file system), you can use `boot.initrd.extraKernelModules`:

    boot.initrd.extraKernelModules = [ "cifs" ];

This causes the specified modules and their dependencies to be added to the initial ramdark.

Kernel runtime parameters can be set through `boot.kernel.sysctl`, e.g.

    boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 120;

sets the kernel’s TCP keepalive time to 120 seconds. To see the available parameters, run `sysctl -a`.