summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/ipv6-config.xml9
-rw-r--r--nixos/doc/manual/configuration/network-manager.xml18
-rw-r--r--nixos/doc/manual/development/option-declarations.xml88
-rw-r--r--nixos/doc/manual/development/option-types.xml394
-rw-r--r--nixos/doc/manual/development/writing-modules.xml1
-rw-r--r--nixos/doc/manual/release-notes/rl-1509.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1609.xml9
-rw-r--r--nixos/doc/manual/release-notes/rl-1703.xml6
-rw-r--r--nixos/lib/testing.nix21
-rw-r--r--nixos/modules/config/fonts/fonts.nix12
-rw-r--r--nixos/modules/config/networking.nix8
-rw-r--r--nixos/modules/config/system-path.nix4
-rw-r--r--nixos/modules/hardware/video/displaylink.nix61
-rw-r--r--nixos/modules/i18n/input-method/fcitx.nix7
-rw-r--r--nixos/modules/i18n/input-method/ibus.nix7
-rw-r--r--nixos/modules/installer/tools/nix-fallback-paths.nix5
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh4
-rw-r--r--nixos/modules/installer/tools/tools.nix14
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/misc/version.nix2
-rw-r--r--nixos/modules/module-list.nix9
-rw-r--r--nixos/modules/profiles/minimal.nix3
-rw-r--r--nixos/modules/programs/info.nix30
-rw-r--r--nixos/modules/programs/shadow.nix1
-rw-r--r--nixos/modules/programs/ssh.nix4
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/security/acme.nix3
-rw-r--r--nixos/modules/security/grsecurity.nix2
-rw-r--r--nixos/modules/security/pam.nix210
-rw-r--r--nixos/modules/security/setuid-wrappers.nix2
-rw-r--r--nixos/modules/security/sudo.nix2
-rw-r--r--nixos/modules/services/audio/mopidy.nix8
-rw-r--r--nixos/modules/services/audio/mpd.nix12
-rw-r--r--nixos/modules/services/audio/ympd.nix57
-rw-r--r--nixos/modules/services/continuous-integration/gocd-agent/default.nix2
-rw-r--r--nixos/modules/services/continuous-integration/gocd-server/default.nix14
-rw-r--r--nixos/modules/services/databases/4store-endpoint.nix4
-rw-r--r--nixos/modules/services/databases/4store.nix3
-rw-r--r--nixos/modules/services/databases/virtuoso.nix3
-rw-r--r--nixos/modules/services/editors/emacs.nix10
-rw-r--r--nixos/modules/services/mail/dovecot.nix3
-rw-r--r--nixos/modules/services/mail/freepops.nix3
-rw-r--r--nixos/modules/services/misc/docker-registry.nix81
-rw-r--r--nixos/modules/services/monitoring/prometheus/default.nix418
-rw-r--r--nixos/modules/services/monitoring/prometheus/node-exporter.nix74
-rw-r--r--nixos/modules/services/monitoring/ups.nix7
-rw-r--r--nixos/modules/services/network-filesystems/drbd.nix4
-rw-r--r--nixos/modules/services/networking/amuled.nix3
-rw-r--r--nixos/modules/services/networking/avahi-daemon.nix15
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix26
-rw-r--r--nixos/modules/services/networking/docker-registry-server.nix98
-rw-r--r--nixos/modules/services/networking/firewall.nix4
-rw-r--r--nixos/modules/services/networking/git-daemon.nix3
-rw-r--r--nixos/modules/services/networking/iodine.nix6
-rw-r--r--nixos/modules/services/networking/networkmanager.nix11
-rw-r--r--nixos/modules/services/networking/radicale.nix3
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix4
-rw-r--r--nixos/modules/services/networking/toxvpn.nix2
-rw-r--r--nixos/modules/services/security/haveged.nix18
-rw-r--r--nixos/modules/services/system/dbus.nix4
-rw-r--r--nixos/modules/services/ttys/agetty.nix3
-rw-r--r--nixos/modules/services/web-apps/tt-rss.nix158
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix7
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix4
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix16
-rw-r--r--nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixos/modules/system/activation/activation-script.nix21
-rw-r--r--nixos/modules/system/boot/kernel.nix6
-rw-r--r--nixos/modules/system/boot/networkd.nix3
-rw-r--r--nixos/modules/system/boot/stage-2-init.sh2
-rw-r--r--nixos/modules/system/boot/systemd.nix29
-rw-r--r--nixos/modules/tasks/filesystems.nix6
-rw-r--r--nixos/modules/tasks/filesystems/nfs.nix16
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix1
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces.nix2
-rw-r--r--nixos/modules/virtualisation/azure-agent.nix3
-rw-r--r--nixos/modules/virtualisation/azure-bootstrap-blobs.nix3
-rw-r--r--nixos/modules/virtualisation/brightbox-image.nix4
-rw-r--r--nixos/modules/virtualisation/docker.nix25
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix4
-rw-r--r--nixos/modules/virtualisation/virtualbox-host.nix9
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix2
-rw-r--r--nixos/release-combined.nix2
-rw-r--r--nixos/release.nix5
-rw-r--r--nixos/tests/blivet.nix1
-rw-r--r--nixos/tests/docker-registry.nix43
-rw-r--r--nixos/tests/docker.nix3
-rw-r--r--nixos/tests/firewall.nix53
-rw-r--r--nixos/tests/influxdb.nix9
-rw-r--r--nixos/tests/kde5.nix (renamed from nixos/tests/sddm-kde5.nix)33
-rw-r--r--nixos/tests/mumble.nix11
-rw-r--r--nixos/tests/prometheus.nix29
-rw-r--r--nixos/tests/pump.io.nix2
-rw-r--r--nixos/tests/tomcat.nix5
-rw-r--r--nixos/tests/virtualbox.nix13
96 files changed, 1662 insertions, 720 deletions
diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml
index 592bf20e545d..bf86926f9bf5 100644
--- a/nixos/doc/manual/configuration/ipv6-config.xml
+++ b/nixos/doc/manual/configuration/ipv6-config.xml
@@ -12,8 +12,15 @@ can disable IPv6 support globally by setting:
 
 <programlisting>
 networking.enableIPv6 = false;
-</programlisting>
+</programlisting></para>
+
+<para>You can disable IPv6 on a single interface using a normal sysctl (in this
+example, we use interface <varname>eth0</varname>):
 
+<programlisting>
+boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
+</programlisting>
 </para>
 
+
 </section>
diff --git a/nixos/doc/manual/configuration/network-manager.xml b/nixos/doc/manual/configuration/network-manager.xml
index b7e47b8729f3..dafbcfcb1e5b 100644
--- a/nixos/doc/manual/configuration/network-manager.xml
+++ b/nixos/doc/manual/configuration/network-manager.xml
@@ -16,12 +16,22 @@ networking.networkmanager.enable = true;
 some desktop managers (e.g., GNOME) enable NetworkManager
 automatically for you.</para>
 
-<para>All users that should have permission to change network settings
-must belong to the <code>networkmanager</code> group.</para>
+<para>All users that should have permission to change network settings must
+belong to the <code>networkmanager</code> group:
+
+<programlisting>
+users.extraUsers.youruser.extraGroups = [ "networkmanager" ];
+</programlisting>
+</para>
+
+<para>NetworkManager is controlled using either <command>nmcli</command> or
+<command>nmtui</command> (curses-based terminal user interface). See their
+manual pages for details on their usage. Some desktop environments (GNOME, KDE)
+have their own configuration tools for NetworkManager.</para>
 
 <note><para><code>networking.networkmanager</code> and
-<code>networking.wireless</code> can not be enabled at the same time:
-you can still connect to the wireless networks using
+<code>networking.wireless</code> (WPA Supplicant) cannot be enabled at the same
+time: you can still connect to the wireless networks using
 NetworkManager.</para></note>
 
 </section>
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
index b0689aa1d97f..7be5e9d51d46 100644
--- a/nixos/doc/manual/development/option-declarations.xml
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -31,9 +31,9 @@ options = {
   <varlistentry>
     <term><varname>type</varname></term>
     <listitem>
-      <para>The type of the option (see below).  It may be omitted,
-      but that’s not advisable since it may lead to errors that are
-      hard to diagnose.</para>
+      <para>The type of the option (see <xref linkend='sec-option-types' />).
+      It may be omitted, but that’s not advisable since it may lead to errors
+      that are hard to diagnose.</para>
     </listitem>
   </varlistentry>
 
@@ -65,86 +65,4 @@ options = {
 
 </para>
 
-<para>Here is a non-exhaustive list of option types:
-
-<variablelist>
-
-  <varlistentry>
-    <term><varname>types.bool</varname></term>
-    <listitem>
-      <para>A Boolean.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.int</varname></term>
-    <listitem>
-      <para>An integer.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.str</varname></term>
-    <listitem>
-      <para>A string.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.lines</varname></term>
-    <listitem>
-      <para>A string.  If there are multiple definitions, they are
-      concatenated, with newline characters in between.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.path</varname></term>
-    <listitem>
-      <para>A path, defined as anything that, when coerced to a
-      string, starts with a slash.  This includes derivations.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.package</varname></term>
-    <listitem>
-      <para>A derivation (such as <literal>pkgs.hello</literal>) or a
-      store path (such as
-      <filename>/nix/store/1ifi1cfbfs5iajmvwgrbmrnrw3a147h9-hello-2.10</filename>).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A list of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.listOf types.str</literal> is a list of
-      strings).  Multiple definitions are concatenated together.</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>A set of elements of type <replaceable>t</replaceable>
-      (e.g., <literal>types.attrsOf types.int</literal> is a set of
-      name/value pairs, the values being integers).</para>
-    </listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
-    <listitem>
-      <para>Either the value <literal>null</literal> or something of
-      type <replaceable>t</replaceable>.</para>
-    </listitem>
-  </varlistentry>
-
-</variablelist>
-
-You can also create new types using the function
-<varname>mkOptionType</varname>.  See
-<filename>lib/types.nix</filename> in Nixpkgs for details.</para>
-
 </section>
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
new file mode 100644
index 000000000000..8871b02cebf1
--- /dev/null
+++ b/nixos/doc/manual/development/option-types.xml
@@ -0,0 +1,394 @@
+<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-option-types">
+
+<title>Options Types</title>
+
+  <para>Option types are a way to put constraints on the values a module option 
+    can take.
+    Types are also responsible of how values are merged in case of multiple 
+    value definitions.</para>
+  <section><title>Basic Types</title>
+
+    <para>Basic types are the simplest available types in the module system.
+      Basic types include multiple string types that mainly differ in how 
+      definition merging is handled.</para>
+
+<variablelist>
+  <varlistentry>
+    <term><varname>types.bool</varname></term>
+    <listitem><para>A boolean, its values can be <literal>true</literal> or 
+        <literal>false</literal>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.int</varname></term>
+    <listitem><para>An integer.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.path</varname></term>
+    <listitem><para>A filesystem path, defined as anything that when coerced to 
+        a string starts with a slash. Even if derivations can be considered as 
+        path, the more specific <literal>types.package</literal> should be 
+        preferred.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.package</varname></term>
+    <listitem><para>A derivation or a store path.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+<para>String related types:</para>
+
+<variablelist>
+  <varlistentry>
+    <term><varname>types.str</varname></term>
+    <listitem><para>A string. Multiple definitions cannot be 
+        merged.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.lines</varname></term>
+    <listitem><para>A string. Multiple definitions are concatenated with a new 
+        line <literal>"\n"</literal>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.commas</varname></term>
+    <listitem><para>A string. Multiple definitions are concatenated with a comma 
+        <literal>","</literal>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.envVar</varname></term>
+    <listitem><para>A string. Multiple definitions are concatenated with a 
+        collon <literal>":"</literal>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.separatedString</varname> 
+      <replaceable>sep</replaceable></term>
+    <listitem><para>A string with a custom separator 
+        <replaceable>sep</replaceable>, e.g. <literal>types.separatedString 
+          "|"</literal>.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+ </section>
+
+ <section><title>Composed Types</title>
+
+   <para>Composed types allow to create complex types by taking another type(s) 
+     or value(s) as parameter(s).
+     It is possible to compose types multiple times, e.g. <literal>with types; 
+       nullOr (enum [ "left" "right" ])</literal>.</para>
+
+<variablelist>
+  <varlistentry>
+    <term><varname>types.listOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>A list of <replaceable>t</replaceable> type, e.g. 
+        <literal>types.listOf int</literal>. Multiple definitions are merged 
+        with list concatenation.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.attrsOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>An attribute set of where all the values are of 
+        <replaceable>t</replaceable> type. Multiple definitions result in the 
+        joined attribute set.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.loaOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>An attribute set or a list of <replaceable>t</replaceable> 
+        type. Multiple definitions are merged according to the 
+        value.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.loeOf</varname> <replaceable>t</replaceable></term>
+    <listitem><para>A list or an element of <replaceable>t</replaceable> type. 
+        Multiple definitions are merged according to the 
+        values.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
+    <listitem><para><literal>null</literal> or type 
+        <replaceable>t</replaceable>. Multiple definitions are merged according 
+        to type <replaceable>t</replaceable>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.uniq</varname> <replaceable>t</replaceable></term>
+    <listitem><para>Ensures that type <replaceable>t</replaceable> cannot be 
+        merged. It is used to ensure option definitions are declared only 
+        once.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.enum</varname> <replaceable>l</replaceable></term>
+    <listitem><para>One element of the list <replaceable>l</replaceable>, e.g. 
+        <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions 
+        cannot be merged</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.either</varname> <replaceable>t1</replaceable> 
+      <replaceable>t2</replaceable></term>
+    <listitem><para>Type <replaceable>t1</replaceable> or type 
+        <replaceable>t2</replaceable>, e.g. <literal>with types; either int 
+          str</literal>. Multiple definitions cannot be 
+        merged.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.submodule</varname> <replaceable>o</replaceable></term>
+    <listitem><para>A set of sub options <replaceable>o</replaceable>. 
+        <replaceable>o</replaceable> can be an attribute set or a function 
+        returning an attribute set. Submodules are used in composed types to 
+        create modular options. Submodule are detailed in <xref 
+          linkend='section-option-types-submodule' />.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+</section>
+
+<section xml:id='section-option-types-submodule'><title>Submodule</title>
+
+  <para>Submodule is a very powerful type that defines a set of sub-options that 
+    are handled like a separate module.
+    It is especially interesting when used with composed types like 
+    <literal>attrsOf</literal> or <literal>listOf</literal>.</para>
+
+  <para>The submodule type take a parameter <replaceable>o</replaceable>, that 
+    should be a set, or a function returning a set with an 
+    <literal>options</literal> key defining the sub-options.
+    The option set can be defined directly (<xref linkend='ex-submodule-direct' 
+      />) or as reference (<xref linkend='ex-submodule-reference' />).</para>
+
+  <para>Submodule option definitions are type-checked accordingly to the options 
+    declarations. It is possible to declare submodule options inside a submodule 
+    sub-options for even higher modularity.</para>
+
+<example xml:id='ex-submodule-direct'><title>Directly defined submodule</title>
+<screen>
+options.mod = mkOption {
+  name = "mod";
+  description = "submodule example";
+  type = with types; listOf (submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  });
+};</screen></example>
+
+<example xml:id='ex-submodule-reference'><title>Submodule defined as a 
+    reference</title>
+<screen>
+let
+  modOptions = {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = int;
+      };
+    };
+  };
+in
+options.mod = mkOption {
+  description = "submodule example";
+  type = with types; listOf (submodule modOptions);
+};</screen></example>
+
+
+<section><title>Composed with <literal>listOf</literal></title>
+
+  <para>When composed with <literal>listOf</literal>, submodule allows multiple 
+    definitions of the submodule option set.</para>
+
+<example xml:id='ex-submodule-listof-declaration'><title>Declaration of a list 
+    of submodules</title>
+<screen>
+options.mod = mkOption {
+  description = "submodule example";
+  type = with types; listOf (submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  });
+};</screen></example>
+
+<example xml:id='ex-submodule-listof-definition'><title>Definition of a list of 
+    submodules</title>
+<screen>
+config.mod = [
+  { foo = 1; bar = "one"; }
+  { foo = 2; bar = "two"; }
+];</screen></example>
+
+</section>
+
+
+<section><title>Composed with <literal>attrsOf</literal></title>
+
+  <para>When composed with <literal>attrsOf</literal>, submodule allows multiple 
+    named definitions of the submodule option set.</para>
+
+<example xml:id='ex-submodule-attrsof-declaration'><title>Declaration of 
+    attribute sets of submodules</title>
+<screen>
+options.mod = mkOption {
+  description = "submodule example";
+  type = with types; attrsOf (submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  });
+};</screen></example>
+
+<example xml:id='ex-submodule-attrsof-definition'><title>Declaration of 
+    attribute sets of submodules</title>
+<screen>
+config.mod.one = { foo = 1; bar = "one"; };
+config.mod.two = { foo = 2; bar = "two"; };</screen></example>
+
+</section>
+</section>
+
+<section><title>Extending types</title>
+
+  <para>Types are mainly characterized by their <literal>check</literal> and 
+    <literal>merge</literal> functions.</para>
+
+<variablelist>
+  <varlistentry>
+    <term><varname>check</varname></term>
+    <listitem><para>The function to type check the value. Takes a value as 
+        parameter and return a boolean.
+        It is possible to extend a type check with the 
+        <literal>addCheck</literal> function (<xref 
+          linkend='ex-extending-type-check-1' />), or to fully override the 
+        check function (<xref linkend='ex-extending-type-check-2' />).</para>
+
+<example xml:id='ex-extending-type-check-1'><title>Adding a type check</title>
+<screen>
+byte = mkOption {
+  description = "An integer between 0 and 255.";
+  type = addCheck (x: x &gt;= 0 &amp;&amp; x &lt;= 255) types.int;
+};</screen></example>
+
+<example xml:id='ex-extending-type-check-2'><title>Overriding a type 
+    check</title>
+<screen>
+nixThings = mkOption {
+  description = "words that start with 'nix'";
+  type = types.str // {
+    check = (x: lib.hasPrefix "nix" x)
+  };
+};</screen></example>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>merge</varname></term>
+    <listitem><para>Function to merge the options values when multiple values 
+        are set.
+The function takes two parameters, <literal>loc</literal> the option path as a 
+list of strings, and <literal>defs</literal> the list of defined values as a 
+list.
+It is possible to override a type merge function for custom 
+needs.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+</section>
+
+<section><title>Custom Types</title>
+
+<para>Custom types can be created with the <literal>mkOptionType</literal> 
+  function.
+As type creation includes some more complex topics such as submodule handling, 
+it is recommended to get familiar with <filename 
+  xlink:href="https://github.com/NixOS/nixpkgs/blob/master/lib/types.nix">types.nix</filename> 
+code before creating a new type.</para>
+
+<para>The only required parameter is <literal>name</literal>.</para>
+
+<variablelist>
+  <varlistentry>
+    <term><varname>name</varname></term>
+    <listitem><para>A string representation of the type function name, name 
+        usually changes accordingly parameters passed to 
+        types.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>check</varname></term>
+    <listitem><para>A function to type check the definition value. Takes the 
+        definition value as a parameter and returns a boolean indicating the 
+        type check result, <literal>true</literal> for success and 
+        <literal>false</literal> for failure.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>merge</varname></term>
+    <listitem><para>A function to merge multiple definitions values. Takes two 
+        parameters:</para>
+      <variablelist>
+        <varlistentry>
+          <term><replaceable>loc</replaceable></term>
+          <listitem><para>The option path as a list of strings, e.g. 
+              <literal>["boot" "loader "grub" 
+                "enable"]</literal>.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><replaceable>defs</replaceable></term>
+          <listitem><para>The list of sets of defined <literal>value</literal> 
+              and <literal>file</literal> where the value was defined, e.g. 
+              <literal>[ { file = "/foo.nix"; value = 1; } { file = "/bar.nix"; 
+                value = 2 } ]</literal>. The <literal>merge</literal> function 
+              should return the merged value or throw an error in case the 
+              values are impossible or not meant to be merged.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>getSubOptions</varname></term>
+    <listitem><para>For composed types that can take a submodule as type 
+        parameter, this function generate sub-options documentation. It takes 
+        the current option prefix as a list and return the set of sub-options. 
+        Usually defined in a recursive manner by adding a term to the prefix, 
+        e.g. <literal>prefix: elemType.getSubOptions (prefix ++ 
+          [<replaceable>"prefix"</replaceable>])</literal> where 
+        <replaceable>"prefix"</replaceable> is the newly added 
+        prefix.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>getSubModules</varname></term>
+    <listitem><para>For composed types that can take a submodule as type 
+        parameter, this function should return the type parameters submodules. 
+        If the type parameter is called <literal>elemType</literal>, the 
+        function should just recursively look into submodules by returning 
+        <literal>elemType.getSubModules;</literal>.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>substSubModules</varname></term>
+    <listitem><para>For composed types that can take a submodule as type 
+        parameter, this function can be used to substitute the parameter of a 
+        submodule type. It takes a module as parameter and return the type with 
+        the submodule options substituted. It is usally defined as a type 
+        function call with a recursive call to 
+        <literal>substSubModules</literal>, e.g for a type 
+        <literal>composedType</literal> that take an <literal>elemtype</literal> 
+        type parameter, this function should be defined as <literal>m: 
+          composedType (elemType.substSubModules m)</literal>.</para></listitem>
+  </varlistentry>
+</variablelist>
+
+</section>
+</section>
diff --git a/nixos/doc/manual/development/writing-modules.xml b/nixos/doc/manual/development/writing-modules.xml
index a68b122ce022..ef6920160e6d 100644
--- a/nixos/doc/manual/development/writing-modules.xml
+++ b/nixos/doc/manual/development/writing-modules.xml
@@ -176,6 +176,7 @@ in {
 </example>
 
 <xi:include href="option-declarations.xml" />
+<xi:include href="option-types.xml" />
 <xi:include href="option-def.xml" />
 <xi:include href="meta-attributes.xml" />
 
diff --git a/nixos/doc/manual/release-notes/rl-1509.xml b/nixos/doc/manual/release-notes/rl-1509.xml
index a68baa0d8078..e0271485c361 100644
--- a/nixos/doc/manual/release-notes/rl-1509.xml
+++ b/nixos/doc/manual/release-notes/rl-1509.xml
@@ -471,7 +471,7 @@ in
   <listitem> <para>
     A newly packaged TeX Live 2015 is provided in <literal>pkgs.texlive</literal>,
     split into 6500 nix packages. For basic user documentation see
-    <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-15.09/pkgs/tools/typesetting/tex/texlive-new/default.nix#L1"
+    <link xlink:href="https://github.com/NixOS/nixpkgs/blob/release-15.09/pkgs/tools/typesetting/tex/texlive/default.nix#L1"
       >the source</link>.
     Beware of <link xlink:href="https://github.com/NixOS/nixpkgs/issues/9757"
       >an issue</link> when installing a too large package set.
diff --git a/nixos/doc/manual/release-notes/rl-1609.xml b/nixos/doc/manual/release-notes/rl-1609.xml
index 70759ee25f86..792b4458caaa 100644
--- a/nixos/doc/manual/release-notes/rl-1609.xml
+++ b/nixos/doc/manual/release-notes/rl-1609.xml
@@ -90,6 +90,15 @@ following incompatible changes:</para>
     Use <literal>security.audit.enable = true;</literal> to explicitly enable it.</para>
   </listitem>
 
+  <listitem>
+    <para>
+      <literal>pkgs.linuxPackages.virtualbox</literal> now contains only the
+      kernel modules instead of the VirtualBox user space binaries.
+      If you want to reference the user space binaries, you have to use the new
+      <literal>pkgs.virtualbox</literal> instead.
+    </para>
+  </listitem>
+
 </itemizedlist>
 
 
diff --git a/nixos/doc/manual/release-notes/rl-1703.xml b/nixos/doc/manual/release-notes/rl-1703.xml
index c0fa4388a2ad..2eda8a56b202 100644
--- a/nixos/doc/manual/release-notes/rl-1703.xml
+++ b/nixos/doc/manual/release-notes/rl-1703.xml
@@ -29,7 +29,11 @@ following incompatible changes:</para>
 
 <itemizedlist>
   <listitem>
-    <para></para>
+    <para>
+      <literal>gnome</literal> alias has been removed along with
+      <literal>gtk</literal>, <literal>gtkmm</literal> and several others.
+      Now you need to use versioned attributes, like <literal>gnome3</literal>.
+    </para>
   </listitem>
 </itemizedlist>
 
diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix
index 61b214bfba8c..7fad5cbc3cd9 100644
--- a/nixos/lib/testing.nix
+++ b/nixos/lib/testing.nix
@@ -157,9 +157,7 @@ rec {
         ${coreutils}/bin/mkdir -p $TMPDIR
         cd $TMPDIR
 
-        $origBuilder $origArgs
-
-        exit $?
+        exec $origBuilder $origArgs
       '';
 
       testScript = ''
@@ -172,9 +170,22 @@ rec {
       '';
 
       vmRunCommand = writeText "vm-run" ''
+        xchg=vm-state-client/xchg
         ${coreutils}/bin/mkdir $out
-        ${coreutils}/bin/mkdir -p vm-state-client/xchg
-        export > vm-state-client/xchg/saved-env
+        ${coreutils}/bin/mkdir -p $xchg
+
+        for i in $passAsFile; do
+          i2=''${i}Path
+          _basename=$(${coreutils}/bin/basename ''${!i2})
+          ${coreutils}/bin/cp ''${!i2} $xchg/$_basename
+          eval $i2=/tmp/xchg/$_basename
+          ${coreutils}/bin/ls -la $xchg
+        done
+
+        unset i i2 _basename
+        export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env
+        unset xchg
+
         export tests='${testScript}'
         ${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm
       ''; # */
diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix
index f913b8c33e56..af3d93fc1bc4 100644
--- a/nixos/modules/config/fonts/fonts.nix
+++ b/nixos/modules/config/fonts/fonts.nix
@@ -11,17 +11,27 @@ with lib;
       # TODO: find another name for it.
       fonts = mkOption {
         type = types.listOf types.path;
+        default = [];
         example = literalExample "[ pkgs.dejavu_fonts ]";
         description = "List of primary font paths.";
       };
 
+      enableDefaultFonts = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable a basic set of fonts providing several font styles
+          and families and reasonable coverage of Unicode.
+        '';
+      };
+
     };
 
   };
 
   config = {
 
-    fonts.fonts =
+    fonts.fonts = mkIf config.fonts.enableDefaultFonts
       [
         pkgs.xorg.fontbhlucidatypewriter100dpi
         pkgs.xorg.fontbhlucidatypewriter75dpi
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index 8a2e630a917a..aab5523c6848 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -223,10 +223,10 @@ in
     # Install the proxy environment variables
     environment.sessionVariables = cfg.proxy.envVars;
 
-    # The ‘ip-up’ target is started when we have IP connectivity.  So
-    # services that depend on IP connectivity (like ntpd) should be
-    # pulled in by this target.
-    systemd.targets.ip-up.description = "Services Requiring IP Connectivity";
+    # The ‘ip-up’ target is kept for backwards compatibility.
+    # New services should use systemd upstream targets:
+    # See https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
+    systemd.targets.ip-up.description = "Services Requiring IP Connectivity (deprecated)";
 
     # This is needed when /etc/resolv.conf is being overriden by networkd
     # and other configurations. If the file is destroyed by an environment
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index 169c86a2eae7..775d0c39c4fa 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -34,10 +34,10 @@ let
       config.programs.ssh.package
       pkgs.perl
       pkgs.procps
+      pkgs.rsync
       pkgs.strace
       pkgs.su
       pkgs.time
-      pkgs.texinfoInteractive
       pkgs.utillinux
       pkgs.which # 88K size
     ];
@@ -104,7 +104,6 @@ in
         "/etc/xdg"
         "/etc/gtk-2.0"
         "/etc/gtk-3.0"
-        "/info"
         "/lib" # FIXME: remove and update debug-info.nix
         "/sbin"
         "/share/applications"
@@ -112,7 +111,6 @@ in
         "/share/doc"
         "/share/emacs"
         "/share/icons"
-        "/share/info"
         "/share/menus"
         "/share/mime"
         "/share/nano"
diff --git a/nixos/modules/hardware/video/displaylink.nix b/nixos/modules/hardware/video/displaylink.nix
new file mode 100644
index 000000000000..2a9382f39410
--- /dev/null
+++ b/nixos/modules/hardware/video/displaylink.nix
@@ -0,0 +1,61 @@
+{ config, lib, ... }:
+
+with lib;
+
+let
+
+  enabled = elem "displaylink" config.services.xserver.videoDrivers;
+
+  displaylink = config.boot.kernelPackages.displaylink;
+
+in
+
+{
+
+  config = mkIf enabled {
+
+    boot.extraModulePackages = [ displaylink ];
+
+    boot.kernelModules = [ "evdi" ];
+
+    # Those are taken from displaylink-installer.sh and from Arch Linux AUR package.
+
+    services.udev.extraRules = ''
+      ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{bNumInterfaces}=="*5", TAG+="uaccess"
+    '';
+
+    powerManagement.powerDownCommands = ''
+      #flush any bytes in pipe
+      while read -n 1 -t 1 SUSPEND_RESULT < /tmp/PmMessagesPort_out; do : ; done;
+
+      #suspend DisplayLinkManager
+      echo "S" > /tmp/PmMessagesPort_in
+
+      #wait until suspend of DisplayLinkManager finish
+      read -n 1 -t 10 SUSPEND_RESULT < /tmp/PmMessagesPort_out
+    '';
+
+    powerManagement.resumeCommands = ''
+      #resume DisplayLinkManager
+      echo "R" > /tmp/PmMessagesPort_in
+    '';
+
+    systemd.services.displaylink = {
+      description = "DisplayLink Manager Service";
+      after = [ "display-manager.service" ];
+      wantedBy = [ "graphical.target" ];
+
+      serviceConfig = {
+        ExecStart = "${displaylink}/bin/DisplayLinkManager";
+        Restart = "always";
+        RestartSec = 5;
+      };
+
+      preStart = ''
+        mkdir -p /var/log/displaylink
+      '';
+    };
+
+  };
+
+}
diff --git a/nixos/modules/i18n/input-method/fcitx.nix b/nixos/modules/i18n/input-method/fcitx.nix
index e97bb9f80eb5..440f13b41522 100644
--- a/nixos/modules/i18n/input-method/fcitx.nix
+++ b/nixos/modules/i18n/input-method/fcitx.nix
@@ -20,10 +20,9 @@ in
         example = literalExample "with pkgs.fcitx-engines; [ mozc hangul ]";
         description =
           let
-            engines =
-              lib.concatStringsSep ", "
-              (map (name: "<literal>${name}</literal>")
-               (lib.attrNames pkgs.fcitx-engines));
+            enginesDrv = filterAttrs (const isDerivation) pkgs.fcitx-engines;
+            engines = concatStringsSep ", "
+              (map (name: "<literal>${name}</literal>") (attrNames enginesDrv));
           in
             "Enabled Fcitx engines. Available engines are: ${engines}.";
       };
diff --git a/nixos/modules/i18n/input-method/ibus.nix b/nixos/modules/i18n/input-method/ibus.nix
index 097a662c3c6d..d64cf2f283bf 100644
--- a/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixos/modules/i18n/input-method/ibus.nix
@@ -30,10 +30,9 @@ in
         example = literalExample "with pkgs.ibus-engines; [ mozc hangul ]";
         description =
           let
-            engines =
-              lib.concatStringsSep ", "
-              (map (name: "<literal>${name}</literal>")
-               (lib.attrNames pkgs.ibus-engines));
+            enginesDrv = filterAttrs (const isDerivation) pkgs.ibus-engines;
+            engines = concatStringsSep ", "
+              (map (name: "<literal>${name}</literal>") (attrNames enginesDrv));
           in
             "Enabled IBus engines. Available engines are: ${engines}.";
       };
diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix
new file mode 100644
index 000000000000..747d9d2bcec5
--- /dev/null
+++ b/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -0,0 +1,5 @@
+{
+  x86_64-linux = "/nix/store/i4mwf2gpvar7dqvlpp5m86llbq3ahbvb-nix-1.11.4";
+  i686-linux = "/nix/store/a3gjrbspb0q4hs3sv5g1y2nza43i8nzv-nix-1.11.4";
+  x86_64-darwin = "/nix/store/7v21yd3qpv0nclcy5cqr5njj9bril12s-nix-1.11.4";
+}
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
index 803989789838..36700d2bf566 100644
--- a/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -261,9 +261,9 @@ fi
 prebuiltNix() {
     machine="$1"
     if [ "$machine" = x86_64 ]; then
-        echo /nix/store/xryr9g56h8yjddp89d6dw12anyb4ch7c-nix-1.10
+        echo @nix_x86_64_linux@
     elif [[ "$machine" =~ i.86 ]]; then
-        echo /nix/store/2w92k5wlpspf0q2k9mnf2z42prx3bwmv-nix-1.10
+        echo @nix_i686_linux@
     else
         echo "$0: unsupported platform"
         exit 1
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index fc39a653abdc..a35f6ad8ae54 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -32,11 +32,15 @@ let
       "cp refs $out";
   };
 
-  nixos-rebuild = makeProg {
-    name = "nixos-rebuild";
-    src = ./nixos-rebuild.sh;
-    nix = config.nix.package.out;
-  };
+  nixos-rebuild =
+    let fallback = import ./nix-fallback-paths.nix; in
+    makeProg {
+      name = "nixos-rebuild";
+      src = ./nixos-rebuild.sh;
+      nix = config.nix.package.out;
+      nix_x86_64_linux = fallback.x86_64-linux;
+      nix_i686_linux = fallback.i686-linux;
+    };
 
   nixos-generate-config = makeProg {
     name = "nixos-generate-config";
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 31c93028bc52..e31349105946 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -181,7 +181,6 @@
       systemd-timesync = 154;
       liquidsoap = 155;
       etcd = 156;
-      docker-registry = 157;
       hbase = 158;
       opentsdb = 159;
       scollector = 160;
@@ -275,6 +274,7 @@
       gocd-server = 252;
       terraria = 253;
       mattermost = 254;
+      prometheus = 255;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -436,7 +436,6 @@
       systemd-timesync = 154;
       liquidsoap = 155;
       #etcd = 156; # unused
-      #docker-registry = 157; # unused
       hbase = 158;
       opentsdb = 159;
       scollector = 160;
@@ -520,6 +519,7 @@
       gocd-server = 252;
       terraria = 253;
       mattermost = 254;
+      prometheus = 255;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index 2ecdbdbf3925..ec423768296a 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -95,7 +95,7 @@ in
       nixosVersionSuffix = mkIf (pathIsDirectory gitRepo) (mkDefault (".git." + gitCommitId));
 
       # Note: code names must only increase in alphabetical order.
-      nixosCodeName = "Flounder";
+      nixosCodeName = "Gorilla";
     };
 
     # Generate /etc/os-release.  See
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 27fbe55cd429..8fef157c458f 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -40,6 +40,7 @@
   ./hardware/video/amdgpu.nix
   ./hardware/video/ati.nix
   ./hardware/video/bumblebee.nix
+  ./hardware/video/displaylink.nix
   ./hardware/video/nvidia.nix
   ./hardware/video/webcam/facetimehd.nix
   ./i18n/input-method/default.nix
@@ -66,8 +67,9 @@
   ./programs/command-not-found/command-not-found.nix
   ./programs/dconf.nix
   ./programs/environment.nix
-  ./programs/freetds.nix
   ./programs/fish.nix
+  ./programs/freetds.nix
+  ./programs/info.nix
   ./programs/kbdlight.nix
   ./programs/light.nix
   ./programs/man.nix
@@ -113,6 +115,7 @@
   ./services/audio/mpd.nix
   ./services/audio/mopidy.nix
   ./services/audio/squeezelite.nix
+  ./services/audio/ympd.nix
   ./services/backup/almir.nix
   ./services/backup/bacula.nix
   ./services/backup/crashplan.nix
@@ -228,7 +231,6 @@
   ./services/misc/dictd.nix
   ./services/misc/dysnomia.nix
   ./services/misc/disnix.nix
-  ./services/misc/docker-registry.nix
   ./services/misc/emby.nix
   ./services/misc/etcd.nix
   ./services/misc/felix.nix
@@ -286,6 +288,8 @@
   ./services/monitoring/monit.nix
   ./services/monitoring/munin.nix
   ./services/monitoring/nagios.nix
+  ./services/monitoring/prometheus/default.nix
+  ./services/monitoring/prometheus/node-exporter.nix
   ./services/monitoring/riemann.nix
   ./services/monitoring/riemann-dash.nix
   ./services/monitoring/riemann-tools.nix
@@ -332,7 +336,6 @@
   ./services/networking/dnschain.nix
   ./services/networking/dnscrypt-proxy.nix
   ./services/networking/dnsmasq.nix
-  ./services/networking/docker-registry-server.nix
   ./services/networking/ejabberd.nix
   ./services/networking/fan.nix
   ./services/networking/ferm.nix
diff --git a/nixos/modules/profiles/minimal.nix b/nixos/modules/profiles/minimal.nix
index c353da227aeb..b047b7063653 100644
--- a/nixos/modules/profiles/minimal.nix
+++ b/nixos/modules/profiles/minimal.nix
@@ -11,4 +11,7 @@ with lib;
   # This isn't perfect, but let's expect the user specifies an UTF-8 defaultLocale
   i18n.supportedLocales = [ (config.i18n.defaultLocale + "/UTF-8") ];
   services.nixosManual.enable = mkDefault false;
+
+  programs.man.enable = mkDefault false;
+  programs.info.enable = mkDefault false;
 }
diff --git a/nixos/modules/programs/info.nix b/nixos/modules/programs/info.nix
new file mode 100644
index 000000000000..be6439dca5ad
--- /dev/null
+++ b/nixos/modules/programs/info.nix
@@ -0,0 +1,30 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options = {
+
+    programs.info.enable = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to enable info pages and the <command>info</command> command.
+      '';
+    };
+
+  };
+
+
+  config = mkIf config.programs.info.enable {
+
+    environment.systemPackages = [ pkgs.texinfoInteractive ];
+
+    environment.pathsToLink = [ "/info" "/share/info" ];
+
+    environment.extraOutputsToInstall = [ "info" ];
+
+  };
+
+}
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index 878c9cc0cf09..ce4d46e19bf9 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -99,7 +99,6 @@ in
         groupdel = { rootOK = true; };
         login = { startSession = true; allowNullPassword = true; showMotd = true; updateWtmp = true; };
         chpasswd = { rootOK = true; };
-        chgpasswd = { rootOK = true; };
       };
 
     security.setuidPrograms = [ "su" "chfn" ]
diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index cc835081c9f9..b6fd9868f98f 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -56,7 +56,6 @@ in
 
       setXAuthLocation = mkOption {
         type = types.bool;
-        default = config.services.xserver.enable;
         description = ''
           Whether to set the path to <command>xauth</command> for X11-forwarded connections.
           This causes a dependency on X11 packages.
@@ -165,6 +164,9 @@ in
 
   config = {
 
+    programs.ssh.setXAuthLocation =
+      mkDefault (config.services.xserver.enable || config.programs.ssh.forwardX11);
+
     assertions =
       [ { assertion = cfg.forwardX11 -> cfg.setXAuthLocation;
           message = "cannot enable X11 forwarding without setting XAuth location";
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 412cccc20d58..34b9724442eb 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -15,7 +15,6 @@ with lib;
     (mkRenamedOptionModule [ "networking" "enableRT73Firmware" ] [ "networking" "enableRalinkFirmware" ])
 
     (mkRenamedOptionModule [ "services" "cadvisor" "host" ] [ "services" "cadvisor" "listenAddress" ])
-    (mkRenamedOptionModule [ "services" "dockerRegistry" "host" ] [ "services" "dockerRegistry" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ])
@@ -154,5 +153,7 @@ with lib;
       "See the 16.03 release notes for more information.")
     (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "")
     (mkRemovedOptionModule [ "services" "dovecot2" "package" ] "")
+    (mkRemovedOptionModule [ "services" "dockerRegistry" ]
+      "docker-registry has been deprecated upstream since a long time.")
   ];
 }
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index 3dac558b9537..45e8f64046b0 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -166,7 +166,8 @@ in
                           ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains);
                 acmeService = {
                   description = "Renew ACME Certificate for ${cert}";
-                  after = [ "network.target" ];
+                  after = [ "network.target" "network-online.target" ];
+                  wants = [ "network-online.target" ];
                   serviceConfig = {
                     Type = "oneshot";
                     SuccessExitStatus = [ "0" "1" ];
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index ea1064c2d425..7ba25f866f24 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -72,6 +72,8 @@ in
         (isNO "GRKERNSEC_NO_RBAC")
       ];
 
+    nixpkgs.config.grsecurity = true;
+
     # Install PaX related utillities into the system profile.
     environment.systemPackages = with pkgs; [ gradm paxctl pax-utils ];
 
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 77815cd6dcc1..6a4f6634c4b3 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -105,6 +105,16 @@ let
         '';
       };
 
+      setEnvironment = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether the service should set the environment variables
+          listed in <option>environment.sessionVariables</option>
+          using <literal>pam_env.so</literal>.
+        '';
+      };
+
       setLoginUid = mkOption {
         type = types.bool;
         description = ''
@@ -219,102 +229,107 @@ let
       # module provides the right hooks.
       text = mkDefault
         (''
-          # Account management.
-          account sufficient pam_unix.so
-          ${optionalString use_ldap
-              "account sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString config.krb5.enable
-              "account sufficient ${pam_krb5}/lib/security/pam_krb5.so"}
-
-          # Authentication management.
-          ${optionalString cfg.rootOK
-              "auth sufficient pam_rootok.so"}
-          ${optionalString cfg.requireWheel
-              "auth required pam_wheel.so use_uid"}
-          ${optionalString cfg.logFailures
-              "auth required pam_tally.so"}
-          ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth)
-              "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"}
-          ${optionalString cfg.fprintAuth
-              "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"}
-          ${optionalString cfg.u2fAuth
-              "auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so"}
-          ${optionalString cfg.usbAuth
-              "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"}
-        '' +
-          # Modules in this block require having the password set in PAM_AUTHTOK.
-          # pam_unix is marked as 'sufficient' on NixOS which means nothing will run
-          # after it succeeds. Certain modules need to run after pam_unix
-          # prompts the user for password so we run it once with 'required' at an
-          # earlier point and it will run again with 'sufficient' further down.
-          # We use try_first_pass the second time to avoid prompting password twice
-          (optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount)) ''
-              auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth
-              ${optionalString config.security.pam.enableEcryptfs
-                "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"}
-              ${optionalString cfg.pamMount
-                "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
-            '') + ''
-          ${optionalString cfg.unixAuth
-              "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
-          ${optionalString cfg.otpwAuth
-              "auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"}
-          ${let oath = config.security.pam.oath; in optionalString cfg.oathAuth
-              "auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}"}
-          ${optionalString use_ldap
-              "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
-          ${optionalString config.krb5.enable ''
-            auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
-            auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
-            auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass
-          ''}
-          auth required pam_deny.so
-
-          # Password management.
-          password requisite pam_unix.so nullok sha512
-          ${optionalString config.security.pam.enableEcryptfs
-              "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
-          ${optionalString cfg.pamMount
-              "password optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
-          ${optionalString use_ldap
-              "password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString config.krb5.enable
-              "password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"}
-          ${optionalString config.services.samba.syncPasswordsByPam
-              "password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"}
-
-          # Session management.
-          session required pam_env.so envfile=${config.system.build.pamEnvironment}
-          session required pam_unix.so
-          ${optionalString cfg.setLoginUid
+           # Account management.
+           account sufficient pam_unix.so
+         '' + optionalString use_ldap ''
+           account sufficient ${pam_ldap}/lib/security/pam_ldap.so
+         '' + optionalString config.krb5.enable ''
+           account sufficient ${pam_krb5}/lib/security/pam_krb5.so
+         '' + ''
+
+           # Authentication management.
+         '' + optionalString cfg.rootOK ''
+           auth sufficient pam_rootok.so
+         '' + optionalString cfg.requireWheel ''
+           auth required pam_wheel.so use_uid
+         '' + optionalString cfg.logFailures ''
+           auth required pam_tally.so
+         '' + optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) ''
+           auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u
+         '' + optionalString cfg.fprintAuth ''
+           auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
+         '' + optionalString cfg.u2fAuth ''
+           auth sufficient ${pkgs.pam_u2f}/lib/security/pam_u2f.so
+         '' + optionalString cfg.usbAuth ''
+           auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so
+         ''
+
+           # Modules in this block require having the password set in PAM_AUTHTOK.
+           # pam_unix is marked as 'sufficient' on NixOS which means nothing will run
+           # after it succeeds. Certain modules need to run after pam_unix
+           # prompts the user for password so we run it once with 'required' at an
+           # earlier point and it will run again with 'sufficient' further down.
+           # We use try_first_pass the second time to avoid prompting password twice
+         + optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount)) (''
+           auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok "}likeauth
+           '' + optionalString config.security.pam.enableEcryptfs ''
+             auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap
+           '' + optionalString cfg.pamMount ''
+             auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so
+           '')
+         + optionalString cfg.unixAuth ''
+           auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok "}likeauth try_first_pass
+         '' + optionalString cfg.otpwAuth ''
+           auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so
+         '' + (let oath = config.security.pam.oath; in optionalString cfg.oathAuth ''
+           auth sufficient ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}
+         '') + optionalString use_ldap ''
+           auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass
+         '' + optionalString config.krb5.enable ''
+           auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
+           auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
+           auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass
+         '' + ''
+           auth required pam_deny.so
+
+           # Password management.
+           password requisite pam_unix.so nullok sha512
+         '' + optionalString config.security.pam.enableEcryptfs ''
+           password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
+         '' + optionalString cfg.pamMount ''
+           password optional ${pkgs.pam_mount}/lib/security/pam_mount.so
+         '' + optionalString use_ldap ''
+           password sufficient ${pam_ldap}/lib/security/pam_ldap.so
+         '' + optionalString config.krb5.enable ''
+           password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
+         '' + optionalString config.services.samba.syncPasswordsByPam ''
+           password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass
+         '' + ''
+
+           # Session management.
+         '' + optionalString cfg.setEnvironment ''
+           session required pam_env.so envfile=${config.system.build.pamEnvironment}
+         '' + ''
+           session required pam_unix.so
+         '' + optionalString cfg.setLoginUid
               "session ${
                 if config.boot.isContainer then "optional" else "required"
-              } pam_loginuid.so"}
-          ${optionalString cfg.makeHomeDir
-              "session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022"}
-          ${optionalString cfg.updateWtmp
-              "session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
-          ${optionalString config.security.pam.enableEcryptfs
-              "session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
-          ${optionalString use_ldap
-              "session optional ${pam_ldap}/lib/security/pam_ldap.so"}
-          ${optionalString config.krb5.enable
-              "session optional ${pam_krb5}/lib/security/pam_krb5.so"}
-          ${optionalString cfg.otpwAuth
-              "session optional ${pkgs.otpw}/lib/security/pam_otpw.so"}
-          ${optionalString cfg.startSession
-              "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"}
-          ${optionalString cfg.forwardXAuth
-              "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"}
-          ${optionalString (cfg.limits != [])
-              "session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"}
-          ${optionalString (cfg.showMotd && config.users.motd != null)
-              "session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"}
-          ${optionalString cfg.pamMount
-              "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
-          ${optionalString (cfg.enableAppArmor && config.security.apparmor.enable)
-              "session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"}
-        '');
+              } pam_loginuid.so"
+         + optionalString cfg.makeHomeDir ''
+           session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=/etc/skel umask=0022
+         '' + optionalString cfg.updateWtmp ''
+           session required ${pkgs.pam}/lib/security/pam_lastlog.so silent
+         '' + optionalString config.security.pam.enableEcryptfs ''
+           session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
+         '' + optionalString use_ldap ''
+           session optional ${pam_ldap}/lib/security/pam_ldap.so
+         '' + optionalString config.krb5.enable ''
+           session optional ${pam_krb5}/lib/security/pam_krb5.so
+         '' + optionalString cfg.otpwAuth ''
+           session optional ${pkgs.otpw}/lib/security/pam_otpw.so
+         '' + optionalString cfg.startSession ''
+           session optional ${pkgs.systemd}/lib/security/pam_systemd.so
+         '' + optionalString cfg.forwardXAuth ''
+           session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99
+         '' + optionalString (cfg.limits != []) ''
+           session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}
+         '' + optionalString (cfg.showMotd && config.users.motd != null) ''
+           session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}
+         '' + optionalString cfg.pamMount ''
+           session optional ${pkgs.pam_mount}/lib/security/pam_mount.so
+         '' + optionalString (cfg.enableAppArmor && config.security.apparmor.enable) ''
+           session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug
+         '');
     };
 
   };
@@ -477,6 +492,13 @@ in
         vlock = {};
         xlock = {};
         xscreensaver = {};
+
+        runuser = { rootOK = true; unixAuth = false; setEnvironment = false; };
+
+        /* FIXME: should runuser -l start a systemd session? Currently
+           it complains "Cannot create session: Already running in a
+           session". */
+        runuser-l = { rootOK = true; unixAuth = false; };
       };
 
   };
diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix
index dcccd8342866..fe220c94313f 100644
--- a/nixos/modules/security/setuid-wrappers.nix
+++ b/nixos/modules/security/setuid-wrappers.nix
@@ -132,7 +132,7 @@ in
             # Compatibility with old state, just remove the folder and symlink
             rm -f ${wrapperDir}/*
             # if it happens to be a tmpfs
-            umount ${wrapperDir} || true
+            ${pkgs.utillinux}/bin/umount ${wrapperDir} || true
             rm -d ${wrapperDir}
             ln -d --symbolic $wrapperDir ${wrapperDir}
           else
diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
index bced2a6ed757..f5612e1b0c5d 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -74,7 +74,7 @@ in
         Defaults env_keep+=SSH_AUTH_SOCK
 
         # "root" is allowed to do anything.
-        root        ALL=(ALL) SETENV: ALL
+        root        ALL=(ALL:ALL) SETENV: ALL
 
         # Users in the "wheel" group can do anything.
         %wheel      ALL=(ALL:ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix
index 029b14ab4726..c0a0f0374294 100644
--- a/nixos/modules/services/audio/mopidy.nix
+++ b/nixos/modules/services/audio/mopidy.nix
@@ -21,13 +21,7 @@ in {
 
     services.mopidy = {
 
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Whether to enable Mopidy, a music player daemon.
-        '';
-      };
+      enable = mkEnableOption "Mopidy, a music player daemon";
 
       dataDir = mkOption {
         default = "/var/lib/mopidy";
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index 5d5fef667941..85e0a7d2ac4e 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -33,6 +33,7 @@ in {
     services.mpd = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = ''
           Whether to enable MPD, the music player daemon.
@@ -40,6 +41,7 @@ in {
       };
 
       musicDirectory = mkOption {
+        type = types.path;
         default = "${cfg.dataDir}/music";
         description = ''
           The directory where mpd reads music from.
@@ -47,6 +49,7 @@ in {
       };
 
       extraConfig = mkOption {
+        type = types.str;
         default = "";
         description = ''
           Extra directives added to to the end of MPD's configuration file,
@@ -56,6 +59,7 @@ in {
       };
 
       dataDir = mkOption {
+        type = types.path;
         default = "/var/lib/mpd";
         description = ''
           The directory where MPD stores its state, tag cache,
@@ -64,11 +68,13 @@ in {
       };
 
       user = mkOption {
+        type = types.str;
         default = "mpd";
         description = "User account under which MPD runs.";
       };
 
       group = mkOption {
+        type = types.str;
         default = "mpd";
         description = "Group account under which MPD runs.";
       };
@@ -76,6 +82,7 @@ in {
       network = {
 
         listenAddress = mkOption {
+          type = types.str;
           default = "any";
           description = ''
             This setting sets the address for the daemon to listen on. Careful attention
@@ -85,6 +92,7 @@ in {
         };
 
         port = mkOption {
+          type = types.int;
           default = 6600;
           description = ''
             This setting is the TCP port that is desired for the daemon to get assigned
@@ -114,12 +122,12 @@ in {
       after = [ "network.target" "sound.target" ];
       description = "Music Player Daemon";
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.mpd ];
+
       preStart = "mkdir -p ${cfg.dataDir} && chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}";
-      script = "exec mpd --no-daemon ${mpdConf}";
       serviceConfig = {
         User = "${cfg.user}";
         PermissionsStartOnly = true;
+        ExecStart = "${pkgs.mpd}/bin/mpd --no-daemon ${mpdConf}";
       };
     };
 
diff --git a/nixos/modules/services/audio/ympd.nix b/nixos/modules/services/audio/ympd.nix
new file mode 100644
index 000000000000..d34c1c9d83cc
--- /dev/null
+++ b/nixos/modules/services/audio/ympd.nix
@@ -0,0 +1,57 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.ympd;
+in {
+
+  ###### interface
+
+  options = {
+
+    services.ympd = {
+
+      enable = mkEnableOption "ympd, the MPD Web GUI";
+
+      webPort = mkOption {
+        type = types.string;
+        default = "8080";
+        description = "The port where ympd's web interface will be available.";
+        example = "ssl://8080:/path/to/ssl-private-key.pem";
+      };
+
+      mpd = {
+        host = mkOption {
+          type = types.string;
+          default = "localhost";
+          description = "The host where MPD is listening.";
+          example = "localhost";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = config.services.mpd.network.port;
+          description = "The port where MPD is listening.";
+          example = 6600;
+        };
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.ympd = {
+      description = "Standalone MPD Web GUI written in C";
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig.ExecStart = "${pkgs.ympd}/bin/ympd --host ${cfg.mpd.host} --port ${toString cfg.mpd.port} --webport ${cfg.webPort} --user nobody";
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/continuous-integration/gocd-agent/default.nix b/nixos/modules/services/continuous-integration/gocd-agent/default.nix
index 21f319f7fcf6..d60b55e83d11 100644
--- a/nixos/modules/services/continuous-integration/gocd-agent/default.nix
+++ b/nixos/modules/services/continuous-integration/gocd-agent/default.nix
@@ -98,7 +98,7 @@ in {
         ];
         description = ''
           Specifies startup command line arguments to pass to Go.CD agent
-          java process.  Example contains debug and gcLog arguments.
+          java process.
         '';
       };
 
diff --git a/nixos/modules/services/continuous-integration/gocd-server/default.nix b/nixos/modules/services/continuous-integration/gocd-server/default.nix
index 2d1986301216..4bb792055d25 100644
--- a/nixos/modules/services/continuous-integration/gocd-server/default.nix
+++ b/nixos/modules/services/continuous-integration/gocd-server/default.nix
@@ -90,7 +90,7 @@ in {
         '';
       };
 
-      extraOptions = mkOption {
+      startupOptions = mkOption {
         default = [
           "-Xms${cfg.initialJavaHeapSize}"
           "-Xmx${cfg.maxJavaHeapMemory}"
@@ -103,6 +103,15 @@ in {
           "-Dcruise.server.port=${toString cfg.port}"
           "-Dcruise.server.ssl.port=${toString cfg.sslPort}"
         ];
+
+        description = ''
+          Specifies startup command line arguments to pass to Go.CD server
+          java process.
+        '';
+      };
+
+      extraOptions = mkOption {
+        default = [ ];
         example = [ 
           "-X debug" 
           "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
@@ -169,7 +178,8 @@ in {
 
       script = ''
         ${pkgs.git}/bin/git config --global --add http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
-        ${pkgs.jre}/bin/java -server ${concatStringsSep " " cfg.extraOptions} \
+        ${pkgs.jre}/bin/java -server ${concatStringsSep " " cfg.startupOptions} \
+                               ${concatStringsSep " " cfg.extraOptions}  \
                               -jar ${pkgs.gocd-server}/go-server/go.jar
       '';
 
diff --git a/nixos/modules/services/databases/4store-endpoint.nix b/nixos/modules/services/databases/4store-endpoint.nix
index 5c55ef406d57..906cb320df98 100644
--- a/nixos/modules/services/databases/4store-endpoint.nix
+++ b/nixos/modules/services/databases/4store-endpoint.nix
@@ -61,7 +61,9 @@ with lib;
     services.avahi.enable = true;
 
     systemd.services."4store-endpoint" = {
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
       script = ''
         ${run} '${pkgs.rdf4store}/bin/4s-httpd -D ${cfg.options} ${if cfg.listenAddress!=null then "-H ${cfg.listenAddress}" else "" } -p ${toString cfg.port} ${cfg.database}'
       '';
diff --git a/nixos/modules/services/databases/4store.nix b/nixos/modules/services/databases/4store.nix
index 33e731e96816..62856822f906 100644
--- a/nixos/modules/services/databases/4store.nix
+++ b/nixos/modules/services/databases/4store.nix
@@ -53,7 +53,8 @@ with lib;
     services.avahi.enable = true;
 
     systemd.services."4store" = {
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
 
       preStart = ''
         mkdir -p ${stateDir}/
diff --git a/nixos/modules/services/databases/virtuoso.nix b/nixos/modules/services/databases/virtuoso.nix
index bdd210a2550e..3231fede08fa 100644
--- a/nixos/modules/services/databases/virtuoso.nix
+++ b/nixos/modules/services/databases/virtuoso.nix
@@ -62,7 +62,8 @@ with lib;
       };
 
     systemd.services.virtuoso = {
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
 
       preStart = ''
         mkdir -p ${stateDir}
diff --git a/nixos/modules/services/editors/emacs.nix b/nixos/modules/services/editors/emacs.nix
index 6795ec52fe4d..08fa6de6374c 100644
--- a/nixos/modules/services/editors/emacs.nix
+++ b/nixos/modules/services/editors/emacs.nix
@@ -79,9 +79,13 @@ in {
 
     environment.systemPackages = [ cfg.package editorScript ];
 
-    environment.variables = if cfg.defaultEditor then {
-      EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor";
-    } else {};
+    environment.variables = {
+      # This is required so that GTK applications launched from Emacs
+      # get properly themed:
+      GTK_DATA_PREFIX = "${config.system.path}";
+    } // (if cfg.defaultEditor then {
+        EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor";
+      } else {});
   };
 
   meta.doc = ./emacs.xml;
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index f239dda564a2..e79d5dadd828 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -271,6 +271,9 @@ in
       { assertion = cfg.showPAMFailure -> cfg.enablePAM;
         message = "dovecot is configured with showPAMFailure while enablePAM is disabled";
       }
+      { assertion = (cfg.sieveScripts != {}) -> ((cfg.mailUser != null) && (cfg.mailGroup != null));
+        message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set";
+      }
     ];
 
   };
diff --git a/nixos/modules/services/mail/freepops.nix b/nixos/modules/services/mail/freepops.nix
index e8c30a36923f..5b729ca50a5e 100644
--- a/nixos/modules/services/mail/freepops.nix
+++ b/nixos/modules/services/mail/freepops.nix
@@ -74,7 +74,8 @@ in
   config = mkIf cfg.enable {
     systemd.services.freepopsd = {
       description = "Freepopsd (webmail over POP3)";
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
       script = ''
         ${pkgs.freepops}/bin/freepopsd \
           -p ${toString cfg.port} \
diff --git a/nixos/modules/services/misc/docker-registry.nix b/nixos/modules/services/misc/docker-registry.nix
deleted file mode 100644
index add339f9bdfe..000000000000
--- a/nixos/modules/services/misc/docker-registry.nix
+++ /dev/null
@@ -1,81 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.dockerRegistry;
-
-in {
-  ###### interface
-
-  options.services.dockerRegistry = {
-    enable = mkOption {
-      description = "Whether to enable docker registry server.";
-      default = false;
-      type = types.bool;
-    };
-
-    listenAddress = mkOption {
-      description = "Docker registry host or ip to bind to.";
-      default = "127.0.0.1";
-      type = types.str;
-    };
-
-    port = mkOption {
-      description = "Docker registry port to bind to.";
-      default = 5000;
-      type = types.int;
-    };
-
-    storagePath = mkOption {
-      type = types.path;
-      default = "/var/lib/docker-registry";
-      description = "Docker registry storage path.";
-    };
-
-    extraConfig = mkOption {
-      description = ''
-        Docker extra registry configuration. See
-        <link xlink:href="https://github.com/docker/docker-registry/blob/master/config/config_sample.yml"/>
-      '';
-      default = {};
-      type = types.attrsOf types.str;
-    };
-  };
-
-  config = mkIf cfg.enable {
-    systemd.services.docker-registry = {
-      description = "Docker Container Registry";
-      wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
-
-      environment = {
-        REGISTRY_HOST = cfg.listenAddress;
-        REGISTRY_PORT = toString cfg.port;
-        GUNICORN_OPTS = "[--preload]"; # see https://github.com/docker/docker-registry#sqlalchemy
-        STORAGE_PATH = cfg.storagePath;
-      } // cfg.extraConfig;
-
-      serviceConfig = {
-        ExecStart = "${pkgs.pythonPackages.docker_registry}/bin/docker-registry";
-        User = "docker-registry";
-        Group = "docker";
-        PermissionsStartOnly = true;
-        WorkingDirectory = cfg.storagePath;
-      };
-
-      postStart = ''
-        until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.listenAddress}:${toString cfg.port}/'; do
-          sleep 1;
-        done
-      '';
-    };
-
-    users.extraGroups.docker.gid = mkDefault config.ids.gids.docker;
-    users.extraUsers.docker-registry = {
-      createHome = true;
-      home = cfg.storagePath;
-      uid = config.ids.uids.docker-registry;
-    };
-  };
-}
diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix
new file mode 100644
index 000000000000..31979d2660cc
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/default.nix
@@ -0,0 +1,418 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus;
+  promUser = "prometheus";
+  promGroup = "prometheus";
+
+  # Get a submodule without any embedded metadata:
+  _filter = x: filterAttrs (k: v: k != "_module") x;
+
+  # Pretty-print JSON to a file
+  writePrettyJSON = name: x:
+    pkgs.runCommand name { } ''
+      echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out
+    '';
+
+  # This becomes the main config file
+  promConfig = {
+    global = cfg.globalConfig;
+    rule_files = cfg.ruleFiles ++ [
+      (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules))
+    ];
+    scrape_configs = cfg.scrapeConfigs;
+  };
+
+  cmdlineArgs = cfg.extraFlags ++ [
+    "-storage.local.path=${cfg.dataDir}/metrics"
+    "-config.file=${writePrettyJSON "prometheus.yml" promConfig}"
+    "-web.listen-address=${cfg.listenAddress}"
+  ];
+
+  promTypes.globalConfig = types.submodule {
+    options = {
+      scrape_interval = mkOption {
+        type = types.str;
+        default = "1m";
+        description = ''
+          How frequently to scrape targets by default.
+        '';
+      };
+
+      scrape_timeout = mkOption {
+        type = types.str;
+        default = "10s";
+        description = ''
+          How long until a scrape request times out.
+        '';
+      };
+
+      evaluation_interval = mkOption {
+        type = types.str;
+        default = "1m";
+        description = ''
+          How frequently to evaluate rules by default.
+        '';
+      };
+
+      labels = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        description = ''
+          The labels to add to any timeseries that this Prometheus instance
+          scrapes.
+        '';
+      };
+    };
+  };
+
+  promTypes.scrape_config = types.submodule {
+    options = {
+      job_name = mkOption {
+        type = types.str;
+        description = ''
+          The job name assigned to scraped metrics by default.
+        '';
+      };
+      scrape_interval = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          How frequently to scrape targets from this job. Defaults to the
+          globally configured default.
+        '';
+      };
+      scrape_timeout = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Per-target timeout when scraping this job. Defaults to the
+          globally configured default.
+        '';
+      };
+      metrics_path = mkOption {
+        type = types.str;
+        default = "/metrics";
+        description = ''
+          The HTTP resource path on which to fetch metrics from targets.
+        '';
+      };
+      scheme = mkOption {
+        type = types.enum ["http" "https"];
+        default = "http";
+        description = ''
+          The URL scheme with which to fetch metrics from targets.
+        '';
+      };
+      basic_auth = mkOption {
+        type = types.nullOr (types.submodule {
+          options = {
+            username = mkOption {
+              type = types.str;
+              description = ''
+                HTTP username
+              '';
+            };
+            password = mkOption {
+              type = types.str;
+              description = ''
+                HTTP password
+              '';
+            };
+          };
+        });
+        default = null;
+        description = ''
+          Optional http login credentials for metrics scraping.
+        '';
+      };
+      dns_sd_configs = mkOption {
+        type = types.listOf promTypes.dns_sd_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          List of DNS service discovery configurations.
+        '';
+      };
+      consul_sd_configs = mkOption {
+        type = types.listOf promTypes.consul_sd_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          List of Consul service discovery configurations.
+        '';
+      };
+      file_sd_configs = mkOption {
+        type = types.listOf promTypes.file_sd_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          List of file service discovery configurations.
+        '';
+      };
+      static_configs = mkOption {
+        type = types.listOf promTypes.static_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          List of labeled target groups for this job.
+        '';
+      };
+      relabel_configs = mkOption {
+        type = types.listOf promTypes.relabel_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          List of relabel configurations.
+        '';
+      };
+    };
+  };
+
+  promTypes.static_config = types.submodule {
+    options = {
+      targets = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          The targets specified by the target group.
+        '';
+      };
+      labels = mkOption {
+        type = types.attrsOf types.str;
+        description = ''
+          Labels assigned to all metrics scraped from the targets.
+        '';
+      };
+    };
+  };
+
+  promTypes.dns_sd_config = types.submodule {
+    options = {
+      names = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          A list of DNS SRV record names to be queried.
+        '';
+      };
+      refresh_interval = mkOption {
+        type = types.str;
+        default = "30s";
+        description = ''
+          The time after which the provided names are refreshed.
+        '';
+      };
+    };
+  };
+
+  promTypes.consul_sd_config = types.submodule {
+    options = {
+      server = mkOption {
+        type = types.str;
+        description = "Consul server to query.";
+      };
+      token = mkOption {
+        type = types.nullOr types.str;
+        description = "Consul token";
+      };
+      datacenter = mkOption {
+        type = types.nullOr types.str;
+        description = "Consul datacenter";
+      };
+      scheme = mkOption {
+        type = types.nullOr types.str;
+        description = "Consul scheme";
+      };
+      username = mkOption {
+        type = types.nullOr types.str;
+        description = "Consul username";
+      };
+      password = mkOption {
+        type = types.nullOr types.str;
+        description = "Consul password";
+      };
+
+      services = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          A list of services for which targets are retrieved.
+        '';
+      };
+      tag_separator = mkOption {
+        type = types.str;
+        default = ",";
+        description = ''
+          The string by which Consul tags are joined into the tag label.
+        '';
+      };
+    };
+  };
+
+  promTypes.file_sd_config = types.submodule {
+    options = {
+      files = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          Patterns for files from which target groups are extracted. Refer
+          to the Prometheus documentation for permitted filename patterns
+          and formats.
+
+        '';
+      };
+      refresh_interval = mkOption {
+        type = types.str;
+        default = "30s";
+        description = ''
+          Refresh interval to re-read the files.
+        '';
+      };
+    };
+  };
+
+  promTypes.relabel_config = types.submodule {
+    options = {
+      source_labels = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          The source labels select values from existing labels. Their content
+          is concatenated using the configured separator and matched against
+          the configured regular expression.
+        '';
+      };
+      separator = mkOption {
+        type = types.str;
+        default = ";";
+        description = ''
+          Separator placed between concatenated source label values.
+        '';
+      };
+      target_label = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Label to which the resulting value is written in a replace action.
+          It is mandatory for replace actions.
+        '';
+      };
+      regex = mkOption {
+        type = types.str;
+        description = ''
+          Regular expression against which the extracted value is matched.
+        '';
+      };
+      replacement = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Replacement value against which a regex replace is performed if the
+          regular expression matches.
+        '';
+      };
+      action = mkOption {
+        type = types.enum ["replace" "keep" "drop"];
+        description = ''
+          Action to perform based on regex matching.
+        '';
+      };
+    };
+  };
+
+in {
+  options = {
+    services.prometheus = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the Prometheus monitoring daemon.
+        '';
+      };
+
+      listenAddress = mkOption {
+        type = types.str;
+        default = "0.0.0.0:9090";
+        description = ''
+          Address to listen on for the web interface, API, and telemetry.
+        '';
+      };
+
+      dataDir = mkOption {
+        type = types.path;
+        default = "/var/lib/prometheus";
+        description = ''
+          Directory to store Prometheus metrics data.
+        '';
+      };
+
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Extra commandline options when launching Prometheus.
+        '';
+      };
+
+      globalConfig = mkOption {
+        type = promTypes.globalConfig;
+        default = {};
+        apply = _filter;
+        description = ''
+          Parameters that are valid in all  configuration contexts. They
+          also serve as defaults for other configuration sections
+        '';
+      };
+
+      rules = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Alerting and/or Recording rules to evaluate at runtime.
+        '';
+      };
+
+      ruleFiles = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          Any additional rules files to include in this configuration.
+        '';
+      };
+
+      scrapeConfigs = mkOption {
+        type = types.listOf promTypes.scrape_config;
+        default = [];
+        apply = x: map _filter x;
+        description = ''
+          A list of scrape configurations.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraGroups.${promGroup}.gid = config.ids.gids.prometheus;
+    users.extraUsers.${promUser} = {
+      description = "Prometheus daemon user";
+      uid = config.ids.uids.prometheus;
+      group = promGroup;
+      home = cfg.dataDir;
+      createHome = true;
+    };
+    systemd.services.prometheus = {
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network.target" ];
+      script = ''
+        #!/bin/sh
+        exec ${pkgs.prometheus}/bin/prometheus \
+          ${concatStringsSep " \\\n  " cmdlineArgs}
+      '';
+      serviceConfig = {
+        User = promUser;
+        Restart  = "always";
+        WorkingDirectory = cfg.dataDir;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/prometheus/node-exporter.nix b/nixos/modules/services/monitoring/prometheus/node-exporter.nix
new file mode 100644
index 000000000000..02aedb53564d
--- /dev/null
+++ b/nixos/modules/services/monitoring/prometheus/node-exporter.nix
@@ -0,0 +1,74 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.prometheus.nodeExporter;
+  cmdlineArgs = cfg.extraFlags ++ [
+    "-web.listen-address=${cfg.listenAddress}"
+  ];
+in {
+  options = {
+    services.prometheus.nodeExporter = {
+      enable = mkEnableOption "prometheus node exporter";
+
+      port = mkOption {
+        type = types.int;
+        default = 9100;
+        description = ''
+          Port to listen on.
+        '';
+      };
+
+      listenAddress = mkOption {
+        type = types.string;
+        default = "0.0.0.0";
+        description = ''
+          Address to listen on.
+        '';
+      };
+
+      enabledCollectors = mkOption {
+        type = types.listOf types.string;
+        default = [];
+        example = ''[ "systemd" ]'';
+        description = ''
+          Collectors to enable, additionally to the defaults.
+        '';
+      };
+
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Extra commandline options when launching the node exporter.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    networking.firewall.allowedTCPPorts = [ cfg.port ];
+
+    systemd.services.prometheus-node-exporter = {
+      description = "Prometheus exporter for machine metrics";
+      unitConfig.Documentation = "https://github.com/prometheus/node_exporter";
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network.target" ];
+      script = ''
+        exec ${pkgs.prometheus-node-exporter}/bin/node_exporter \
+          ${optionalString (cfg.enabledCollectors != [])
+            ''-collectors.enabled ${concatStringsSep "," cfg.enabledCollectors}''} \
+          -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+          ${concatStringsSep " \\\n  " cfg.extraFlags}
+      '';
+      serviceConfig = {
+        User = "nobody";
+        Restart  = "always";
+        PrivateTmp = true;
+        WorkingDirectory = /tmp;
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/ups.nix b/nixos/modules/services/monitoring/ups.nix
index 5f80d547dbcb..febf0c95f5bd 100644
--- a/nixos/modules/services/monitoring/ups.nix
+++ b/nixos/modules/services/monitoring/ups.nix
@@ -182,7 +182,8 @@ in
 
     systemd.services.upsmon = {
       description = "Uninterruptible Power Supplies (Monitor)";
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
       serviceConfig.Type = "forking";
       script = "${pkgs.nut}/sbin/upsmon";
       environment.NUT_CONFPATH = "/etc/nut/";
@@ -191,8 +192,8 @@ in
 
     systemd.services.upsd = {
       description = "Uninterruptible Power Supplies (Daemon)";
+      after = [ "network.target" "upsmon.service" ];
       wantedBy = [ "multi-user.target" ];
-      after = [ "network-interfaces.target" "upsmon.service" ];
       serviceConfig.Type = "forking";
       # TODO: replace 'root' by another username.
       script = "${pkgs.nut}/sbin/upsd -u root";
@@ -202,8 +203,8 @@ in
 
     systemd.services.upsdrv = {
       description = "Uninterruptible Power Supplies (Register all UPS)";
-      wantedBy = [ "multi-user.target" ];
       after = [ "upsd.service" ];
+      wantedBy = [ "multi-user.target" ];
       # TODO: replace 'root' by another username.
       script = ''${pkgs.nut}/bin/upsdrvctl -u root start'';
       serviceConfig = {
diff --git a/nixos/modules/services/network-filesystems/drbd.nix b/nixos/modules/services/network-filesystems/drbd.nix
index 9896a93b1894..57b1fbb597c7 100644
--- a/nixos/modules/services/network-filesystems/drbd.nix
+++ b/nixos/modules/services/network-filesystems/drbd.nix
@@ -53,9 +53,9 @@ let cfg = config.services.drbd; in
       };
 
     systemd.services.drbd = {
-      after = [ "systemd-udev.settle.service" ];
+      after = [ "systemd-udev.settle.service" "network.target" ];
       wants = [ "systemd-udev.settle.service" ];
-      wantedBy = [ "ip-up.target" ];
+      wantedBy = [ "multi-user.target" ];
       script = ''
         ${pkgs.drbd}/sbin/drbdadm up all
       '';
diff --git a/nixos/modules/services/networking/amuled.nix b/nixos/modules/services/networking/amuled.nix
index bc488d0e9100..fc7d56a24fa7 100644
--- a/nixos/modules/services/networking/amuled.nix
+++ b/nixos/modules/services/networking/amuled.nix
@@ -59,7 +59,8 @@ in
 
     systemd.services.amuled = {
       description = "AMule daemon";
-      wantedBy = [ "ip-up.target" ];
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
 
       preStart = ''
         mkdir -p ${cfg.dataDir}
diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix
index 7650f45c5570..ecc091d1d03d 100644
--- a/nixos/modules/services/networking/avahi-daemon.nix
+++ b/nixos/modules/services/networking/avahi-daemon.nix
@@ -7,10 +7,6 @@ let
 
   cfg = config.services.avahi;
 
-  # We must escape interfaces due to the systemd interpretation
-  subsystemDevice = interface:
-    "sys-subsystem-net-devices-${utils.escapeSystemdPath interface}.device";
-
   avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" ''
     [server]
     ${# Users can set `networking.hostName' to the empty string, when getting
@@ -75,7 +71,8 @@ in
       };
 
       browseDomains = mkOption {
-        default = [ "0pointer.de" "zeroconf.org" ];
+        default = [ ];
+        example = [ "0pointer.de" "zeroconf.org" ];
         description = ''
           List of non-local DNS domains to be browsed.
         '';
@@ -179,14 +176,8 @@ in
     environment.systemPackages = [ pkgs.avahi ];
 
     systemd.services.avahi-daemon =
-      let
-        deps = optionals (cfg.interfaces!=null) (map subsystemDevice cfg.interfaces);
-      in
       { description = "Avahi daemon";
-        wantedBy = [ "ip-up.target" ];
-        bindsTo = deps;
-        after = deps;
-        before = [ "ip-up.target" ];
+        wantedBy = [ "multi-user.target" ];
         # Receive restart event after resume
         partOf = [ "post-resume.target" ];
 
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index b31d479ab4fd..4b0e90886510 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -10,7 +10,8 @@ let
 
   interfaces = attrValues config.networking.interfaces;
 
-  enableDHCP = config.networking.useDHCP || any (i: i.useDHCP == true) interfaces;
+  enableDHCP = config.networking.dhcpcd.enable &&
+        (config.networking.useDHCP || any (i: i.useDHCP == true) interfaces);
 
   # Don't start dhcpcd on explicitly configured interfaces or on
   # interfaces that are part of a bridge, bond or sit device.
@@ -61,7 +62,6 @@ let
       ${cfg.extraConfig}
     '';
 
-  # Hook for emitting ip-up/ip-down events.
   exitHook = pkgs.writeText "dhcpcd.exit-hook"
     ''
       if [ "$reason" = BOUND -o "$reason" = REBOOT ]; then
@@ -73,14 +73,8 @@ let
           # applies to openntpd.
           ${config.systemd.package}/bin/systemctl try-restart ntpd.service
           ${config.systemd.package}/bin/systemctl try-restart openntpd.service
-
-          ${config.systemd.package}/bin/systemctl start ip-up.target
       fi
 
-      #if [ "$reason" = EXPIRE -o "$reason" = RELEASE -o "$reason" = NOCARRIER ] ; then
-      #    ${config.systemd.package}/bin/systemctl start ip-down.target
-      #fi
-
       ${cfg.runHook}
     '';
 
@@ -92,6 +86,15 @@ in
 
   options = {
 
+    networking.dhcpcd.enable = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to enable dhcpcd for device configuration. This is mainly to
+        explicitly disable dhcpcd (for example when using networkd).
+      '';
+    };
+
     networking.dhcpcd.persistent = mkOption {
       type = types.bool;
       default = false;
@@ -154,10 +157,9 @@ in
     systemd.services.dhcpcd =
       { description = "DHCP Client";
 
-        wantedBy = [ "network.target" ];
-        # Work-around to deal with problems where the kernel would remove &
-        # re-create Wifi interfaces early during boot.
-        after = [ "network-interfaces.target" ];
+        wantedBy = [ "multi-user.target" ];
+        wants = [ "network.target" ];
+        before = [ "network.target" ];
 
         # Stopping dhcpcd during a reconfiguration is undesirable
         # because it brings down the network interfaces configured by
diff --git a/nixos/modules/services/networking/docker-registry-server.nix b/nixos/modules/services/networking/docker-registry-server.nix
deleted file mode 100644
index d21bbb6a86c3..000000000000
--- a/nixos/modules/services/networking/docker-registry-server.nix
+++ /dev/null
@@ -1,98 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.nodeDockerRegistry;
-
-in {
-  options.services.nodeDockerRegistry = {
-    enable = mkEnableOption "docker registry service";
-
-    port = mkOption {
-      description = "Docker registry listening port.";
-      default = 8080;
-      type = types.int;
-    };
-
-    users = mkOption {
-      description = "Docker registry list of users.";
-      default = [];
-      options = [{
-        user = mkOption {
-          description = "Docker registry user username.";
-          type = types.str;
-        };
-
-        pass = mkOption {
-          description = "Docker registry user password.";
-          type = types.str;
-        };
-      }];
-      type = types.listOf types.optionSet;
-    };
-
-    onTag = mkOption {
-      description = "Docker registry hook triggered when an image is tagged.";
-      default = "";
-      type = types.str;
-    };
-
-    onImage = mkOption {
-      description = "Docker registry hook triggered when an image metadata is uploaded.";
-      default = "";
-      type = types.str;
-    };
-
-    onLayer = mkOption {
-      description = "Docker registry hook triggered when an when an image layer is uploaded.";
-      default = "";
-      type = types.str;
-    };
-
-    onVerify = mkOption {
-      description = "Docker registry hook triggered when an image layer+metadata has been verified.";
-      default = "";
-      type = types.str;
-    };
-
-    onIndex = mkOption {
-      description = "Docker registry hook triggered when an when an image file system data has been indexed.";
-      default = "";
-      type = types.str;
-    };
-
-    dataDir = mkOption {
-      description = "Docker registry data directory";
-      default = "/var/lib/docker-registry";
-      type = types.path;
-    };
-  };
-
-  config = mkIf cfg.enable {
-    systemd.services.docker-registry-server = {
-      description = "Docker Registry Service.";
-      wantedBy = ["multi-user.target"];
-      after = ["network.target"];
-      script = ''
-        ${pkgs.nodePackages.docker-registry-server}/bin/docker-registry-server \
-          --dir ${cfg.dataDir} \
-          --port ${toString cfg.port} \
-          ${concatMapStringsSep " " (u: "--user ${u.user}:${u.pass}") cfg.users} \
-          ${optionalString (cfg.onTag != "") "--on-tag '${cfg.onTag}'"} \
-          ${optionalString (cfg.onImage != "") "--on-image '${cfg.onImage}'"} \
-          ${optionalString (cfg.onVerify != "") "--on-verify '${cfg.onVerify}'"} \
-          ${optionalString (cfg.onIndex != "") "--on-index '${cfg.onIndex}'"}
-      '';
-
-      serviceConfig.User = "docker-registry";
-    };
-
-    users.extraUsers.docker-registry = {
-      uid = config.ids.uids.docker-registry;
-      description = "Docker registry user";
-      createHome = true;
-      home = cfg.dataDir;
-    };
-  };
-}
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index 138153306dd8..942fcc03f59b 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -490,7 +490,8 @@ in
 
     systemd.services.firewall = {
       description = "Firewall";
-      wantedBy = [ "network-pre.target" ];
+      wantedBy = [ "sysinit.target" ];
+      wants = [ "network-pre.target" ];
       before = [ "network-pre.target" ];
       after = [ "systemd-modules-load.service" ];
 
@@ -500,6 +501,7 @@ in
       # containers don't have CAP_SYS_MODULE. So the host system had
       # better have all necessary modules already loaded.
       unitConfig.ConditionCapability = "CAP_NET_ADMIN";
+      unitConfig.DefaultDependencies = false;
 
       reloadIfChanged = true;
 
diff --git a/nixos/modules/services/networking/git-daemon.nix b/nixos/modules/services/networking/git-daemon.nix
index 215ffe48a563..cd3fcd0f8f66 100644
--- a/nixos/modules/services/networking/git-daemon.nix
+++ b/nixos/modules/services/networking/git-daemon.nix
@@ -116,7 +116,8 @@ in
       };
 
     systemd.services."git-daemon" = {
-      wantedBy = [ "ip-up.target" ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
       script = "${pkgs.git}/bin/git daemon --reuseaddr "
         + (optionalString (cfg.basePath != "") "--base-path=${cfg.basePath} ")
         + (optionalString (cfg.listenAddress != "") "--listen=${cfg.listenAddress} ")
diff --git a/nixos/modules/services/networking/iodine.nix b/nixos/modules/services/networking/iodine.nix
index 1b0d2d9a517c..512dbd77ae4b 100644
--- a/nixos/modules/services/networking/iodine.nix
+++ b/nixos/modules/services/networking/iodine.nix
@@ -106,7 +106,8 @@ in
       createIodineClientService = name: cfg:
       {
         description = "iodine client - ${name}";
-        wantedBy = [ "ip-up.target" ];
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           RestartSec = "30s";
           Restart = "always";
@@ -121,7 +122,8 @@ in
     ) // {
       iodined = mkIf (cfg.server.enable) {
         description = "iodine, ip over dns server daemon";
-        wantedBy = [ "ip-up.target" ];
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
         serviceConfig.ExecStart = "${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${cfg.server.ip} ${cfg.server.domain}";
       };
     };
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index d198e3bfc02c..65ffaece4772 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -52,14 +52,6 @@ let
     });
   '';
 
-  ipUpScript = writeScript "01nixos-ip-up" ''
-    #!/bin/sh
-    if test "$2" = "up"; then
-      ${config.systemd.package}/bin/systemctl start ip-up.target
-      ${config.systemd.package}/bin/systemctl start network-online.target
-    fi
-  '';
-
   ns = xs: writeText "nameservers" (
     concatStrings (map (s: "nameserver ${s}\n") xs)
   );
@@ -188,9 +180,6 @@ in {
     boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections.
 
     environment.etc = with cfg.basePackages; [
-      { source = ipUpScript;
-        target = "NetworkManager/dispatcher.d/01nixos-ip-up";
-      }
       { source = configFile;
         target = "NetworkManager/NetworkManager.conf";
       }
diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix
index 19762f4e570c..d5e2e3041b49 100644
--- a/nixos/modules/services/networking/radicale.nix
+++ b/nixos/modules/services/networking/radicale.nix
@@ -52,8 +52,7 @@ in
       description = "A Simple Calendar and Contact Server";
       after = [ "network-interfaces.target" ];
       wantedBy = [ "multi-user.target" ];
-      script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -d";
-      serviceConfig.Type = "forking";
+      script = "${pkgs.pythonPackages.radicale}/bin/radicale -C ${confFile} -f";
       serviceConfig.User = "radicale";
       serviceConfig.Group = "radicale";
     };
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index f900ef494abf..1d15a1419722 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -85,7 +85,7 @@ in
 
       forwardX11 = mkOption {
         type = types.bool;
-        default = cfgc.setXAuthLocation;
+        default = false;
         description = ''
           Whether to allow X11 connections to be forwarded.
         '';
@@ -227,6 +227,8 @@ in
 
   config = mkIf cfg.enable {
 
+    programs.ssh.setXAuthLocation = mkForce cfg.forwardX11;
+
     users.extraUsers.sshd =
       { isSystemUser = true;
         description = "SSH privilege separation user";
diff --git a/nixos/modules/services/networking/toxvpn.nix b/nixos/modules/services/networking/toxvpn.nix
index c38424c8e273..911836fdee42 100644
--- a/nixos/modules/services/networking/toxvpn.nix
+++ b/nixos/modules/services/networking/toxvpn.nix
@@ -25,8 +25,8 @@ with lib;
     systemd.services.toxvpn = {
       description = "toxvpn daemon";
 
-      requires = [ "network-online.target" ]; # consider replacing by NetworkManager-wait-online.service
       wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
 
       preStart = ''
         mkdir -p /run/toxvpn || true
diff --git a/nixos/modules/services/security/haveged.nix b/nixos/modules/services/security/haveged.nix
index 2aa523bf70a4..eca529188810 100644
--- a/nixos/modules/services/security/haveged.nix
+++ b/nixos/modules/services/security/haveged.nix
@@ -48,14 +48,18 @@ in
       { description = "Entropy Harvesting Daemon";
         unitConfig.Documentation = "man:haveged(8)";
         wantedBy = [ "multi-user.target" ];
-        
+
         path = [ pkgs.haveged ];
-        
-        serviceConfig = 
-          { Type = "forking";
-            ExecStart = "${pkgs.haveged}/sbin/haveged -w ${toString cfg.refill_threshold} -v 1";
-            PIDFile = "/run/haveged.pid";
-          };
+
+        serviceConfig = {
+          ExecStart = "${pkgs.haveged}/bin/haveged -F -w ${toString cfg.refill_threshold} -v 1";
+          SuccessExitStatus = 143;
+          PrivateTmp = true;
+          PrivateDevices = true;
+          PrivateNetwork = true;
+          ProtectSystem = "full";
+          ProtectHome = true;
+        };
       };
 
   };
diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix
index 8bcd6f01656d..6c4833afbe8b 100644
--- a/nixos/modules/services/system/dbus.nix
+++ b/nixos/modules/services/system/dbus.nix
@@ -84,7 +84,7 @@ in
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus_tools ];
+    environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ];
 
     environment.etc = singleton
       { source = configDir;
@@ -104,7 +104,7 @@ in
 
     security.setuidOwners = singleton
       { program = "dbus-daemon-launch-helper";
-        source = "${pkgs.dbus_daemon.out}/libexec/dbus-daemon-launch-helper";
+        source = "${pkgs.dbus.daemon}/libexec/dbus-daemon-launch-helper";
         owner = "root";
         group = "messagebus";
         setuid = true;
diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix
index ea7196fc8733..051d54e932fb 100644
--- a/nixos/modules/services/ttys/agetty.nix
+++ b/nixos/modules/services/ttys/agetty.nix
@@ -80,8 +80,7 @@ in
       };
 
     systemd.services."container-getty@" =
-      { unitConfig.ConditionPathExists = "/dev/pts/%I"; # Work around being respawned when "machinectl login" exits.
-        serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM";
+      { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM";
         restartIfChanged = false;
       };
 
diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix
index b08070f1e366..5193814da725 100644
--- a/nixos/modules/services/web-apps/tt-rss.nix
+++ b/nixos/modules/services/web-apps/tt-rss.nix
@@ -18,7 +18,6 @@ let
 
   poolName = "tt-rss";
   phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock";
-  virtualHostName = "tt-rss";
 
   tt-rss-config = pkgs.writeText "config.php" ''
     <?php
@@ -34,10 +33,10 @@ let
       define('MYSQL_CHARSET', 'UTF8');
 
       define('DB_TYPE', '${cfg.database.type}');
-      define('DB_HOST', '${cfg.database.host}');
+      define('DB_HOST', '${optionalString (cfg.database.host != null) cfg.database.host}');
       define('DB_USER', '${cfg.database.user}');
       define('DB_NAME', '${cfg.database.name}');
-      define('DB_PASS', '${escape ["'" "\\"] cfg.database.password}');
+      define('DB_PASS', '${optionalString (cfg.database.password != null) (escape ["'" "\\"] cfg.database.password)}');
       define('DB_PORT', '${toString dbPort}');
 
       define('AUTH_AUTO_CREATE', ${boolToString cfg.auth.autoCreate});
@@ -91,12 +90,21 @@ let
 
       enable = mkEnableOption "tt-rss";
 
+      root = mkOption {
+        type = types.path;
+        default = "/var/lib/tt-rss";
+        example = "/var/lib/tt-rss";
+        description = ''
+          Root of the application.
+        '';
+      };
+
       user = mkOption {
         type = types.str;
         default = "nginx";
         example = "nginx";
         description = ''
-          User account under which both the service and the web-application run.
+          User account under which both the update daemon and the web-application run.
         '';
       };
 
@@ -110,17 +118,13 @@ let
         '';
       };
 
-      # TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged
-
-      # virtualHost = mkOption {
-      #   type = types.str;
-      #   default = "${virtualHostName}";
-      #   description = ''
-      #     Name of existing nginx virtual host that is used to run web-application.
-      #     If not specified a host will be created automatically with
-      #     default values.
-      #   '';
-      # };
+      virtualHost = mkOption {
+        type = types.nullOr types.str;
+        default = "tt-rss";
+        description = ''
+          Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
+        '';
+      };
 
       database = {
         type = mkOption {
@@ -132,10 +136,10 @@ let
         };
 
         host = mkOption {
-          type = types.str;
-          default = "localhost";
+          type = types.nullOr types.str;
+          default = null;
           description = ''
-            Host of the database.
+            Host of the database. Leave null to use Unix domain socket.
           '';
         };
 
@@ -362,7 +366,7 @@ let
 
       singleUserMode = mkOption {
         type = types.bool;
-        default = true;
+        default = false;
 
         description = ''
           Operate in single user mode, disables all functionality related to
@@ -445,17 +449,15 @@ let
 
   ###### implementation
 
-  config = let
-    root = "/var/lib/tt-rss";
-  in mkIf cfg.enable {
+  config = mkIf cfg.enable {
 
-    services.phpfpm.poolConfigs = if cfg.pool == "${poolName}" then {
+    services.phpfpm.poolConfigs = mkIf (cfg.pool == "${poolName}") {
       "${poolName}" = ''
         listen = "${phpfpmSocketName}";
         listen.owner = nginx
         listen.group = nginx
         listen.mode = 0600
-        user = nginx
+        user = ${cfg.user}
         pm = dynamic
         pm.max_children = 75
         pm.start_servers = 10
@@ -464,36 +466,26 @@ let
         pm.max_requests = 500
         catch_workers_output = 1
       '';
-    } else {};
-
-    # TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged
-
-    # services.nginx.virtualHosts = if cfg.virtualHost == "${virtualHostName}" then {
-    #   "${virtualHostName}" = {
-    #     root = "${root}";
-    #     extraConfig = ''
-    #       access_log  /var/log/nginx-${virtualHostName}-access.log;
-    #       error_log   /var/log/nginx-${virtualHostName}-error.log;
-    #     '';
-
-    #     locations."/" = {
-    #       extraConfig = ''
-    #         index index.php;
-    #       '';
-    #     };
-
-    #     locations."~ \.php$" = {
-    #       extraConfig = ''
-    #         fastcgi_split_path_info ^(.+\.php)(/.+)$;
-    #         fastcgi_pass unix:${phpfpmSocketName};
-    #         fastcgi_index index.php;
-    #         fastcgi_param SCRIPT_FILENAME ${root}/$fastcgi_script_name;
-
-    #         include ${pkgs.nginx}/conf/fastcgi_params;
-    #       '';
-    #     };
-    #   };
-    # } else {};
+    };
+
+    services.nginx.virtualHosts = mkIf (cfg.virtualHost != null) {
+      "${cfg.virtualHost}" = {
+        root = "${cfg.root}";
+
+        locations."/" = {
+          index = "index.php";
+        };
+
+        locations."~ \.php$" = {
+          extraConfig = ''
+            fastcgi_split_path_info ^(.+\.php)(/.+)$;
+            fastcgi_pass unix:${phpfpmSocketName};
+            fastcgi_index index.php;
+            fastcgi_param SCRIPT_FILENAME ${cfg.root}/$fastcgi_script_name;
+          '';
+        };
+      };
+    };
 
 
     systemd.services.tt-rss = let
@@ -503,35 +495,34 @@ let
         description = "Tiny Tiny RSS feeds update daemon";
 
         preStart = let
-          callSql = if cfg.database.type == "pgsql" then (e: ''
-                 ${optionalString (cfg.database.password != null)
-                   "PGPASSWORD=${cfg.database.password}"} ${pkgs.postgresql95}/bin/psql \
-                     -U ${cfg.database.user}                                            \
-                     -h ${cfg.database.host}                                            \
-                     --port ${toString dbPort}                                          \
-                     -c '${e}'                                                          \
-                     ${cfg.database.name}'')
-
-               else if cfg.database.type == "mysql" then (e: ''
-                 echo '${e}' | ${pkgs.mysql}/bin/mysql                  \
-                   ${optionalString (cfg.database.password != null)
-                     "-p${cfg.database.password}"}                      \
-                   -u ${cfg.database.user}                              \
-                   -h ${cfg.database.host}                              \
-                   -P ${toString dbPort}                                \
-                   ${cfg.database.name}'')
-
-               else "";
+          callSql = e:
+              if cfg.database.type == "pgsql" then ''
+                  ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \
+                  ${pkgs.postgresql95}/bin/psql \
+                    -U ${cfg.database.user} \
+                    ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \
+                    -c '${e}' \
+                    ${cfg.database.name}''
+
+              else if cfg.database.type == "mysql" then ''
+                  echo '${e}' | ${pkgs.mysql}/bin/mysql \
+                    -u ${cfg.database.user} \
+                    ${optionalString (cfg.database.password != null) "-p${cfg.database.password}"} \
+                    ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} -P ${toString dbPort}"} \
+                    ${cfg.database.name}''
+
+              else "";
 
         in ''
-          rm -rf "${root}/*"
-          mkdir -m 755 -p "${root}"
-          cp -r "${pkgs.tt-rss}/"* "${root}"
-          ln -sf "${tt-rss-config}" "${root}/config.php"
-          chown -R "${cfg.user}" "${root}"
-          chmod -R 755 "${root}"
-        '' + (optionalString (cfg.database.type == "pgsql") ''
-
+          rm -rf "${cfg.root}/*"
+          mkdir -m 755 -p "${cfg.root}"
+          cp -r "${pkgs.tt-rss}/"* "${cfg.root}"
+          ln -sf "${tt-rss-config}" "${cfg.root}/config.php"
+          chown -R "${cfg.user}" "${cfg.root}"
+          chmod -R 755 "${cfg.root}"
+        ''
+
+        + (optionalString (cfg.database.type == "pgsql") ''
           exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \
           | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//')
 
@@ -540,8 +531,9 @@ let
           else
             echo 'The database contains some data. Leaving it as it is.'
           fi;
-        '') + (optionalString (cfg.database.type == "mysql") ''
+        '')
 
+        + (optionalString (cfg.database.type == "mysql") ''
           exists=$(${callSql "select count(*) > 0 from information_schema.tables where table_schema = schema()"} \
           | tail -n+2 | sed -e 's/[ \n\t]*//')
 
@@ -554,7 +546,7 @@ let
 
         serviceConfig = {
           User = "${cfg.user}";
-          ExecStart = "${pkgs.php}/bin/php /var/lib/tt-rss/update.php --daemon";
+          ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon";
           StandardOutput = "syslog";
           StandardError = "syslog";
           PermissionsStartOnly = true;
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 6e62606f323e..94c442e165b7 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -114,17 +114,18 @@ let
         port = if vhost.port != null then vhost.port else (if ssl then 443 else 80);
         listenString = toString port + optionalString ssl " ssl http2"
           + optionalString vhost.default " default";
-        acmeLocation = optionalString vhost.enableACME ''
+        acmeLocation = optionalString vhost.enableACME (''
           location /.well-known/acme-challenge {
-            try_files $uri @acme-fallback;
+            ${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"}
             root ${vhost.acmeRoot};
             auth_basic off;
           }
+        '' + (optionalString (vhost.acmeFallbackHost != null) ''
           location @acme-fallback {
             auth_basic off;
             proxy_pass http://${vhost.acmeFallbackHost};
           }
-        '';
+        ''));
       in ''
         ${optionalString vhost.forceSSL ''
           server {
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index ee3f68bf8059..dcebbc9229fc 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -39,8 +39,8 @@ with lib;
     };
 
     acmeFallbackHost = mkOption {
-      type = types.str;
-      default = "0.0.0.0";
+      type = types.nullOr types.str;
+      default = null;
       description = ''
         Host which to proxy requests to if acme challenge is not found. Useful
         if you want multiple hosts to be able to verify the same domain name.
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index c3be20b41e29..fa6b4c0629d7 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -10,6 +10,10 @@ in
 
 {
 
+  meta = {
+    maintainers = with maintainers; [ danbst ];
+  };
+
   ###### interface
 
   options = {
@@ -23,9 +27,9 @@ in
 
       package = mkOption {
         type = types.package;
-        default = pkgs.tomcat7;
-        defaultText = "pkgs.tomcat7";
-        example = lib.literalExample "pkgs.tomcat8";
+        default = pkgs.tomcat85;
+        defaultText = "pkgs.tomcat85";
+        example = lib.literalExample "pkgs.tomcatUnstable";
         description = ''
           Which tomcat package to use.
         '';
@@ -74,8 +78,8 @@ in
 
       webapps = mkOption {
         type = types.listOf types.package;
-        default = [ tomcat ];
-        defaultText = "[ tomcat ]";
+        default = [ tomcat.webapps ];
+        defaultText = "[ tomcat.webapps ]";
         description = "List containing WAR files or directories with WAR files which are web applications to be deployed on Tomcat";
       };
 
@@ -352,7 +356,7 @@ in
           ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh'
       '';
 
-      postStop = ''
+      preStop = ''
         echo "Stopping tomcat..."
         CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh
       '';
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index b03f70385b1f..6c6a1e79ed0e 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -654,6 +654,8 @@ in
         ${xrandrMonitorSections}
       '';
 
+    fonts.enableDefaultFonts = mkDefault true;
+
   };
 
 }
diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix
index 1c587413121e..60298362d767 100644
--- a/nixos/modules/system/activation/activation-script.nix
+++ b/nixos/modules/system/activation/activation-script.nix
@@ -12,11 +12,13 @@ let
     '';
   });
 
-  path = map getBin
-    [ pkgs.coreutils pkgs.gnugrep pkgs.findutils
-      pkgs.glibc # needed for getent
-      pkgs.shadow
-      pkgs.nettools # needed for hostname
+  path = with pkgs; map getBin
+    [ coreutils
+      gnugrep
+      findutils
+      glibc # needed for getent
+      shadow
+      nettools # needed for hostname
     ];
 
 in
@@ -137,8 +139,13 @@ in
 
         mkdir -m 1777 -p /var/tmp
 
-        # Empty, read-only home directory of many system accounts.
-        mkdir -m 0555 -p /var/empty
+        # Empty, immutable home directory of many system accounts.
+        mkdir -p /var/empty
+        # Make sure it's really empty
+        ${pkgs.e2fsprogs}/bin/chattr -i /var/empty
+        find /var/empty -mindepth 1 -delete
+        chmod 0555 /var/empty
+        ${pkgs.e2fsprogs}/bin/chattr +i /var/empty
       '';
 
     system.activationScripts.usrbinenv = if config.environment.usrbinenv != null
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index 0f342f44fe76..ba15d0318b17 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -203,6 +203,12 @@ in
         # Misc. stuff.
         "pcips2" "atkbd"
 
+        # Temporary fix for https://github.com/NixOS/nixpkgs/issues/18451
+        # Remove as soon as upstream gets fixed - marking it:
+        # TODO
+        # FIXME
+        "i8042"
+
         # To wait for SCSI devices to appear.
         "scsi_wait_scan"
 
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index ab7485500261..38b4b437369d 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -677,8 +677,7 @@ in
     };
 
     systemd.services.systemd-networkd-wait-online = {
-      before = [ "network-online.target" "ip-up.target" ];
-      wantedBy = [ "network-online.target" "ip-up.target" ];
+      wantedBy = [ "network-online.target" ];
     };
 
     systemd.services."systemd-network-wait-online@" = {
diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh
index 704150e77d72..ae88222f2780 100644
--- a/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixos/modules/system/boot/stage-2-init.sh
@@ -29,7 +29,7 @@ setPath "@path@"
 # Normally, stage 1 mounts the root filesystem read/writable.
 # However, in some environments, stage 2 is executed directly, and the
 # root is read-only.  So make it writable here.
-if [ "$container" != systemd-nspawn ]; then
+if [ -z "$container" ]; then
     mount -n -o remount,rw none /
 fi
 
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index df72be1b4be5..b724995bb1fc 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -14,6 +14,7 @@ let
   upstreamSystemUnits =
     [ # Targets.
       "basic.target"
+      "busnames.target"
       "sysinit.target"
       "sockets.target"
       "graphical.target"
@@ -140,6 +141,7 @@ let
       "user.slice"
       "machine.slice"
       "systemd-machined.service"
+      "systemd-nspawn@.service"
 
       # Temporary file creation / cleanup.
       "systemd-tmpfiles-clean.service"
@@ -569,6 +571,16 @@ in
       '';
     };
 
+    systemd.user.extraConfig = mkOption {
+      default = "";
+      type = types.lines;
+      example = "DefaultCPUAccounting=yes";
+      description = ''
+        Extra config options for systemd user instances. See man systemd-user.conf for
+        available options.
+      '';
+    };
+
     systemd.tmpfiles.rules = mkOption {
       type = types.listOf types.str;
       default = [];
@@ -663,6 +675,11 @@ in
         ${config.systemd.extraConfig}
       '';
 
+      "systemd/user.conf".text = ''
+        [Manager]
+        ${config.systemd.user.extraConfig}
+      '';
+
       "systemd/journald.conf".text = ''
         [Journal]
         RateLimitInterval=${config.services.journald.rateLimitInterval}
@@ -725,18 +742,6 @@ in
         unitConfig.X-StopOnReconfiguration = true;
       };
 
-    systemd.targets.network-online.after = [ "ip-up.target" ];
-
-    systemd.targets.network-pre = {
-      wantedBy = [ "network.target" ];
-      before = [ "network.target" ];
-    };
-
-    systemd.targets.remote-fs-pre = {
-      wantedBy = [ "remote-fs.target" ];
-      before = [ "remote-fs.target" ];
-    };
-
     systemd.units =
       mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
       // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index a66ece1020f8..3c822c8716d0 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -286,11 +286,15 @@ in
     # Sync mount options with systemd's src/core/mount-setup.c: mount_table.
     boot.specialFileSystems = {
       "/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; };
-      "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; };
       "/run" = { fsType = "tmpfs"; options = [ "nodev" "strictatime" "mode=755" "size=${config.boot.runSize}" ]; };
       "/dev" = { fsType = "devtmpfs"; options = [ "nosuid" "strictatime" "mode=755" "size=${config.boot.devSize}" ]; };
       "/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
       "/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "gid=${toString config.ids.gids.tty}" ]; };
+    } // optionalAttrs (!config.boot.isContainer) {
+      # systemd-nspawn populates /sys by itself, and remounting it causes all
+      # kinds of weird issues (most noticeably, waiting for host disk device
+      # nodes).
+      "/sys" = { fsType = "sysfs"; options = [ "nosuid" "noexec" "nodev" ]; };
     };
 
   };
diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix
index e454eca3a0e5..e9a7ccc721a9 100644
--- a/nixos/modules/tasks/filesystems/nfs.nix
+++ b/nixos/modules/tasks/filesystems/nfs.nix
@@ -38,15 +38,17 @@ in
         default = null;
         example = 4000;
         description = ''
-          Use fixed port for rpc.statd, useful if NFS server is behind firewall.
+          Use a fixed port for <command>rpc.statd</command>. This is
+          useful if the NFS server is behind a firewall.
         '';
       };
       lockdPort = mkOption {
         default = null;
         example = 4001;
         description = ''
-          Use fixed port for NFS lock manager kernel module (lockd/nlockmgr),
-          useful if NFS server is behind firewall.
+          Use a fixed port for the NFS lock manager kernel module
+          (<literal>lockd/nlockmgr</literal>).  This is useful if the
+          NFS server is behind a firewall.
         '';
       };
     };
@@ -68,13 +70,16 @@ in
 
     boot.initrd.kernelModules = mkIf inInitrd [ "nfs" ];
 
+    # FIXME: should use upstream units from nfs-utils.
+
     systemd.services.statd =
       { description = "NFSv3 Network Status Monitor";
 
         path = [ pkgs.nfs-utils pkgs.sysvtools pkgs.utillinux ];
 
-        wantedBy = [ "remote-fs-pre.target" ];
+        wants = [ "remote-fs-pre.target" ];
         before = [ "remote-fs-pre.target" ];
+        wantedBy = [ "remote-fs.target" ];
         requires = [ "basic.target" "rpcbind.service" ];
         after = [ "basic.target" "rpcbind.service" ];
 
@@ -100,8 +105,9 @@ in
 
         path = [ pkgs.sysvtools pkgs.utillinux ];
 
-        wantedBy = [ "remote-fs-pre.target" ];
+        wants = [ "remote-fs-pre.target" ];
         before = [ "remote-fs-pre.target" ];
+        wantedBy = [ "remote-fs.target" ];
         requires = [ "rpcbind.service" ];
         after = [ "rpcbind.service" ];
 
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index c960e401f9b1..d1b62e0fd4e4 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -142,7 +142,6 @@ in
                     # (Flushing this interface may have removed it.)
                     ${config.systemd.package}/bin/systemctl try-restart --no-block network-setup.service
                   fi
-                  ${config.systemd.package}/bin/systemctl start ip-up.target
                 '';
             preStop = flip concatMapStrings (ips) (ip:
                 let
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index 301ee43fd0e5..974041d7e1a5 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -43,7 +43,7 @@ in
       message = "networking.bridges.${n}.rstp is not supported by networkd.";
     });
 
-    systemd.services.dhcpcd.enable = mkDefault false;
+    networking.dhcpcd.enable = mkDefault false;
 
     systemd.services.network-local-commands = {
       after = [ "systemd-networkd.service" ];
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index c52bd904caec..dc62cae24c7a 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -231,7 +231,7 @@ let
         type = types.bool;
         description = ''
           Whether this interface is virtual and should be created by tunctl.
-          This is mainly useful for creating bridges between a host a virtual
+          This is mainly useful for creating bridges between a host and a virtual
           network such as VPN or a virtual machine.
         '';
       };
diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix
index a89cd454dc73..6817eb837a01 100644
--- a/nixos/modules/virtualisation/azure-agent.nix
+++ b/nixos/modules/virtualisation/azure-agent.nix
@@ -178,7 +178,8 @@ in
 
     systemd.services.waagent = {
       wantedBy = [ "multi-user.target" ];
-      after = [ "ip-up.target" "sshd.service" ];
+      after = [ "network-online.target" "sshd.service" ];
+      wants = [ "network-online.target" ];
 
       path = [ pkgs.e2fsprogs ];
       description = "Windows Azure Agent Service";
diff --git a/nixos/modules/virtualisation/azure-bootstrap-blobs.nix b/nixos/modules/virtualisation/azure-bootstrap-blobs.nix
new file mode 100644
index 000000000000..281be9a12318
--- /dev/null
+++ b/nixos/modules/virtualisation/azure-bootstrap-blobs.nix
@@ -0,0 +1,3 @@
+{
+    "16.03" = "https://nixos.blob.core.windows.net/images/nixos-image-16.03.847.8688c17-x86_64-linux.vhd";
+}
diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix
index ab49d8871f85..e2905913b6c5 100644
--- a/nixos/modules/virtualisation/brightbox-image.nix
+++ b/nixos/modules/virtualisation/brightbox-image.nix
@@ -116,8 +116,8 @@ in
 
       wantedBy = [ "multi-user.target" "sshd.service" ];
       before = [ "sshd.service" ];
-      wants = [ "ip-up.target" ];
-      after = [ "ip-up.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "network-online.target" ];
 
       path = [ pkgs.wget pkgs.iproute ];
 
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index ebc2be087a5b..92fe98f3f9c2 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -40,13 +40,25 @@ in
       };
     storageDriver =
       mkOption {
-        type = types.enum ["aufs" "btrfs" "devicemapper" "overlay" "zfs"];
-        default = "devicemapper";
+        type = types.nullOr (types.enum ["aufs" "btrfs" "devicemapper" "overlay" "overlay2" "zfs"]);
+        default = null;
         description =
           ''
-            This option determines which Docker storage driver to use.
+            This option determines which Docker storage driver to use. By default
+            it let's docker automatically choose preferred storage driver.
           '';
       };
+
+    logDriver =
+      mkOption {
+        type = types.enum ["none" "json-file" "syslog" "journald" "gelf" "fluentd" "awslogs" "splunk" "etwlogs" "gcplogs"];
+        default = "journald";
+        description =
+          ''
+            This option determines which Docker log driver to use.
+          '';
+      };
+
     extraOptions =
       mkOption {
         type = types.separatedString " ";
@@ -88,7 +100,12 @@ in
         after = [ "network.target" ] ++ (optional cfg.socketActivation "docker.socket") ;
         requires = optional cfg.socketActivation "docker.socket";
         serviceConfig = {
-          ExecStart = "${pkgs.docker}/bin/docker daemon --group=docker --storage-driver=${cfg.storageDriver} ${optionalString cfg.socketActivation "--host=fd://"} ${cfg.extraOptions}";
+          ExecStart = ''${pkgs.docker}/bin/dockerd \
+            --group=docker --log-driver=${cfg.logDriver} \
+            ${optionalString (cfg.storageDriver != null) "--storage-driver=${cfg.storageDriver}"} \
+            ${optionalString cfg.socketActivation "--host=fd://"} \
+            ${cfg.extraOptions}
+          '';
           #  I'm not sure if that limits aren't too high, but it's what
           #  goes in config bundled with docker itself
           LimitNOFILE = 1048576;
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index 59b77dde5d9a..489b612f1675 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -134,8 +134,8 @@ in
 
       wantedBy = [ "sshd.service" ];
       before = [ "sshd.service" ];
-      after = [ "network-online.target" "ip-up.target" ];
-      wants = [ "network-online.target" "ip-up.target" ];
+      after = [ "network-online.target" ];
+      wants = [ "network-online.target" ];
 
       script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'";
                    mktemp = "mktemp --tmpdir=/run"; in
diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix
index ce4abecd6762..7214543871d6 100644
--- a/nixos/modules/virtualisation/virtualbox-host.nix
+++ b/nixos/modules/virtualisation/virtualbox-host.nix
@@ -4,10 +4,15 @@ with lib;
 
 let
   cfg = config.virtualisation.virtualbox.host;
-  virtualbox = config.boot.kernelPackages.virtualbox.override {
+
+  virtualbox = pkgs.virtualbox.override {
     inherit (cfg) enableHardening headless;
   };
 
+  kernelModules = config.boot.kernelPackages.virtualbox.override {
+    inherit virtualbox;
+  };
+
 in
 
 {
@@ -60,7 +65,7 @@ in
 
   config = mkIf cfg.enable (mkMerge [{
     boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ];
-    boot.extraModulePackages = [ virtualbox ];
+    boot.extraModulePackages = [ kernelModules ];
     environment.systemPackages = [ virtualbox ];
 
     security.setuidOwners = let
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index b6a5b3e4788d..d68b3bb73904 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -34,7 +34,7 @@ in {
       postVM =
         ''
           export HOME=$PWD
-          export PATH=${pkgs.linuxPackages.virtualbox}/bin:$PATH
+          export PATH=${pkgs.virtualbox}/bin:$PATH
 
           echo "creating VirtualBox pass-through disk wrapper (no copying invovled)..."
           VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index f2ca6af7e3a4..70b29aa23a5b 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -73,6 +73,7 @@ in rec {
         (all nixos.tests.ipv6)
         (all nixos.tests.i3wm)
         (all nixos.tests.kde4)
+        (all nixos.tests.kde5)
         #(all nixos.tests.lightdm)
         (all nixos.tests.login)
         (all nixos.tests.misc)
@@ -88,6 +89,7 @@ in rec {
         (all nixos.tests.networking.scripted.sit)
         (all nixos.tests.networking.scripted.vlan)
         (all nixos.tests.nfs3)
+        (all nixos.tests.nfs4)
         (all nixos.tests.openssh)
         (all nixos.tests.printing)
         (all nixos.tests.proxy)
diff --git a/nixos/release.nix b/nixos/release.nix
index a5b4ab5f04cf..d66ebd7cb15c 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -228,7 +228,6 @@ in rec {
   tests.containers-imperative = callTest tests/containers-imperative.nix {};
   tests.containers-extra_veth = callTest tests/containers-extra_veth.nix {};
   tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
-  tests.dockerRegistry = hydraJob (import tests/docker-registry.nix { system = "x86_64-linux"; });
   tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; };
   tests.ecryptfs = callTest tests/ecryptfs.nix {};
   tests.etcd = hydraJob (import tests/etcd.nix { system = "x86_64-linux"; });
@@ -251,6 +250,7 @@ in rec {
   tests.ipv6 = callTest tests/ipv6.nix {};
   tests.jenkins = callTest tests/jenkins.nix {};
   tests.kde4 = callTest tests/kde4.nix {};
+  tests.kde5 = callTest tests/kde5.nix {};
   tests.keymap = callSubTests tests/keymap.nix {};
   tests.initrdNetwork = callTest tests/initrd-network.nix {};
   tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; });
@@ -274,7 +274,7 @@ in rec {
   tests.nfs4 = callTest tests/nfs.nix { version = 4; };
   tests.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
-  tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
+  #tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
   tests.peerflix = callTest tests/peerflix.nix {};
   tests.postgresql = callTest tests/postgresql.nix {};
   tests.printing = callTest tests/printing.nix {};
@@ -284,7 +284,6 @@ in rec {
   tests.quake3 = callTest tests/quake3.nix {};
   tests.runInMachine = callTest tests/run-in-machine.nix {};
   tests.sddm = callTest tests/sddm.nix {};
-  tests.sddm-kde5 = callTest tests/sddm-kde5.nix {};
   tests.simple = callTest tests/simple.nix {};
   tests.smokeping = callTest tests/smokeping.nix {};
   tests.taskserver = callTest tests/taskserver.nix {};
diff --git a/nixos/tests/blivet.nix b/nixos/tests/blivet.nix
index 33a79e65efe1..a7b836ce99a6 100644
--- a/nixos/tests/blivet.nix
+++ b/nixos/tests/blivet.nix
@@ -69,6 +69,7 @@ import ./make-test.nix ({ pkgs, ... }: with pkgs.pythonPackages; rec {
     sed -i \
       -e '1i import tempfile' \
       -e 's|_STORE_FILE_PATH = .*|_STORE_FILE_PATH = tempfile.gettempdir()|' \
+      -e 's|DEFAULT_STORE_SIZE = .*|DEFAULT_STORE_SIZE = 409600|' \
       tests/loopbackedtestcase.py
 
     PYTHONPATH=".:$(< "${pkgs.stdenv.mkDerivation {
diff --git a/nixos/tests/docker-registry.nix b/nixos/tests/docker-registry.nix
deleted file mode 100644
index eed3284202f5..000000000000
--- a/nixos/tests/docker-registry.nix
+++ /dev/null
@@ -1,43 +0,0 @@
-# This test runs docker-registry and check if it works
-
-import ./make-test.nix ({ pkgs, ...} : {
-  name = "docker-registry";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ offline ];
-  };
-
-  nodes = {
-    registry = { config, pkgs, ... }: {
-      services.dockerRegistry.enable = true;
-      services.dockerRegistry.port = 8080;
-      services.dockerRegistry.host = "0.0.0.0";
-      networking.firewall.allowedTCPPorts = [ 8080 ];
-    };
-
-    client1 = { config, pkgs, ...}: {
-      virtualisation.docker.enable = true;
-      virtualisation.docker.extraOptions = "--insecure-registry registry:8080";
-    };
-
-    client2 = { config, pkgs, ...}: {
-      virtualisation.docker.enable = true;
-      virtualisation.docker.extraOptions = "--insecure-registry registry:8080";
-    };
-  };
-
-  testScript = ''
-    $client1->start();
-    $client1->waitForUnit("docker.service");
-    $client1->succeed("tar cv --files-from /dev/null | docker import - scratch");
-    $client1->succeed("docker tag scratch registry:8080/scratch");
-
-    $registry->start();
-    $registry->waitForUnit("docker-registry.service");
-    $client1->succeed("docker push registry:8080/scratch");
-
-    $client2->start();
-    $client2->waitForUnit("docker.service");
-    $client2->succeed("docker pull registry:8080/scratch");
-    $client2->succeed("docker images | grep scratch");
-  '';
-})
diff --git a/nixos/tests/docker.nix b/nixos/tests/docker.nix
index 06e511d6e0bd..1b57a94a05d4 100644
--- a/nixos/tests/docker.nix
+++ b/nixos/tests/docker.nix
@@ -11,9 +11,6 @@ import ./make-test.nix ({ pkgs, ...} : {
       { config, pkgs, ... }:
         {
           virtualisation.docker.enable = true;
-          # FIXME: The default "devicemapper" storageDriver fails in NixOS VM
-          # tests.
-          virtualisation.docker.storageDriver = "overlay";
         };
     };
 
diff --git a/nixos/tests/firewall.nix b/nixos/tests/firewall.nix
index 8f2cb27b60f1..1119a5312eb5 100644
--- a/nixos/tests/firewall.nix
+++ b/nixos/tests/firewall.nix
@@ -15,6 +15,16 @@ import ./make-test.nix ( { pkgs, ... } : {
           services.httpd.adminAddr = "foo@example.org";
         };
 
+      # Dummy configuration to check whether firewall.service will be honored
+      # during system activation. This only needs to be different to the
+      # original walled configuration so that there is a change in the service
+      # file.
+      walled2 =
+        { config, pkgs, nodes, ... }:
+        { networking.firewall.enable = true;
+          networking.firewall.rejectPackets = true;
+        };
+
       attacker =
         { config, pkgs, ... }:
         { services.httpd.enable = true;
@@ -23,28 +33,33 @@ import ./make-test.nix ( { pkgs, ... } : {
         };
     };
 
-  testScript =
-    { nodes, ... }:
-    ''
-      startAll;
+  testScript = { nodes, ... }: let
+    newSystem = nodes.walled2.config.system.build.toplevel;
+  in ''
+    $walled->start;
+    $attacker->start;
+
+    $walled->waitForUnit("firewall");
+    $walled->waitForUnit("httpd");
+    $attacker->waitForUnit("network.target");
 
-      $walled->waitForUnit("firewall");
-      $walled->waitForUnit("httpd");
-      $attacker->waitForUnit("network.target");
+    # Local connections should still work.
+    $walled->succeed("curl -v http://localhost/ >&2");
 
-      # Local connections should still work.
-      $walled->succeed("curl -v http://localhost/ >&2");
+    # Connections to the firewalled machine should fail, but ping should succeed.
+    $attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2");
+    $attacker->succeed("ping -c 1 walled >&2");
 
-      # Connections to the firewalled machine should fail, but ping should succeed.
-      $attacker->fail("curl --fail --connect-timeout 2 http://walled/ >&2");
-      $attacker->succeed("ping -c 1 walled >&2");
+    # Outgoing connections/pings should still work.
+    $walled->succeed("curl -v http://attacker/ >&2");
+    $walled->succeed("ping -c 1 attacker >&2");
 
-      # Outgoing connections/pings should still work.
-      $walled->succeed("curl -v http://attacker/ >&2");
-      $walled->succeed("ping -c 1 attacker >&2");
+    # If we stop the firewall, then connections should succeed.
+    $walled->stopJob("firewall");
+    $attacker->succeed("curl -v http://walled/ >&2");
 
-      # If we stop the firewall, then connections should succeed.
-      $walled->stopJob("firewall");
-      $attacker->succeed("curl -v http://walled/ >&2");
-    '';
+    # Check whether activation of a new configuration reloads the firewall.
+    $walled->succeed("${newSystem}/bin/switch-to-configuration test 2>&1" .
+                     " | grep -qF firewall.service");
+  '';
 })
diff --git a/nixos/tests/influxdb.nix b/nixos/tests/influxdb.nix
index 0408d8983ade..aca2189716a4 100644
--- a/nixos/tests/influxdb.nix
+++ b/nixos/tests/influxdb.nix
@@ -22,18 +22,15 @@ import ./make-test.nix ({ pkgs, ...} : {
 
     # create database
     $one->succeed(q~
-      curl -X POST 'http://localhost:8086/db?u=root&p=root' \
-        -d '{"name": "test"}'
+      curl -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE test"
     ~);
 
     # write some points and run simple query
     $one->succeed(q~
-      curl -X POST 'http://localhost:8086/db/test/series?u=root&p=root' \
-        -d '[{"name":"foo","columns":["val"],"points":[[6666]]}]'
+      curl -XPOST 'http://localhost:8086/write?db=test' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000'
     ~);
     $one->succeed(q~
-      curl -G 'http://localhost:8086/db/test/series?u=root&p=root' \
-        --data-urlencode 'q=select * from foo limit 1' | grep 6666
+      curl -GET 'http://localhost:8086/query' --data-urlencode "db=test" --data-urlencode "q=SELECT \"value\" FROM \"cpu_load_short\" WHERE \"region\"='us-west'"  | grep "0\.64"
     ~);
   '';
 })
diff --git a/nixos/tests/sddm-kde5.nix b/nixos/tests/kde5.nix
index 0247d267aaa4..787dd2f8cbdd 100644
--- a/nixos/tests/sddm-kde5.nix
+++ b/nixos/tests/kde5.nix
@@ -24,29 +24,26 @@ import ./make-test.nix ({ pkgs, ...} :
 
   testScript = { nodes, ... }:
   let xdo = "${pkgs.xdotool}/bin/xdotool"; in
-   ''     
-    sub krunner {
-      my ($win,) = @_;
-      $machine->execute("${xdo} key Alt+F2 sleep 1 type $win");
-      $machine->execute("${xdo} search --sync --onlyvisible --class krunner sleep 5 key Return");
-    }
+   ''
+    startAll;
+
+    $machine->waitForFile("/home/alice/.Xauthority");
+    $machine->succeed("xauth merge ~alice/.Xauthority");
 
     $machine->waitUntilSucceeds("pgrep plasmashell");
-    $machine->succeed("xauth merge ~alice/.Xauthority");    
-    $machine->waitForWindow(qr/Desktop.*/);
+    $machine->waitForWindow("^Desktop ");
 
     # Check that logging in has given the user ownership of devices.
     $machine->succeed("getfacl /dev/snd/timer | grep -q alice");
-    
-    krunner("dolphin");
-    $machine->waitForWindow(qr/.*Dolphin/);
-    
-    krunner("konsole");
-    $machine->waitForWindow(qr/.*Konsole/);
-    
-    krunner("systemsettings5");
-    $machine->waitForWindow(qr/.*Settings/);
-    $machine->sleep(20);
+
+    $machine->execute("su - alice -c 'DISPLAY=:0.0 dolphin &'");
+    $machine->waitForWindow(" Dolphin");
+
+    $machine->execute("su - alice -c 'DISPLAY=:0.0 konsole &'");
+    $machine->waitForWindow("Konsole");
+
+    $machine->execute("su - alice -c 'DISPLAY=:0.0 systemsettings5 &'");
+    $machine->waitForWindow("Settings");
 
     $machine->execute("${xdo} key Alt+F1 sleep 10");
     $machine->screenshot("screen");
diff --git a/nixos/tests/mumble.nix b/nixos/tests/mumble.nix
index 35f440026997..7959b85a0cf0 100644
--- a/nixos/tests/mumble.nix
+++ b/nixos/tests/mumble.nix
@@ -36,18 +36,29 @@ in
     # cancel client audio configuration
     $client1->waitForWindow(qr/Audio Tuning Wizard/);
     $client2->waitForWindow(qr/Audio Tuning Wizard/);
+    $server->sleep(5); # wait because mumble is slow to register event handlers
     $client1->sendKeys("esc");
     $client2->sendKeys("esc");
 
     # cancel client cert configuration
     $client1->waitForWindow(qr/Certificate Management/);
     $client2->waitForWindow(qr/Certificate Management/);
+    $server->sleep(5); # wait because mumble is slow to register event handlers
     $client1->sendKeys("esc");
     $client2->sendKeys("esc");
 
     # accept server certificate
     $client1->waitForWindow(qr/^Mumble$/);
     $client2->waitForWindow(qr/^Mumble$/);
+    $server->sleep(5); # wait because mumble is slow to register event handlers
+    $client1->sendChars("y");
+    $client2->sendChars("y");
+    $server->sleep(5); # wait because mumble is slow to register event handlers
+
+    # sometimes the wrong of the 2 windows is focused, we switch focus and try pressing "y" again
+    $client1->sendKeys("alt-tab");
+    $client2->sendKeys("alt-tab");
+    $server->sleep(5); # wait because mumble is slow to register event handlers
     $client1->sendChars("y");
     $client2->sendChars("y");
 
diff --git a/nixos/tests/prometheus.nix b/nixos/tests/prometheus.nix
new file mode 100644
index 000000000000..7605227100d2
--- /dev/null
+++ b/nixos/tests/prometheus.nix
@@ -0,0 +1,29 @@
+import ./make-test.nix {
+  name = "prometheus";
+
+  nodes = {
+    one = { config, pkgs, ... }: {
+      services.prometheus = {
+        enable = true;
+        globalConfig = {
+          labels = { foo = "bar"; };
+        };
+        scrapeConfigs = [{
+          job_name = "prometheus";
+          target_groups = [{
+            targets = [ "127.0.0.1:9090" ];
+            labels = { instance = "localhost"; };
+          }];
+        }];
+        rules = [ ''testrule = count(up{job="prometheus"})'' ];
+      };
+    };
+  };
+
+  testScript = ''
+    startAll;
+    $one->waitForUnit("prometheus.service");
+    $one->waitForOpenPort(9090);
+    $one->succeed("curl -s http://127.0.0.1:9090/metrics");
+  '';
+}
diff --git a/nixos/tests/pump.io.nix b/nixos/tests/pump.io.nix
index 89fa23c3336e..3864f676497e 100644
--- a/nixos/tests/pump.io.nix
+++ b/nixos/tests/pump.io.nix
@@ -81,7 +81,7 @@ in {
            '';
           };
           systemd.services.mongodb.unitConfig.Before = "pump.io.service";
-          systemd.services.mongodb.unitConfig.RequiredBy = "pump.io.service";
+          systemd.services."pump.io".unitConfig.Requires = "mongodb.service";
         };
     };
 
diff --git a/nixos/tests/tomcat.nix b/nixos/tests/tomcat.nix
index 92680d82ba89..475c947e72d9 100644
--- a/nixos/tests/tomcat.nix
+++ b/nixos/tests/tomcat.nix
@@ -23,9 +23,8 @@ import ./make-test.nix ({ pkgs, ...} : {
     startAll;
 
     $server->waitForUnit("tomcat");
-    $server->sleep(30); # Dirty, but it takes a while before Tomcat handles to requests properly
     $client->waitForUnit("network.target");
-    $client->succeed("curl --fail http://server/examples/servlets/servlet/HelloWorldExample");
-    $client->succeed("curl --fail http://server/examples/jsp/jsp2/simpletag/hello.jsp");
+    $client->waitUntilSucceeds("curl --fail http://server/examples/servlets/servlet/HelloWorldExample");
+    $client->waitUntilSucceeds("curl --fail http://server/examples/jsp/jsp2/simpletag/hello.jsp");
   '';
 })
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index ab4d46ab7e15..66f16ed8bcc5 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -144,6 +144,7 @@ let
       "--uart1 0x3F8 4"
       "--uartmode1 client /run/virtualbox-log-${name}.sock"
       "--memory 768"
+      "--audio none"
     ] ++ (attrs.vmFlags or []));
 
     controllerFlags = mkFlags [
@@ -273,9 +274,12 @@ let
 
       sub shutdownVM_${name} {
         $machine->succeed(ru "touch ${sharePath}/shutdown");
-        $machine->waitUntilSucceeds(
-          "test ! -e ${sharePath}/shutdown ".
-          "  -a ! -e ${sharePath}/boot-done"
+        $machine->execute(
+          'set -e; i=0; '.
+          'while test -e ${sharePath}/shutdown '.
+          '        -o -e ${sharePath}/boot-done; do '.
+          'sleep 1; i=$(($i + 1)); [ $i -le 3600 ]; '.
+          'done'
         );
         waitForShutdown_${name};
       }
@@ -386,6 +390,7 @@ in mapAttrs mkVBoxTest {
     $machine->sendKeys("ctrl-q");
     $machine->sleep(5);
     $machine->screenshot("gui_manager_stopped");
+    destroyVM_simple;
   '';
 
   simple-cli = ''
@@ -403,6 +408,7 @@ in mapAttrs mkVBoxTest {
     });
 
     shutdownVM_simple;
+    destroyVM_simple;
   '';
 
   headless = ''
@@ -411,6 +417,7 @@ in mapAttrs mkVBoxTest {
     waitForStartup_headless;
     waitForVMBoot_headless;
     shutdownVM_headless;
+    destroyVM_headless;
   '';
 
   host-usb-permissions = ''