diff --git a/nixos/doc/manual/configuration.xml b/nixos/doc/manual/configuration.xml
index b0b1da71184..eb7894f157c 100644
--- a/nixos/doc/manual/configuration.xml
+++ b/nixos/doc/manual/configuration.xml
@@ -7,7 +7,7 @@
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
+, changes to this file only take
effect after you run nixos-rebuild.
@@ -15,7 +15,698 @@ effect after you run nixos-rebuild.
Configuration syntax
-TODO
+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,
+ 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, 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
+. When multiple modules
+define an option, NixOS will try to merge the
+definitions. In the case of
+, that’s easy: the lists of
+packages can simply be concatenated. For other types of options, a
+merge may not be possible: for instance, if two modules define
+,
+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 = 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 moduleIf 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 only if
+ 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
+ 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
+
+
+
+ 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 ])
+
+
+
+
+
+
+
+
+
@@ -170,7 +861,7 @@ recursion.)
-Adding custom packages
+Adding custom packagesIt’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
diff --git a/nixos/doc/manual/installation.xml b/nixos/doc/manual/installation.xml
index 0bf92b7d5bc..ba9bfcc652b 100644
--- a/nixos/doc/manual/installation.xml
+++ b/nixos/doc/manual/installation.xml
@@ -275,6 +275,8 @@ $ reboot
NixOS configuration
+{ config, pkgs, ... }:
+
{
imports =
[ # Include the results of the hardware scan.