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 that file only take effect after you run nixos-rebuild.
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 . 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 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 <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 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 unstalled using the 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-env1 manpage or the Nix manual.
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 = "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 can be enabled as follows: networking.firewall.enable = true; 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 (). UDP ports can be opened through . 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 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 '';