summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorParnell Springmeyer <parnell@digitalmentat.com>2018-01-10 10:13:49 -0800
committerParnell Springmeyer <parnell@digitalmentat.com>2018-01-10 10:13:49 -0800
commite4ec980e9ced7dbea0fb1310f831207bbc7175b0 (patch)
tree0c9ec3233fc73958db0637d409a44c527f0984eb /nixos
parenta6cdf0aaa17530773f1de918c88a1f3245fd2612 (diff)
parent80cb0c39de929f7e8e65d587cb22af777db98bea (diff)
downloadnixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.gz
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.bz2
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.lz
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.xz
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.zst
nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.zip
Merge remote-tracking branch 'upstream/master' into parnell/fetchdocker
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/firewall.xml19
-rw-r--r--nixos/doc/manual/configuration/x-windows.xml9
-rw-r--r--nixos/doc/manual/development/option-declarations.xml9
-rw-r--r--nixos/doc/manual/development/option-types.xml6
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.xml29
-rw-r--r--nixos/doc/manual/installation/installing-uefi.xml48
-rw-r--r--nixos/doc/manual/installation/installing-usb.xml20
-rw-r--r--nixos/doc/manual/installation/installing.xml122
-rw-r--r--nixos/doc/manual/installation/obtaining.xml9
-rw-r--r--nixos/doc/manual/release-notes/rl-1404.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1803.xml110
-rw-r--r--nixos/lib/make-disk-image.nix5
-rw-r--r--nixos/lib/make-ext4-fs.nix2
-rw-r--r--nixos/lib/make-squashfs.nix29
-rw-r--r--nixos/lib/test-driver/Machine.pm28
-rwxr-xr-xnixos/maintainers/scripts/ec2/create-amis.sh2
-rw-r--r--nixos/modules/config/networking.nix4
-rw-r--r--nixos/modules/config/no-x-libs.nix2
-rw-r--r--nixos/modules/installer/netboot/netboot.nix19
-rw-r--r--nixos/modules/installer/tools/nix-fallback-paths.nix7
-rw-r--r--nixos/modules/misc/ids.nix20
-rw-r--r--nixos/modules/module-list.nix17
-rw-r--r--nixos/modules/profiles/all-hardware.nix5
-rw-r--r--nixos/modules/programs/bash/bash.nix7
-rw-r--r--nixos/modules/programs/ccache.nix83
-rw-r--r--nixos/modules/programs/dconf.nix16
-rw-r--r--nixos/modules/programs/rootston.nix103
-rw-r--r--nixos/modules/programs/sway.nix55
-rw-r--r--nixos/modules/programs/tmux.nix11
-rw-r--r--nixos/modules/programs/way-cooler.nix78
-rw-r--r--nixos/modules/rename.nix7
-rw-r--r--nixos/modules/security/pam.nix20
-rw-r--r--nixos/modules/security/wrappers/default.nix4
-rw-r--r--nixos/modules/services/audio/mopidy.nix14
-rw-r--r--nixos/modules/services/backup/tarsnap.nix2
-rw-r--r--nixos/modules/services/backup/znapzend.nix369
-rw-r--r--nixos/modules/services/continuous-integration/buildkite-agent.nix11
-rw-r--r--nixos/modules/services/databases/memcached.nix57
-rw-r--r--nixos/modules/services/databases/mysql.nix17
-rw-r--r--nixos/modules/services/databases/redis.nix1
-rw-r--r--nixos/modules/services/desktops/gnome3/at-spi2-core.nix21
-rw-r--r--nixos/modules/services/games/ghost-one.nix105
-rw-r--r--nixos/modules/services/hardware/80-net-setup-link.rules13
-rw-r--r--nixos/modules/services/hardware/thinkfan.nix2
-rw-r--r--nixos/modules/services/hardware/u2f.nix23
-rw-r--r--nixos/modules/services/hardware/udev.nix2
-rw-r--r--nixos/modules/services/hardware/usbmuxd.nix74
-rw-r--r--nixos/modules/services/logging/logcheck.nix2
-rw-r--r--nixos/modules/services/logging/logstash.nix2
-rw-r--r--nixos/modules/services/mail/clamsmtp.nix179
-rw-r--r--nixos/modules/services/mail/dkimproxy-out.nix118
-rw-r--r--nixos/modules/services/mail/rspamd.nix11
-rw-r--r--nixos/modules/services/misc/dysnomia.nix8
-rw-r--r--nixos/modules/services/misc/gitlab.nix20
-rw-r--r--nixos/modules/services/misc/gitolite.nix2
-rw-r--r--nixos/modules/services/misc/gollum.nix21
-rw-r--r--nixos/modules/services/misc/logkeys.nix2
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix18
-rw-r--r--nixos/modules/services/misc/mbpfan.nix8
-rw-r--r--nixos/modules/services/misc/osrm.nix85
-rw-r--r--nixos/modules/services/misc/xmr-stak.nix73
-rw-r--r--nixos/modules/services/monitoring/smartd.nix18
-rw-r--r--nixos/modules/services/monitoring/statsd.nix31
-rw-r--r--nixos/modules/services/network-filesystems/beegfs.nix343
-rw-r--r--nixos/modules/services/network-filesystems/davfs2.nix74
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix1
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix6
-rw-r--r--nixos/modules/services/networking/i2pd.nix17
-rw-r--r--nixos/modules/services/networking/kresd.nix21
-rw-r--r--nixos/modules/services/networking/lldpd.nix1
-rw-r--r--nixos/modules/services/networking/nat.nix49
-rw-r--r--nixos/modules/services/networking/networkmanager.nix23
-rw-r--r--nixos/modules/services/networking/nsd.nix6
-rw-r--r--nixos/modules/services/networking/prosody.nix76
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix5
-rw-r--r--nixos/modules/services/scheduling/fcron.nix28
-rw-r--r--nixos/modules/services/security/clamav.nix4
-rw-r--r--nixos/modules/services/security/tor.nix83
-rw-r--r--nixos/modules/services/security/usbguard.nix2
-rw-r--r--nixos/modules/services/system/localtime.nix60
-rw-r--r--nixos/modules/services/web-apps/tt-rss.nix71
-rw-r--r--nixos/modules/services/web-servers/lighttpd/default.nix3
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix3
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix14
-rw-r--r--nixos/modules/services/web-servers/tomcat.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix6
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/mate.nix46
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix18
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix9
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix31
-rw-r--r--nixos/modules/services/x11/hardware/libinput.nix2
-rw-r--r--nixos/modules/services/x11/window-managers/awesome.nix11
-rw-r--r--nixos/modules/system/boot/grow-partition.nix43
-rw-r--r--nixos/modules/system/boot/initrd-ssh.nix5
-rw-r--r--nixos/modules/system/boot/kernel.nix4
-rw-r--r--nixos/modules/system/boot/luksroot.nix9
-rw-r--r--nixos/modules/system/boot/plymouth.nix9
-rw-r--r--nixos/modules/tasks/filesystems/btrfs.nix113
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix2
-rw-r--r--nixos/modules/testing/test-instrumentation.nix2
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix4
-rw-r--r--nixos/modules/virtualisation/containers.nix5
-rw-r--r--nixos/modules/virtualisation/ec2-amis.nix31
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix3
-rw-r--r--nixos/modules/virtualisation/grow-partition.nix51
-rw-r--r--nixos/modules/virtualisation/hyperv-guest.nix37
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix18
-rw-r--r--nixos/modules/virtualisation/lxcfs.nix4
-rw-r--r--nixos/modules/virtualisation/nova-config.nix4
-rw-r--r--nixos/modules/virtualisation/nova.nix174
-rw-r--r--nixos/modules/virtualisation/openstack/common.nix84
-rw-r--r--nixos/modules/virtualisation/openstack/glance.nix245
-rw-r--r--nixos/modules/virtualisation/openstack/keystone.nix220
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix2
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix4
-rw-r--r--nixos/release.nix54
-rw-r--r--nixos/tests/beegfs.nix115
-rw-r--r--nixos/tests/glance.nix77
-rw-r--r--nixos/tests/jenkins.nix5
-rw-r--r--nixos/tests/keystone.nix82
-rw-r--r--nixos/tests/printing.nix2
-rw-r--r--nixos/tests/radicale.nix2
-rw-r--r--nixos/tests/statsd.nix40
-rw-r--r--nixos/tests/vault.nix23
-rw-r--r--nixos/tests/virtualbox.nix3
127 files changed, 3200 insertions, 1511 deletions
diff --git a/nixos/doc/manual/configuration/firewall.xml b/nixos/doc/manual/configuration/firewall.xml
index 87406c28c2f7..75cccef95b38 100644
--- a/nixos/doc/manual/configuration/firewall.xml
+++ b/nixos/doc/manual/configuration/firewall.xml
@@ -23,10 +23,23 @@ networking.firewall.allowedTCPPorts = [ 80 443 ];
 </programlisting>
 
 Note that TCP port 22 (ssh) is opened automatically if the SSH daemon
-is enabled (<option>services.openssh.enable = true</option>).  UDP
+is enabled (<option>services.openssh.enable = true</option>). UDP
 ports can be opened through
-<option>networking.firewall.allowedUDPPorts</option>.  Also of
-interest is
+<option>networking.firewall.allowedUDPPorts</option>.</para>
+
+<para>To open ranges of TCP ports:
+
+<programlisting>
+networking.firewall.allowedTCPPortRanges = [
+  { from = 4000; to = 4007; }
+  { from = 8000; to = 8010; }
+];
+</programlisting>
+
+Similarly, UDP port ranges can be opened through
+<option>networking.firewall.allowedUDPPortRanges</option>.</para>
+
+<para>Also of interest is
 
 <programlisting>
 networking.firewall.allowPing = true;
diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml
index fc6082ce3afd..9c2c59006f15 100644
--- a/nixos/doc/manual/configuration/x-windows.xml
+++ b/nixos/doc/manual/configuration/x-windows.xml
@@ -115,13 +115,14 @@ hardware.opengl.driSupport32Bit = true;
 <para>Support for Synaptics touchpads (found in many laptops such as
 the Dell Latitude series) can be enabled as follows:
 <programlisting>
-services.xserver.synaptics.enable = true;
+services.xserver.libinput.enable = true;
 </programlisting>
 The driver has many options (see <xref linkend="ch-options"/>).  For
-instance, the following enables two-finger scrolling:
+instance, the following disables tap-to-click behavior:
 <programlisting>
-services.xserver.synaptics.twoFingerScroll = true;
+services.xserver.libinput.tapping = false;
 </programlisting>
+Note: the use of <literal>services.xserver.synaptics</literal> is deprecated since NixOS 17.09.
 </para>
 
 </simplesect>
@@ -129,7 +130,7 @@ services.xserver.synaptics.twoFingerScroll = true;
 <simplesect><title>GTK/Qt themes</title>
 
 <para>GTK themes can be installed either to user profile or system-wide (via
-<literal>system.environmentPackages</literal>). To make Qt 5 applications look similar
+<literal>environment.systemPackages</literal>). To make Qt 5 applications look similar
 to GTK2 ones, you can install <literal>qt5.qtbase.gtk</literal> package into your
 system environment. It should work for all Qt 5 library versions.
 </para>
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
index be793152f9ef..ed718c89eb77 100644
--- a/nixos/doc/manual/development/option-declarations.xml
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -22,6 +22,15 @@ options = {
 };
 </programlisting>
 
+The attribute names within the <replaceable>name</replaceable>
+attribute path must be camel cased in general but should, as an
+exception, match the
+<link
+xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
+package attribute name</link> when referencing a Nixpkgs package. For
+example, the option <varname>services.nix-serve.bindAddress</varname>
+references the <varname>nix-serve</varname> Nixpkgs package.
+
 </para>
 
 <para>The function <varname>mkOption</varname> accepts the following arguments.
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
index 83dcf0232d9d..ec940d5d2b86 100644
--- a/nixos/doc/manual/development/option-types.xml
+++ b/nixos/doc/manual/development/option-types.xml
@@ -110,6 +110,12 @@
     <listitem><para>A string. Multiple definitions are concatenated with a 
         collon <literal>":"</literal>.</para></listitem>
   </varlistentry>
+  <varlistentry>
+    <term><varname>types.strMatching</varname></term>
+    <listitem><para>A string matching a specific regular expression. Multiple
+    definitions cannot be merged.  The regular expression is processed using
+    <literal>builtins.match</literal>.</para></listitem>
+  </varlistentry>
 </variablelist>
 
  </section>
diff --git a/nixos/doc/manual/development/writing-nixos-tests.xml b/nixos/doc/manual/development/writing-nixos-tests.xml
index 7b25a39e83b8..a8f6aa00858e 100644
--- a/nixos/doc/manual/development/writing-nixos-tests.xml
+++ b/nixos/doc/manual/development/writing-nixos-tests.xml
@@ -272,8 +272,37 @@ startAll;
     </listitem>
   </varlistentry>
 
+  <varlistentry>
+    <term><methodname>systemctl</methodname></term>
+    <listitem>
+      <para>Runs <literal>systemctl</literal> commands with optional support for
+      <literal>systemctl --user</literal></para>
+    <para>
+      <programlisting>
+        $machine->systemctl("list-jobs --no-pager"); // runs `systemctl list-jobs --no-pager`
+        $machine->systemctl("list-jobs --no-pager", "any-user"); // spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager`
+      </programlisting>
+    </para>
+    </listitem>
+  </varlistentry>
+
 </variablelist>
 
 </para>
 
+<para>
+  To test user units declared by <literal>systemd.user.services</literal> the optional <literal>$user</literal>
+  argument can be used:
+
+  <programlisting>
+    $machine->start;
+    $machine->waitForX;
+    $machine->waitForUnit("xautolock.service", "x-session-user");
+  </programlisting>
+
+  This applies to <literal>systemctl</literal>, <literal>getUnitInfo</literal>,
+  <literal>waitForUnit</literal>, <literal>startJob</literal>
+  and <literal>stopJob</literal>.
+</para>
+
 </section>
diff --git a/nixos/doc/manual/installation/installing-uefi.xml b/nixos/doc/manual/installation/installing-uefi.xml
deleted file mode 100644
index 0d3eaa8bb1fb..000000000000
--- a/nixos/doc/manual/installation/installing-uefi.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<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-uefi-installation">
-
-<title>UEFI Installation</title>
-
-<para>NixOS can also be installed on UEFI systems.  The procedure
-is by and large the same as a BIOS installation, with the following
-changes:
-
-<itemizedlist>
-  <listitem>
-    <para>You should boot the live CD in UEFI mode (consult your
-    specific hardware's documentation for instructions). You may find
-    the <link
-    xlink:href="http://www.rodsbooks.com/refind">rEFInd
-    boot manager</link> useful.</para>
-  </listitem>
-  <listitem>
-    <para>Instead of <command>fdisk</command>, you should use
-    <command>gdisk</command> to partition your disks. You will need to
-    have a separate partition for <filename>/boot</filename> with
-    partition code EF00, and it should be formatted as a
-    <literal>vfat</literal> filesystem.</para>
-  </listitem>
-  <listitem>
-    <para>Instead of <option>boot.loader.grub.device</option>,
-    you must set <option>boot.loader.systemd-boot.enable</option> to
-    <literal>true</literal>. <command>nixos-generate-config</command>
-    should do this automatically for new configurations when booted in
-    UEFI mode.</para>
-  </listitem>
-  <listitem>
-    <para>After having mounted your installation partition to
-    <code>/mnt</code>, you must mount the <code>boot</code> partition
-    to <code>/mnt/boot</code>.</para>
-  </listitem>
-  <listitem>
-    <para>You may want to look at the options starting with
-    <option>boot.loader.efi</option> and <option>boot.loader.systemd-boot</option>
-    as well.</para>
-  </listitem>
-</itemizedlist>
-</para>
-
-</section>
diff --git a/nixos/doc/manual/installation/installing-usb.xml b/nixos/doc/manual/installation/installing-usb.xml
index 31d51816e39b..122a4745f194 100644
--- a/nixos/doc/manual/installation/installing-usb.xml
+++ b/nixos/doc/manual/installation/installing-usb.xml
@@ -11,10 +11,24 @@ a USB stick. You can use the <command>dd</command> utility to write the image:
 <command>dd if=<replaceable>path-to-image</replaceable>
 of=<replaceable>/dev/sdb</replaceable></command>. Be careful about specifying the
 correct drive; you can use the <command>lsblk</command> command to get a list of
-block devices. If you're on macOS you can run <command>diskutil list</command>
-to see the list of devices; the device you'll use for the USB must be ejected
-before writing the image.</para>
+block devices.</para>
 
+<para>On macOS:
+<programlisting>
+$ diskutil list
+[..]
+/dev/diskN (external, physical):
+   #:                       TYPE NAME                    SIZE       IDENTIFIER
+[..]
+$ diskutil unmountDisk diskN
+Unmount of all volumes on diskN was successful
+$ sudo dd bs=1m if=nix.iso of=/dev/rdiskN
+</programlisting>
+Using the 'raw' <command>rdiskN</command> device instead of <command>diskN</command>
+completes in minutes instead of hours. After <command>dd</command> completes, a GUI
+dialog "The disk you inserted was not readable by this computer" will pop up, which
+can be ignored.</para>
+         
 <para>The <command>dd</command> utility will write the image verbatim to the drive,
 making it the recommended option for both UEFI and non-UEFI installations. For
 non-UEFI installations, you can alternatively use
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index b0674307a563..ab9108c30a71 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -6,9 +6,18 @@
 
 <title>Installing NixOS</title>
 
+<para>NixOS can be installed on BIOS or UEFI systems.  The procedure
+for a UEFI installation is by and large the same as a BIOS installation. The differences are mentioned in the steps that follow.</para>
+
 <orderedlist>
 
-  <listitem><para>Boot from the CD.</para></listitem>
+  <listitem><para>Boot from the CD.</para>
+    <variablelist>
+      <varlistentry><term>UEFI systems</term>
+      <listitem><para>You should boot the live CD in UEFI mode
+  (consult your specific hardware's documentation for instructions).
+  You may find the <link xlink:href="http://www.rodsbooks.com/refind">rEFInd boot
+  manager</link> useful.</para></listitem></varlistentry></variablelist></listitem>
 
   <listitem><para>The CD contains a basic NixOS installation.  (It
   also contains Memtest86+, useful if you want to test new hardware).
@@ -50,7 +59,31 @@
   <itemizedlist>
 
     <listitem><para>For partitioning:
-    <command>fdisk</command>.</para></listitem>
+    <command>fdisk</command>.
+<screen>
+# fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
+-- for UEFI systems only
+> n      # <lineannotation>(create a new partition for /boot)</lineannotation>
+> 3      # <lineannotation>(make it a partition number 3)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+> +512M  # <lineannotation>(the size of the UEFI boot partition)</lineannotation>
+> t      # <lineannotation>(change the partition type ...)</lineannotation>
+> 3      # <lineannotation>(... of the boot partition ...)</lineannotation>
+> 1      # <lineannotation>(... to 'UEFI System')</lineannotation>
+-- for BIOS or UEFI systems
+> n      # <lineannotation>(create a new partition for /swap)</lineannotation>
+> 2      # <lineannotation>(make it a partition number 2)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+> +8G    # <lineannotation>(the size of the swap partition, set to whatever you like)</lineannotation>
+> n      # <lineannotation>(create a new partition for /)</lineannotation>
+> 1      # <lineannotation>(make it a partition number 1)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+>        # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation>
+> a      # <lineannotation>(make the partition bootable)</lineannotation>
+> x      # <lineannotation>(enter expert mode)</lineannotation>
+> f      # <lineannotation>(fix up the partition ordering)</lineannotation>
+> r      # <lineannotation>(exit expert mode)</lineannotation>
+> w      # <lineannotation>(write the partition table to disk and exit)</lineannotation></screen></para></listitem>
 
     <listitem><para>For initialising Ext4 partitions:
     <command>mkfs.ext4</command>.  It is recommended that you assign a
@@ -67,7 +100,25 @@
     <listitem><para>For creating swap partitions:
     <command>mkswap</command>.  Again it’s recommended to assign a
     label to the swap partition: <option>-L
-    <replaceable>label</replaceable></option>.</para></listitem>
+    <replaceable>label</replaceable></option>. For example:
+
+<screen>
+# mkswap -L swap /dev/sda2</screen>
+
+    </para></listitem>
+
+    <listitem>
+    <variablelist>
+      <varlistentry><term>UEFI systems</term>
+      <listitem><para>For creating boot partitions:
+    <command>mkfs.fat</command>.  Again it’s recommended to assign a
+    label to the boot partition: <option>-L
+    <replaceable>label</replaceable></option>. For example:
+
+<screen>
+# mkfs.fat -F 32 -L boot /dev/sda3</screen>
+
+    </para></listitem></varlistentry></variablelist></listitem>
 
     <listitem><para>For creating LVM volumes, the LVM commands, e.g.,
 
@@ -95,11 +146,27 @@
 
   </para></listitem>
 
+  <listitem>
+    <variablelist>
+      <varlistentry><term>UEFI systems</term>
+      <listitem><para>Mount the boot file system on <filename>/mnt/boot</filename>, e.g.
+
+<screen>
+# mount /dev/disk/by-label/boot /mnt/boot
+</screen>
+
+  </para></listitem></varlistentry></variablelist></listitem>
+
   <listitem><para>If your machine has a limited amount of memory, you
   may want to activate swap devices now (<command>swapon
   <replaceable>device</replaceable></command>).  The installer (or
   rather, the build actions that it may spawn) may need quite a bit of
-  RAM, depending on your configuration.</para></listitem>
+  RAM, depending on your configuration.
+
+<screen>
+# swapon /dev/sda2</screen>
+
+  </para></listitem>
 
   <listitem>
 
@@ -135,10 +202,25 @@
     install Emacs by running <literal>nix-env -i
     emacs</literal>.</para>
 
-    <para>You <emphasis>must</emphasis> set the option
+    <variablelist>
+
+      <varlistentry><term>BIOS systems</term>
+      <listitem><para>You <emphasis>must</emphasis> set the option
     <option>boot.loader.grub.device</option> to specify on which disk
     the GRUB boot loader is to be installed.  Without it, NixOS cannot
-    boot.</para>
+      boot.</para></listitem></varlistentry>
+
+      <varlistentry><term>UEFI systems</term>
+      <listitem><para>You <emphasis>must</emphasis> set the option
+      <option>boot.loader.systemd-boot.enable</option> to <literal>true</literal>.
+      <command>nixos-generate-config</command> should do this automatically for new
+      configurations when booted in
+      UEFI mode.</para>
+      <para>You may want to look at the options starting with
+      <option>boot.loader.efi</option> and <option>boot.loader.systemd-boot</option>
+      as well.</para></listitem></varlistentry>
+
+    </variablelist>
 
     <para>If there are other operating systems running on the machine before
     installing NixOS, the
@@ -247,10 +329,34 @@ drive (here <filename>/dev/sda</filename>).  <xref linkend="ex-config"
 <example xml:id='ex-install-sequence'><title>Commands for Installing NixOS on <filename>/dev/sda</filename></title>
 <screen>
 # fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation>
+-- for UEFI systems only
+> n      # <lineannotation>(create a new partition for /boot)</lineannotation>
+> 3      # <lineannotation>(make it a partition number 3)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+> +512M  # <lineannotation>(the size of the UEFI boot partition)</lineannotation>
+> t      # <lineannotation>(change the partition type ...)</lineannotation>
+> 3      # <lineannotation>(... of the boot partition ...)</lineannotation>
+> 1      # <lineannotation>(... to 'UEFI System')</lineannotation>
+-- for BIOS or UEFI systems
+> n      # <lineannotation>(create a new partition for /swap)</lineannotation>
+> 2      # <lineannotation>(make it a partition number 2)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+> +8G    # <lineannotation>(the size of the swap partition)</lineannotation>
+> n      # <lineannotation>(create a new partition for /)</lineannotation>
+> 1      # <lineannotation>(make it a partition number 1)</lineannotation>
+>        # <lineannotation>(press enter to accept the default)</lineannotation>
+>        # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation>
+> a      # <lineannotation>(make the partition bootable)</lineannotation>
+> x      # <lineannotation>(enter expert mode)</lineannotation>
+> f      # <lineannotation>(fix up the partition ordering)</lineannotation>
+> r      # <lineannotation>(exit expert mode)</lineannotation>
+> w      # <lineannotation>(write the partition table to disk and exit)</lineannotation>
 # mkfs.ext4 -L nixos /dev/sda1
 # mkswap -L swap /dev/sda2
 # swapon /dev/sda2
+# mkfs.fat -F 32 -L boot /dev/sda3        # <lineannotation>(for UEFI systems only)</lineannotation>
 # mount /dev/disk/by-label/nixos /mnt
+# mount /dev/disk/by-label/boot /mnt/boot # <lineannotation>(for UEFI systems only)</lineannotation>
 # nixos-generate-config --root /mnt
 # nano /mnt/etc/nixos/configuration.nix
 # nixos-install
@@ -267,7 +373,8 @@ drive (here <filename>/dev/sda</filename>).  <xref linkend="ex-config"
       ./hardware-configuration.nix
     ];
 
-  boot.loader.grub.device = "/dev/sda";
+  boot.loader.grub.device = "/dev/sda";   # <lineannotation>(for BIOS systems only)</lineannotation>
+  boot.loader.systemd-boot.enable = true; # <lineannotation>(for UEFI systems only)</lineannotation>
 
   # Note: setting fileSystems is generally not
   # necessary, since nixos-generate-config figures them out
@@ -279,7 +386,6 @@ drive (here <filename>/dev/sda</filename>).  <xref linkend="ex-config"
 }</screen>
 </example>
 
-<xi:include href="installing-uefi.xml" />
 <xi:include href="installing-usb.xml" />
 <xi:include href="installing-pxe.xml" />
 <xi:include href="installing-virtualbox-guest.xml" />
diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml
index 20a4838be880..9b2b474c60ce 100644
--- a/nixos/doc/manual/installation/obtaining.xml
+++ b/nixos/doc/manual/installation/obtaining.xml
@@ -12,11 +12,10 @@ download page</link>.  There are a number of installation options.  If
 you happen to have an optical drive and a spare CD, burning the
 image to CD and booting from that is probably the easiest option.
 Most people will need to prepare a USB stick to boot from.
-Unetbootin is recommended and the process is described in brief below.
-Note that systems which use UEFI require some additional manual steps.
-If you run into difficulty a number of alternative methods are presented
-in the <link
-xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
+<xref linkend="sec-booting-from-usb"/> describes the preferred method
+to prepare a USB stick.
+A number of alternative methods are presented in the <link
+xlink:href="https://nixos.wiki/wiki/NixOS_Installation_Guide#Making_the_installation_media">NixOS
 Wiki</link>.</para>
 
 <para>As an alternative to installing NixOS yourself, you can get a
diff --git a/nixos/doc/manual/release-notes/rl-1404.xml b/nixos/doc/manual/release-notes/rl-1404.xml
index 36f67ed88b0b..137caf14cba2 100644
--- a/nixos/doc/manual/release-notes/rl-1404.xml
+++ b/nixos/doc/manual/release-notes/rl-1404.xml
@@ -13,7 +13,7 @@ the following highlights:
 <itemizedlist>
 
   <listitem><para>Installation on UEFI systems is now supported.  See
-  <xref linkend="sec-uefi-installation"/> for
+  <xref linkend="sec-installation"/> for
   details.</para></listitem>
 
   <listitem><para>Systemd has been updated to version 212, which has
diff --git a/nixos/doc/manual/release-notes/rl-1803.xml b/nixos/doc/manual/release-notes/rl-1803.xml
index b0e29182127e..12ff2e39a1bf 100644
--- a/nixos/doc/manual/release-notes/rl-1803.xml
+++ b/nixos/doc/manual/release-notes/rl-1803.xml
@@ -20,6 +20,22 @@ has the following highlights: </para>
 <itemizedlist>
   <listitem>
     <para>
+      MariaDB 10.2, updated from 10.1, is now the default MySQL implementation. While upgrading a few changes
+      have been made to the infrastructure involved:
+      <itemizedlist>
+        <listitem>
+          <para>
+            <literal>libmysql</literal> has been deprecated, please use <literal>mysql.connector-c</literal>
+            instead, a compatibility passthru has been added to the MySQL packages.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The <literal>mysql57</literal> package has a new <literal>static</literal> output containing
+            the static libraries including <literal>libmysqld.a</literal>
+          </para>
+        </listitem>
+      </itemizedlist>
     </para>
   </listitem>
 </itemizedlist>
@@ -95,6 +111,34 @@ following incompatible changes:</para>
       <link xlink:href="https://search.nix.gsc.io/?q=stateVersion">here</link>.
     </para>
   </listitem>
+  <listitem>
+    <para>
+      <literal>cc-wrapper</literal>has been split in two; there is now also a <literal>bintools-wrapper</literal>.
+      The most commonly used files in <filename>nix-support</filename> are now split between the two wrappers.
+      Some commonly used ones, like <filename>nix-support/dynamic-linker</filename>, are duplicated for backwards compatability, even though they rightly belong only in <literal>bintools-wrapper</literal>.
+      Other more obscure ones are just moved.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The propagation logic has been changed.
+      The new logic, along with new types of dependencies that go with, is thoroughly documented in the "Specifying dependencies" section of the "Standard Environment" chapter of the nixpkgs manual.
+      <!-- That's <xref linkend="ssec-stdenv-attributes"> were we to merge the manuals. -->
+      The old logic isn't but is easy to describe: dependencies were propagated as the same type of dependency no matter what.
+      In practice, that means that many <function>propagatedNativeBuildInputs</function> should instead be  <function>propagatedBuildInputs</function>.
+      Thankfully, that was and is the least used type of dependency.
+      Also, it means that some <function>propagatedBuildInputs</function> should instead be <function>depsTargetTargetPropagated</function>.
+      Other types dependencies should be unaffected.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The <literal>memcached</literal> service no longer accept dynamic socket
+      paths via <option>services.memcached.socket</option>. Unix sockets can be
+      still enabled by <option>services.memcached.enableUnixSocket</option> and
+      will be accessible at <literal>/run/memcached/memcached.sock</literal>.
+    </para>
+  </listitem>
 </itemizedlist>
 
 </section>
@@ -131,6 +175,72 @@ following incompatible changes:</para>
       must be set to true.
     </para>
   </listitem>
+  <listitem>
+    <para>
+      The option <option>services.logstash.listenAddress</option> is now <literal>127.0.0.1</literal> by default.
+      Previously the default behaviour was to listen on all interfaces.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <literal>services.btrfs.autoScrub</literal> has been added, to
+      periodically check btrfs filesystems for data corruption.
+      If there's a correct copy available, it will automatically repair
+      corrupted blocks.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <literal>displayManager.lightdm.greeters.gtk.clock-format.</literal>
+      has been added, the clock format string (as expected by
+      strftime, e.g. <literal>%H:%M</literal>) to use with the lightdm
+      gtk greeter panel.
+    </para>
+    <para>
+      If set to null the default clock format is used.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      <literal>displayManager.lightdm.greeters.gtk.indicators</literal>
+      has been added, a list of allowed indicator modules to use with
+      the lightdm gtk greeter panel.
+    </para>
+    <para>
+      Built-in indicators include <literal>~a11y</literal>,
+      <literal>~language</literal>, <literal>~session</literal>,
+      <literal>~power</literal>, <literal>~clock</literal>,
+      <literal>~host</literal>, <literal>~spacer</literal>. Unity
+      indicators can be represented by short name
+      (e.g. <literal>sound</literal>, <literal>power</literal>),
+      service file name, or absolute path.
+    </para>
+    <para>
+      If set to <literal>null</literal> the default indicators are
+      used.
+    </para>
+    <para>
+      In order to have the previous default configuration add
+<programlisting>
+  services.xserver.displayManager.lightdm.greeters.gtk.indicators = [
+    "~host" "~spacer"
+    "~clock" "~spacer"
+    "~session"
+    "~language"
+    "~a11y"
+    "~power"
+  ];
+</programlisting>
+      to your <literal>configuration.nix</literal>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The NixOS test driver supports user services declared by <literal>systemd.user.services</literal>.
+      The methods <literal>waitForUnit</literal>, <literal>getUnitInfo</literal>, <literal>startJob</literal>
+      and <literal>stopJob</literal> provide an optional <literal>$user</literal> argument for that purpose.
+    </para>
+  </listitem>
 </itemizedlist>
 
 </section>
diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix
index bf25e0cab259..636d0223fb77 100644
--- a/nixos/lib/make-disk-image.nix
+++ b/nixos/lib/make-disk-image.nix
@@ -129,6 +129,9 @@ let format' = format; in let
     # TODO: Nix really likes to chown things it creates to its current user...
     fakeroot nixos-prepare-root $root ${channelSources} ${config.system.build.toplevel} closure
 
+    # fakeroot seems to always give the owner write permissions, which we do not want
+    find $root/nix/store -mindepth 1 -maxdepth 1 -type f -o -type d | xargs chmod -R a-w
+
     echo "copying staging root to image..."
     cptofs ${optionalString partitioned "-P 1"} -t ${fsType} -i $diskImage $root/* /
   '';
@@ -150,8 +153,6 @@ in pkgs.vmTools.runInLinuxVM (
     }
     ''
       ${if partitioned then ''
-        . /sys/class/block/vda1/uevent
-        mknod /dev/vda1 b $MAJOR $MINOR
         rootDisk=/dev/vda1
       '' else ''
         rootDisk=/dev/vda
diff --git a/nixos/lib/make-ext4-fs.nix b/nixos/lib/make-ext4-fs.nix
index f06649e1991a..21c69ed560a3 100644
--- a/nixos/lib/make-ext4-fs.nix
+++ b/nixos/lib/make-ext4-fs.nix
@@ -10,7 +10,7 @@
 pkgs.stdenv.mkDerivation {
   name = "ext4-fs.img";
 
-  buildInputs = with pkgs; [e2fsprogs libfaketime perl];
+  nativeBuildInputs = with pkgs; [e2fsprogs libfaketime perl];
 
   # For obtaining the closure of `storePaths'.
   exportReferencesGraph =
diff --git a/nixos/lib/make-squashfs.nix b/nixos/lib/make-squashfs.nix
index 4100af27becb..9d47a3222cc2 100644
--- a/nixos/lib/make-squashfs.nix
+++ b/nixos/lib/make-squashfs.nix
@@ -8,7 +8,7 @@
 stdenv.mkDerivation {
   name = "squashfs.img";
 
-  buildInputs = [perl squashfsTools];
+  nativeBuildInputs = [perl squashfsTools];
 
   # For obtaining the closure of `storeContents'.
   exportReferencesGraph =
@@ -19,6 +19,33 @@ stdenv.mkDerivation {
       # Add the closures of the top-level store objects.
       storePaths=$(perl ${pathsFromGraph} closure-*)
 
+      # If a Hydra slave happens to have store paths with bad permissions/mtime,
+      # abort now so that they don't end up in ISO images in the channel.
+      # https://github.com/NixOS/nixpkgs/issues/32242
+      hasBadPaths=""
+      for path in $storePaths; do
+        if [ -h "$path" ]; then
+          continue
+        fi
+
+        mtime=$(stat -c %Y "$path")
+        mode=$(stat -c %a "$path")
+
+        if [ "$mtime" != 1 ]; then
+          echo "Store path '$path' has an invalid mtime."
+          hasBadPaths=1
+        fi
+        if [ "$mode" != 444 ] && [ "$mode" != 555 ]; then
+          echo "Store path '$path' has invalid permissions ($mode)."
+          hasBadPaths=1
+        fi
+      done
+
+      if [ -n "$hasBadPaths" ]; then
+        echo "You have bad paths in your store, please fix them."
+        exit 1
+      fi
+
       # Also include a manifest of the closures in a format suitable
       # for nix-store --load-db.
       printRegistration=1 perl ${pathsFromGraph} closure-* > nix-path-registration
diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm
index a01c3c336a1b..78598b3efb4b 100644
--- a/nixos/lib/test-driver/Machine.pm
+++ b/nixos/lib/test-driver/Machine.pm
@@ -362,8 +362,8 @@ sub mustFail {
 
 
 sub getUnitInfo {
-    my ($self, $unit) = @_;
-    my ($status, $lines) = $self->execute("systemctl --no-pager show '$unit'");
+    my ($self, $unit, $user) = @_;
+    my ($status, $lines) = $self->systemctl("--no-pager show \"$unit\"", $user);
     return undef if $status != 0;
     my $info = {};
     foreach my $line (split '\n', $lines) {
@@ -373,6 +373,16 @@ sub getUnitInfo {
     return $info;
 }
 
+sub systemctl {
+    my ($self, $q, $user) = @_;
+    if ($user) {
+        $q =~ s/'/\\'/g;
+        return $self->execute("su -l $user -c \$'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user $q'");
+    }
+
+    return $self->execute("systemctl $q");
+}
+
 # Fail if the given systemd unit is not in the "active" state.
 sub requireActiveUnit {
     my ($self, $unit) = @_;
@@ -387,16 +397,16 @@ sub requireActiveUnit {
 
 # Wait for a systemd unit to reach the "active" state.
 sub waitForUnit {
-    my ($self, $unit) = @_;
+    my ($self, $unit, $user) = @_;
     $self->nest("waiting for unit ‘$unit’", sub {
         retry sub {
-            my $info = $self->getUnitInfo($unit);
+            my $info = $self->getUnitInfo($unit, $user);
             my $state = $info->{ActiveState};
             die "unit ‘$unit’ reached state ‘$state’\n" if $state eq "failed";
             if ($state eq "inactive") {
                 # If there are no pending jobs, then assume this unit
                 # will never reach active state.
-                my ($status, $jobs) = $self->execute("systemctl list-jobs --full 2>&1");
+                my ($status, $jobs) = $self->systemctl("list-jobs --full 2>&1", $user);
                 if ($jobs =~ /No jobs/) {  # FIXME: fragile
                     # Handle the case where the unit may have started
                     # between the previous getUnitInfo() and
@@ -430,14 +440,14 @@ sub waitForFile {
 }
 
 sub startJob {
-    my ($self, $jobName) = @_;
-    $self->execute("systemctl start $jobName");
+    my ($self, $jobName, $user) = @_;
+    $self->systemctl("start $jobName", $user);
     # FIXME: check result
 }
 
 sub stopJob {
-    my ($self, $jobName) = @_;
-    $self->execute("systemctl stop $jobName");
+    my ($self, $jobName, $user) = @_;
+    $self->systemctl("stop $jobName", $user);
 }
 
 
diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh
index dfc0f8d11465..347e6b9c6e0d 100755
--- a/nixos/maintainers/scripts/ec2/create-amis.sh
+++ b/nixos/maintainers/scripts/ec2/create-amis.sh
@@ -18,7 +18,7 @@ rm -f ec2-amis.nix
 
 types="hvm"
 stores="ebs"
-regions="eu-west-1 eu-west-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
+regions="eu-west-1 eu-west-2 eu-west-3 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
 
 for type in $types; do
     link=$stateDir/$type
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index 619f36cd5150..4101ef82f3e1 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -290,8 +290,8 @@ in
           ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd
         ''}
 
-        # Make sure resolv.conf is up to date if not managed by systemd
-        ${optionalString (!config.services.resolved.enable) ''
+        # Make sure resolv.conf is up to date if not managed manually or by systemd
+        ${optionalString (!config.environment.etc?"resolv.conf") ''
           ${pkgs.openresolv}/bin/resolvconf -u
         ''}
       '';
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix
index ae3e17ac27b6..e1c4d0d602af 100644
--- a/nixos/modules/config/no-x-libs.nix
+++ b/nixos/modules/config/no-x-libs.nix
@@ -35,7 +35,7 @@ with lib;
       networkmanager_pptp = pkgs.networkmanager_pptp.override { withGnome = false; };
       networkmanager_vpnc = pkgs.networkmanager_vpnc.override { withGnome = false; };
       networkmanager_iodine = pkgs.networkmanager_iodine.override { withGnome = false; };
-      pinentry = pkgs.pinentry.override { gtk2 = null; qt4 = null; };
+      pinentry = pkgs.pinentry_ncurses;
     };
   };
 }
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index 0f6046339b37..52239b619126 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -18,17 +18,17 @@ with lib;
 
   };
 
-  config = {
-
-    boot.loader.grub.version = 2;
-
+  config = rec {
     # Don't build the GRUB menu builder script, since we don't need it
     # here and it causes a cyclic dependency.
     boot.loader.grub.enable = false;
 
     # !!! Hack - attributes expected by other modules.
-    system.boot.loader.kernelFile = "bzImage";
-    environment.systemPackages = [ pkgs.grub2 pkgs.grub2_efi pkgs.syslinux ];
+    environment.systemPackages = [ pkgs.grub2_efi ]
+      ++ (if pkgs.stdenv.system == "aarch64-linux"
+          then []
+          else [ pkgs.grub2 pkgs.syslinux ]);
+    system.boot.loader.kernelFile = pkgs.stdenv.platform.kernelTarget;
 
     fileSystems."/" =
       { fsType = "tmpfs";
@@ -84,7 +84,12 @@ with lib;
         ];
     };
 
-    system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" "#!ipxe\nkernel bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}\ninitrd initrd\nboot";
+    system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
+      #!ipxe
+      kernel ${pkgs.stdenv.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+      initrd initrd
+      boot
+    '';
 
     boot.loader.timeout = 10;
 
diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix
index 321fb9a2030a..131c779b1ab1 100644
--- a/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,5 +1,6 @@
 {
-  x86_64-linux = "/nix/store/b4s1gxiis1ryvybnjhdjvgc5sr1nq0ys-nix-1.11.15";
-  i686-linux = "/nix/store/kgb5hs7qw13bvb6icramv1ry9dard3h9-nix-1.11.15";
-  x86_64-darwin = "/nix/store/dgwz3dxdzs2wwd7pg7cdhvl8rv0qpnbj-nix-1.11.15";
+  x86_64-linux = "/nix/store/gy4yv67gv3j6in0lalw37j353zdmfcwm-nix-1.11.16";
+  i686-linux = "/nix/store/ifmyq5ryfxhhrzh62hiq65xyz1fwffga-nix-1.11.16";
+  aarch64-linux = "/nix/store/y9mfv3sx75mbfibf1zna1kq9v98fk2nb-nix-1.11.16";
+  x86_64-darwin = "/nix/store/hwpp7kia2f0in5ns2hiw41q38k30jpj2-nix-1.11.16";
 }
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index c10b5a0ec932..c6440dd906fd 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -65,7 +65,7 @@
       foldingathome = 37;
       sabnzbd = 38;
       #kdm = 39; # dropped in 17.03
-      ghostone = 40;
+      #ghostone = 40; # dropped in 18.03
       git = 41;
       fourstore = 42;
       fourstorehttp = 43;
@@ -197,10 +197,10 @@
       #input = 174; # unused
       sddm = 175;
       tss = 176;
-      memcached = 177;
+      #memcached = 177; removed 2018-01-03
       ntp = 179;
       zabbix = 180;
-      redis = 181;
+      #redis = 181; removed 2018-01-03
       unifi = 183;
       uptimed = 184;
       zope2 = 185;
@@ -281,8 +281,8 @@
       stanchion = 262;
       riak-cs = 263;
       infinoted = 264;
-      keystone = 265;
-      glance = 266;
+      # keystone = 265; # unused, removed 2017-12-13
+      # glance = 266; # unused, removed 2017-12-13
       couchpotato = 267;
       gogs = 268;
       pdns-recursor = 269;
@@ -348,7 +348,7 @@
       #foldingathome = 37; # unused
       #sabnzd = 38; # unused
       #kdm = 39; # unused, even before 17.03
-      ghostone = 40;
+      #ghostone = 40; # dropped in 18.03
       git = 41;
       fourstore = 42;
       fourstorehttp = 43;
@@ -475,10 +475,10 @@
       input = 174;
       sddm = 175;
       tss = 176;
-      #memcached = 177; # unused
+      #memcached = 177; # unused, removed 2018-01-03
       #ntp = 179; # unused
       #zabbix = 180; # unused
-      #redis = 181; # unused
+      #redis = 181; # unused, removed 2018-01-03
       #unifi = 183; # unused
       #uptimed = 184; # unused
       #zope2 = 185; # unused
@@ -551,8 +551,8 @@
       stanchion = 262;
       riak-cs = 263;
       infinoted = 264;
-      keystone = 265;
-      glance = 266;
+      # keystone = 265; # unused, removed 2017-12-13
+      # glance = 266; # unused, removed 2017-12-13
       couchpotato = 267;
       gogs = 268;
       kresd = 270;
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 5e2161aacb66..8d329b5b4b25 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -71,6 +71,7 @@
   ./programs/bcc.nix
   ./programs/blcr.nix
   ./programs/browserpass.nix
+  ./programs/ccache.nix
   ./programs/cdemu.nix
   ./programs/chromium.nix
   ./programs/command-not-found/command-not-found.nix
@@ -91,6 +92,7 @@
   ./programs/npm.nix
   ./programs/oblogout.nix
   ./programs/qt5ct.nix
+  ./programs/rootston.nix
   ./programs/screen.nix
   ./programs/slock.nix
   ./programs/shadow.nix
@@ -104,6 +106,7 @@
   ./programs/tmux.nix
   ./programs/venus.nix
   ./programs/vim.nix
+  ./programs/way-cooler.nix
   ./programs/wireshark.nix
   ./programs/xfs_quota.nix
   ./programs/xonsh.nix
@@ -217,7 +220,6 @@
   ./services/editors/emacs.nix
   ./services/editors/infinoted.nix
   ./services/games/factorio.nix
-  ./services/games/ghost-one.nix
   ./services/games/minecraft-server.nix
   ./services/games/minetest-server.nix
   ./services/games/terraria.nix
@@ -239,9 +241,11 @@
   ./services/hardware/tlp.nix
   ./services/hardware/thinkfan.nix
   ./services/hardware/trezord.nix
+  ./services/hardware/u2f.nix
   ./services/hardware/udev.nix
   ./services/hardware/udisks2.nix
   ./services/hardware/upower.nix
+  ./services/hardware/usbmuxd.nix
   ./services/hardware/thermald.nix
   ./services/logging/SystemdJournal2Gelf.nix
   ./services/logging/awstats.nix
@@ -257,6 +261,8 @@
   ./services/logging/rsyslogd.nix
   ./services/logging/syslog-ng.nix
   ./services/logging/syslogd.nix
+  ./services/mail/clamsmtp.nix
+  ./services/mail/dkimproxy-out.nix
   ./services/mail/dovecot.nix
   ./services/mail/dspam.nix
   ./services/mail/exim.nix
@@ -328,6 +334,7 @@
   ./services/misc/nix-ssh-serve.nix
   ./services/misc/nzbget.nix
   ./services/misc/octoprint.nix
+  ./services/misc/osrm.nix
   ./services/misc/packagekit.nix
   ./services/misc/parsoid.nix
   ./services/misc/phd.nix
@@ -352,6 +359,7 @@
   ./services/misc/taskserver
   ./services/misc/tzupdate.nix
   ./services/misc/uhub.nix
+  ./services/misc/xmr-stak.nix
   ./services/misc/zookeeper.nix
   ./services/monitoring/apcupsd.nix
   ./services/monitoring/arbtt.nix
@@ -398,7 +406,9 @@
   ./services/monitoring/vnstat.nix
   ./services/monitoring/zabbix-agent.nix
   ./services/monitoring/zabbix-server.nix
+  ./services/network-filesystems/beegfs.nix
   ./services/network-filesystems/cachefilesd.nix
+  ./services/network-filesystems/davfs2.nix
   ./services/network-filesystems/drbd.nix
   ./services/network-filesystems/glusterfs.nix
   ./services/network-filesystems/kbfs.nix
@@ -588,6 +598,7 @@
   ./services/system/cloud-init.nix
   ./services/system/dbus.nix
   ./services/system/earlyoom.nix
+  ./services/system/localtime.nix
   ./services/system/kerberos.nix
   ./services/system/nscd.nix
   ./services/system/saslauthd.nix
@@ -671,6 +682,7 @@
   ./system/activation/top-level.nix
   ./system/boot/coredump.nix
   ./system/boot/emergency-mode.nix
+  ./system/boot/grow-partition.nix
   ./system/boot/initrd-network.nix
   ./system/boot/initrd-ssh.nix
   ./system/boot/kernel.nix
@@ -737,6 +749,7 @@
   ./virtualisation/lxcfs.nix
   ./virtualisation/lxd.nix
   ./virtualisation/amazon-options.nix
+  ./virtualisation/hyperv-guest.nix
   ./virtualisation/openvswitch.nix
   ./virtualisation/parallels-guest.nix
   ./virtualisation/rkt.nix
@@ -745,6 +758,4 @@
   ./virtualisation/vmware-guest.nix
   ./virtualisation/xen-dom0.nix
   ./virtualisation/xe-guest-utilities.nix
-  ./virtualisation/openstack/keystone.nix
-  ./virtualisation/openstack/glance.nix
 ]
diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix
index 3c7e516c497f..f56640f19782 100644
--- a/nixos/modules/profiles/all-hardware.nix
+++ b/nixos/modules/profiles/all-hardware.nix
@@ -19,13 +19,12 @@
       "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4"
       "sata_uli" "sata_via" "sata_vsc"
 
-      "pata_ali" "pata_amd" "pata_artop" "pata_atiixp"
-      "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar"
+      "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" "pata_efar"
       "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3"
       "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell"
       "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix"
       "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000"
-      "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis"
+      "pata_serverworks" "pata_sil680" "pata_sis"
       "pata_sl82c105" "pata_triflex" "pata_via"
       "pata_winbond"
 
diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix
index ef1acdfe66e6..1abdb4973a44 100644
--- a/nixos/modules/programs/bash/bash.nix
+++ b/nixos/modules/programs/bash/bash.nix
@@ -14,13 +14,16 @@ let
   bashCompletion = optionalString cfg.enableCompletion ''
     # Check whether we're running a version of Bash that has support for
     # programmable completion. If we do, enable all modules installed in
-    # the system (and user profile).
+    # the system and user profile in obsolete /etc/bash_completion.d/
+    # directories. Bash loads completions in all
+    # $XDG_DATA_DIRS/share/bash-completion/completions/
+    # on demand, so they do not need to be sourced here.
     if shopt -q progcomp &>/dev/null; then
       . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
       nullglobStatus=$(shopt -p nullglob)
       shopt -s nullglob
       for p in $NIX_PROFILES; do
-        for m in "$p/etc/bash_completion.d/"* "$p/share/bash-completion/completions/"*; do
+        for m in "$p/etc/bash_completion.d/"*; do
           . $m
         done
       done
diff --git a/nixos/modules/programs/ccache.nix b/nixos/modules/programs/ccache.nix
new file mode 100644
index 000000000000..874774c72b47
--- /dev/null
+++ b/nixos/modules/programs/ccache.nix
@@ -0,0 +1,83 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+  cfg = config.programs.ccache;
+in {
+  options.programs.ccache = {
+    # host configuration
+    enable = mkEnableOption "CCache";
+    cacheDir = mkOption {
+      type = types.path;
+      description = "CCache directory";
+      default = "/var/cache/ccache";
+    };
+    # target configuration
+    packageNames = mkOption {
+      type = types.listOf types.str;
+      description = "Nix top-level packages to be compiled using CCache";
+      default = [];
+      example = [ "wxGTK30" "qt48" "ffmpeg_3_3" "libav_all" ];
+    };
+  };
+
+  config = mkMerge [
+    # host configuration
+    (mkIf cfg.enable {
+      systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 root nixbld -" ];
+
+      # "nix-ccache --show-stats" and "nix-ccache --clear"
+      security.wrappers.nix-ccache = {
+        group = "nixbld";
+        setgid = true;
+        source = pkgs.writeScript "nix-ccache.pl" ''
+          #!${pkgs.perl}/bin/perl
+
+          %ENV=( CCACHE_DIR => '${cfg.cacheDir}' );
+          sub untaint {
+            my $v = shift;
+            return '-C' if $v eq '-C' || $v eq '--clear';
+            return '-V' if $v eq '-V' || $v eq '--version';
+            return '-s' if $v eq '-s' || $v eq '--show-stats';
+            return '-z' if $v eq '-z' || $v eq '--zero-stats';
+            exec('${pkgs.ccache}/bin/ccache', '-h');
+          }
+          exec('${pkgs.ccache}/bin/ccache', map { untaint $_ } @ARGV);
+        '';
+      };
+    })
+
+    # target configuration
+    (mkIf (cfg.packageNames != []) {
+      nixpkgs.overlays = [
+        (self: super: genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; }))
+
+        (self: super: {
+          ccacheWrapper = super.ccacheWrapper.override {
+            extraConfig = ''
+              export CCACHE_COMPRESS=1
+              export CCACHE_DIR="${cfg.cacheDir}"
+              export CCACHE_UMASK=007
+              if [ ! -d "$CCACHE_DIR" ]; then
+                echo "====="
+                echo "Directory '$CCACHE_DIR' does not exist"
+                echo "Please create it with:"
+                echo "  sudo mkdir -m0770 '$CCACHE_DIR'"
+                echo "  sudo chown root:nixbld '$CCACHE_DIR'"
+                echo "====="
+                exit 1
+              fi
+              if [ ! -w "$CCACHE_DIR" ]; then
+                echo "====="
+                echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)"
+                echo "Please verify its access permissions"
+                echo "====="
+                exit 1
+              fi
+            '';
+          };
+        })
+      ];
+    })
+  ];
+}
\ No newline at end of file
diff --git a/nixos/modules/programs/dconf.nix b/nixos/modules/programs/dconf.nix
index 1b7e20799819..27bfdf022e7d 100644
--- a/nixos/modules/programs/dconf.nix
+++ b/nixos/modules/programs/dconf.nix
@@ -1,7 +1,8 @@
-{ config, lib, ... }:
+{ config, lib, pkgs, ... }:
+
+with lib;
 
 let
-  inherit (lib) mkOption mkIf types mapAttrsToList;
   cfg = config.programs.dconf;
 
   mkDconfProfile = name: path:
@@ -13,6 +14,7 @@ in
 
   options = {
     programs.dconf = {
+      enable = mkEnableOption "dconf";
 
       profiles = mkOption {
         type = types.attrsOf types.path;
@@ -26,9 +28,15 @@ in
 
   ###### implementation
 
-  config = mkIf (cfg.profiles != {}) {
-    environment.etc =
+  config = mkIf (cfg.profiles != {} || cfg.enable) {
+    environment.etc = optionals (cfg.profiles != {})
       (mapAttrsToList mkDconfProfile cfg.profiles);
+
+    environment.variables.GIO_EXTRA_MODULES = optional cfg.enable
+      "${pkgs.gnome3.dconf.lib}/lib/gio/modules";
+    # https://github.com/NixOS/nixpkgs/pull/31891
+    #environment.variables.XDG_DATA_DIRS = optional cfg.enable
+    #  "$(echo ${pkgs.gnome3.gsettings_desktop_schemas}/share/gsettings-schemas/gsettings-desktop-schemas-*)";
   };
 
 }
diff --git a/nixos/modules/programs/rootston.nix b/nixos/modules/programs/rootston.nix
new file mode 100644
index 000000000000..1946b1db657b
--- /dev/null
+++ b/nixos/modules/programs/rootston.nix
@@ -0,0 +1,103 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.rootston;
+
+  rootstonWrapped = pkgs.writeScriptBin "rootston" ''
+    #! ${pkgs.stdenv.shell}
+    if [[ "$#" -ge 1 ]]; then
+      exec ${pkgs.rootston}/bin/rootston "$@"
+    else
+      ${cfg.extraSessionCommands}
+      exec ${pkgs.rootston}/bin/rootston -C ${cfg.configFile}
+    fi
+  '';
+in {
+  options.programs.rootston = {
+    enable = mkEnableOption ''
+      rootston, the reference compositor for wlroots. The purpose of rootston
+      is to test and demonstrate the features of wlroots (if you want a real
+      Wayland compositor you should e.g. use Sway instead). You can manually
+      start the compositor by running "rootston" from a terminal'';
+
+    extraSessionCommands = mkOption {
+      type = types.lines;
+      default = "";
+      example = ''
+        # Define a keymap (US QWERTY is the default)
+        export XKB_DEFAULT_LAYOUT=de,us
+        export XKB_DEFAULT_VARIANT=nodeadkeys
+        export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,caps:escape
+      '';
+      description = ''
+        Shell commands executed just before rootston is started.
+      '';
+    };
+
+    extraPackages = mkOption {
+      type = with types; listOf package;
+      default = with pkgs; [
+        westonLite xwayland rofi
+      ];
+      defaultText = literalExample ''
+        with pkgs; [
+          westonLite xwayland rofi
+        ]
+      '';
+      example = literalExample "[ ]";
+      description = ''
+        Extra packages to be installed system wide.
+      '';
+    };
+
+    config = mkOption {
+      type = types.str;
+      default = ''
+        [keyboard]
+        meta-key = Logo
+
+        # Sway/i3 like Keybindings
+        # Maps key combinations with commands to execute
+        # Commands include:
+        # - "exit" to stop the compositor
+        # - "exec" to execute a shell command
+        # - "close" to close the current view
+        # - "next_window" to cycle through windows
+        [bindings]
+        Logo+Shift+e = exit
+        Logo+q = close
+        Logo+m = maximize
+        Alt+Tab = next_window
+        Logo+Return = exec weston-terminal
+        Logo+d = exec rofi -show run
+      '';
+      description = ''
+        Default configuration for rootston (used when called without any
+        parameters).
+      '';
+    };
+
+    configFile = mkOption {
+      type = types.path;
+      default = "/etc/rootston.ini";
+      example = literalExample "${pkgs.rootston}/etc/rootston.ini";
+      description = ''
+        Path to the default rootston configuration file (the "config" option
+        will have no effect if you change the path).
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.etc."rootston.ini".text = cfg.config;
+    environment.systemPackages = [ rootstonWrapped ] ++ cfg.extraPackages;
+
+    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultFonts = mkDefault true;
+    programs.dconf.enable = mkDefault true;
+  };
+
+  meta.maintainers = with lib.maintainers; [ primeos gnidorah ];
+}
diff --git a/nixos/modules/programs/sway.nix b/nixos/modules/programs/sway.nix
index 5d13b90daace..d9503d6004ff 100644
--- a/nixos/modules/programs/sway.nix
+++ b/nixos/modules/programs/sway.nix
@@ -4,36 +4,42 @@ with lib;
 
 let
   cfg = config.programs.sway;
-  sway = pkgs.sway;
+  swayPackage = pkgs.sway;
 
-  swayWrapped = pkgs.writeScriptBin "sway" ''
-    #! ${pkgs.stdenv.shell}
-    if [ "$1" != "" ]; then
-      sway-setcap "$@"
-      exit
+  swayWrapped = pkgs.writeShellScriptBin "sway" ''
+    if [[ "$#" -ge 1 ]]; then
+      exec sway-setcap "$@"
+    else
+      ${cfg.extraSessionCommands}
+      exec ${pkgs.dbus.dbus-launch} --exit-with-session sway-setcap
     fi
-    ${cfg.extraSessionCommands}
-    exec ${pkgs.dbus.dbus-launch} --exit-with-session sway-setcap
   '';
   swayJoined = pkgs.symlinkJoin {
-    name = "sway-wrapped";
-    paths = [ swayWrapped sway ];
+    name = "sway-joined";
+    paths = [ swayWrapped swayPackage ];
   };
-in
-{
+in {
   options.programs.sway = {
-    enable = mkEnableOption "sway";
+    enable = mkEnableOption ''
+      the tiling Wayland compositor Sway. After adding yourself to the "sway"
+      group you can manually launch Sway by executing "sway" from a terminal.
+      If you call "sway" with any parameters the extraSessionCommands won't be
+      executed and Sway won't be launched with dbus-launch'';
 
     extraSessionCommands = mkOption {
-      default     = "";
-      type        = types.lines;
+      type = types.lines;
+      default = "";
       example = ''
-        export XKB_DEFAULT_LAYOUT=us,de
-        export XKB_DEFAULT_VARIANT=,nodeadkeys
-        export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,
+        # Define a keymap (US QWERTY is the default)
+        export XKB_DEFAULT_LAYOUT=de,us
+        export XKB_DEFAULT_VARIANT=nodeadkeys
+        export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,caps:escape
+        # Change the Keyboard repeat delay and rate
+        export WLC_REPEAT_DELAY=660
+        export WLC_REPEAT_RATE=25
       '';
       description = ''
-        Shell commands executed just before sway is started.
+        Shell commands executed just before Sway is started.
       '';
     };
 
@@ -42,9 +48,12 @@ in
       default = with pkgs; [
         i3status xwayland rxvt_unicode dmenu
       ];
+      defaultText = literalExample ''
+        with pkgs; [ i3status xwayland rxvt_unicode dmenu ];
+      '';
       example = literalExample ''
         with pkgs; [
-          i3status xwayland rxvt_unicode dmenu
+          i3lock light termite
         ]
       '';
       description = ''
@@ -57,7 +66,7 @@ in
     environment.systemPackages = [ swayJoined ] ++ cfg.extraPackages;
     security.wrappers.sway = {
       program = "sway-setcap";
-      source = "${sway}/bin/sway";
+      source = "${swayPackage}/bin/sway";
       capabilities = "cap_sys_ptrace,cap_sys_tty_config=eip";
       owner = "root";
       group = "sway";
@@ -65,8 +74,12 @@ in
     };
 
     users.extraGroups.sway = {};
+    security.pam.services.swaylock = {};
 
     hardware.opengl.enable = mkDefault true;
     fonts.enableDefaultFonts = mkDefault true;
+    programs.dconf.enable = mkDefault true;
   };
+
+  meta.maintainers = with lib.maintainers; [ gnidorah primeos ];
 }
diff --git a/nixos/modules/programs/tmux.nix b/nixos/modules/programs/tmux.nix
index ed1d88a420a2..1eb6fa6bf2fa 100644
--- a/nixos/modules/programs/tmux.nix
+++ b/nixos/modules/programs/tmux.nix
@@ -151,6 +151,15 @@ in {
         type = types.str;
         description = "Set the $TERM variable.";
       };
+
+      secureSocket = mkOption {
+        default = true;
+        type = types.bool;
+        description = ''
+          Store tmux socket under /run, which is more secure than /tmp, but as a
+          downside it doesn't survive user logout.
+        '';
+      };
     };
   };
 
@@ -163,7 +172,7 @@ in {
       systemPackages = [ pkgs.tmux ];
 
       variables = {
-        TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}'';
+        TMUX_TMPDIR = lib.optional cfg.secureSocket ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}'';
       };
     };
   };
diff --git a/nixos/modules/programs/way-cooler.nix b/nixos/modules/programs/way-cooler.nix
new file mode 100644
index 000000000000..633e959be9f3
--- /dev/null
+++ b/nixos/modules/programs/way-cooler.nix
@@ -0,0 +1,78 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.way-cooler;
+  way-cooler = pkgs.way-cooler;
+
+  wcWrapped = pkgs.writeShellScriptBin "way-cooler" ''
+    ${cfg.extraSessionCommands}
+    exec ${pkgs.dbus.dbus-launch} --exit-with-session ${way-cooler}/bin/way-cooler
+  '';
+  wcJoined = pkgs.symlinkJoin {
+    name = "way-cooler-wrapped";
+    paths = [ wcWrapped way-cooler ];
+  };
+  configFile = readFile "${way-cooler}/etc/way-cooler/init.lua";
+  spawnBar = ''
+    util.program.spawn_at_startup("lemonbar");
+  '';
+in
+{
+  options.programs.way-cooler = {
+    enable = mkEnableOption "way-cooler";
+
+    extraSessionCommands = mkOption {
+      default     = "";
+      type        = types.lines;
+      example = ''
+        export XKB_DEFAULT_LAYOUT=us,de
+        export XKB_DEFAULT_VARIANT=,nodeadkeys
+        export XKB_DEFAULT_OPTIONS=grp:caps_toggle,
+      '';
+      description = ''
+        Shell commands executed just before way-cooler is started.
+      '';
+    };
+
+    extraPackages = mkOption {
+      type = with types; listOf package;
+      default = with pkgs; [
+        westonLite xwayland dmenu
+      ];
+      example = literalExample ''
+        with pkgs; [
+          westonLite xwayland dmenu
+        ]
+      '';
+      description = ''
+        Extra packages to be installed system wide.
+      '';
+    };
+
+    enableBar = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to enable an unofficial bar.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ wcJoined ] ++ cfg.extraPackages;
+
+    security.pam.services.wc-lock = {};
+    environment.etc."way-cooler/init.lua".text = ''
+      ${configFile}
+      ${optionalString cfg.enableBar spawnBar}
+    '';
+
+    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultFonts = mkDefault true;
+    programs.dconf.enable = mkDefault true;
+  };
+
+  meta.maintainers = with maintainers; [ gnidorah ];
+}
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index eb10d4f428be..562be13a3f64 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -82,6 +82,10 @@ with lib;
     (mkRenamedOptionModule [ "services" "virtualboxHost" "addNetworkInterface" ] [ "virtualisation" "virtualbox" "host" "addNetworkInterface" ])
     (mkRenamedOptionModule [ "services" "virtualboxHost" "enableHardening" ] [ "virtualisation" "virtualbox" "host" "enableHardening" ])
 
+    # libvirtd
+    (mkRemovedOptionModule [ "virtualisation" "libvirtd" "enableKVM" ]
+      "Set the option `virtualisation.libvirtd.qemuPackage' instead.")
+
     # Tarsnap
     (mkRenamedOptionModule [ "services" "tarsnap" "config" ] [ "services" "tarsnap" "archives" ])
 
@@ -182,6 +186,9 @@ with lib;
     (mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "forceAutohint" ] [ "config" "fonts" "fontconfig" "forceAutohint" ])
     (mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ] [ "config" "fonts" "fontconfig" "renderMonoTTFAsBitmap" ])
 
+    # Profile splitting
+    (mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ])
+
     # Options that are obsolete and have no replacement.
     (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
     (mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 2d6713311a45..3fff9e78aa19 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -223,6 +223,17 @@ let
         '';
       };
 
+      enableGnomeKeyring = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          If enabled, pam_gnome_keyring will attempt to automatically unlock the
+          user's default Gnome keyring upon login. If the user login password does
+          not match their keyring password, Gnome Keyring will prompt separately
+          after login.
+        '';
+      };
+
       text = mkOption {
         type = types.nullOr types.lines;
         description = "Contents of the PAM service file.";
@@ -273,7 +284,7 @@ let
           # 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 || cfg.enableKwallet)) ''
+          (optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount || cfg.enableKwallet || cfg.enableGnomeKeyring)) ''
               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"}
@@ -282,6 +293,8 @@ let
               ${optionalString cfg.enableKwallet
                 ("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
                  " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
+              ${optionalString cfg.enableGnomeKeyring
+                ("auth optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so")}
             '') + ''
           ${optionalString cfg.unixAuth
               "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"}
@@ -351,6 +364,10 @@ let
           ${optionalString (cfg.enableKwallet)
               ("session optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" +
                " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")}
+          ${optionalString (cfg.enableGnomeKeyring)
+              "session optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start"}
+          ${optionalString (config.virtualisation.lxc.lxcfs.enable)
+               "session optional ${pkgs.lxcfs}/lib/security/pam_cgfs.so -c freezer,memory,name=systemd,unified,cpuset"}
         '');
     };
 
@@ -519,7 +536,6 @@ in
         ftp = {};
         i3lock = {};
         i3lock-color = {};
-        swaylock = {};
         screen = {};
         vlock = {};
         xlock = {};
diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix
index 1f64213accd4..77e4b2a616d8 100644
--- a/nixos/modules/security/wrappers/default.nix
+++ b/nixos/modules/security/wrappers/default.nix
@@ -17,7 +17,7 @@ let
     hardeningEnable = [ "pie" ];
     installPhase = ''
       mkdir -p $out/bin
-      gcc -Wall -O2 -DWRAPPER_DIR=\"${parentWrapperDir}\" \
+      $CC -Wall -O2 -DWRAPPER_DIR=\"${parentWrapperDir}\" \
           -lcap-ng -lcap ${./wrapper.c} -o $out/bin/security-wrapper
     '';
   };
@@ -79,7 +79,7 @@ let
                  ({ owner = "root";
                     group = "root";
                   } // s)
-          else if 
+          else if
              (s ? "setuid" && s.setuid) ||
              (s ? "setgid" && s.setgid) ||
              (s ? "permissions")
diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix
index c0a0f0374294..52613d450b51 100644
--- a/nixos/modules/services/audio/mopidy.nix
+++ b/nixos/modules/services/audio/mopidy.nix
@@ -4,17 +4,22 @@ with pkgs;
 with lib;
 
 let
-
   uid = config.ids.uids.mopidy;
   gid = config.ids.gids.mopidy;
   cfg = config.services.mopidy;
 
   mopidyConf = writeText "mopidy.conf" cfg.configuration;
 
-  mopidyEnv = python.buildEnv.override {
-    extraLibs = [ mopidy ] ++ cfg.extensionPackages;
+  mopidyEnv = buildEnv {
+    name = "mopidy-with-extensions-${mopidy.version}";
+    paths = closePropagation cfg.extensionPackages;
+    pathsToLink = [ "/${python.sitePackages}" ];
+    buildInputs = [ makeWrapper ];
+    postBuild = ''
+      makeWrapper ${mopidy}/bin/mopidy $out/bin/mopidy \
+        --prefix PYTHONPATH : $out/${python.sitePackages}
+    '';
   };
-
 in {
 
   options = {
@@ -61,7 +66,6 @@ in {
 
   };
 
-
   ###### implementation
 
   config = mkIf cfg.enable {
diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix
index 7c9dedb67ad2..59e9d122fb50 100644
--- a/nixos/modules/services/backup/tarsnap.nix
+++ b/nixos/modules/services/backup/tarsnap.nix
@@ -115,7 +115,7 @@ in
                 description = ''
                   Print global archive statistics upon completion.
                   The output is available via
-                  <command>systemctl status tarsnap@archive-name</command>.
+                  <command>systemctl status tarsnap-archive-name</command>.
                 '';
               };
 
diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix
index baf99930e3eb..762bb4b38675 100644
--- a/nixos/modules/services/backup/znapzend.nix
+++ b/nixos/modules/services/backup/znapzend.nix
@@ -1,39 +1,372 @@
 { config, lib, pkgs, ... }:
 
 with lib;
+with types;
 
 let
+
+  # Converts a plan like
+  #   { "1d" = "1h"; "1w" = "1d"; }
+  # into
+  #   "1d=>1h,1w=>1d"
+  attrToPlan = attrs: concatStringsSep "," (builtins.attrValues (
+    mapAttrs (n: v: "${n}=>${v}") attrs));
+
+  planDescription = ''
+      The znapzend backup plan to use for the source.
+    </para>
+    <para>
+      The plan specifies how often to backup and for how long to keep the
+      backups. It consists of a series of retention periodes to interval
+      associations:
+    </para>
+    <para>
+      <literal>
+        retA=>intA,retB=>intB,...
+      </literal>
+    </para>
+    <para>
+    Both intervals and retention periods are expressed in standard units
+    of time or multiples of them. You can use both the full name or a
+    shortcut according to the following listing:
+    </para>
+    <para>
+      <literal>
+        second|sec|s, minute|min, hour|h, day|d, week|w, month|mon|m, year|y
+      </literal>
+    </para>
+    <para>
+      See <citerefentry><refentrytitle>znapzendzetup</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more info.
+  '';
+  planExample = "1h=>10min,1d=>1h,1w=>1d,1m=>1w,1y=>1m";
+
+  # A type for a string of the form number{b|k|M|G}
+  mbufferSizeType = str // {
+    check = x: str.check x && builtins.isList (builtins.match "^[0-9]+[bkMG]$" x);
+    description = "string of the form number{b|k|M|G}";
+  };
+
+  # Type for a string that must contain certain other strings (the list parameter).
+  # Note that these would need regex escaping.
+  stringContainingStrings = list: let
+    matching = s: map (str: builtins.match ".*${str}.*" s) list;
+  in str // {
+    check = x: str.check x && all isList (matching x);
+    description = "string containing all of the characters ${concatStringsSep ", " list}";
+  };
+
+  timestampType = stringContainingStrings [ "%Y" "%m" "%d" "%H" "%M" "%S" ];
+
+  destType = srcConfig: submodule ({ name, ... }: {
+    options = {
+
+      label = mkOption {
+        type = str;
+        description = "Label for this destination. Defaults to the attribute name.";
+      };
+
+      plan = mkOption {
+        type = str;
+        description = planDescription;
+        example = planExample;
+      };
+
+      dataset = mkOption {
+        type = str;
+        description = "Dataset name to send snapshots to.";
+        example = "tank/main";
+      };
+
+      host = mkOption {
+        type = nullOr str;
+        description = ''
+          Host to use for the destination dataset. Can be prefixed with
+          <literal>user@</literal> to specify the ssh user.
+        '';
+        default = null;
+        example = "john@example.com";
+      };
+
+      presend = mkOption {
+        type = nullOr str;
+        description = ''
+          Command to run before sending the snapshot to the destination.
+          Intended to run a remote script via <command>ssh</command> on the
+          destination, e.g. to bring up a backup disk or server or to put a
+          zpool online/offline. See also <option>postsend</option>.
+        '';
+        default = null;
+        example = "ssh root@bserv zpool import -Nf tank";
+      };
+
+      postsend = mkOption {
+        type = nullOr str;
+        description = ''
+          Command to run after sending the snapshot to the destination.
+          Intended to run a remote script via <command>ssh</command> on the
+          destination, e.g. to bring up a backup disk or server or to put a
+          zpool online/offline. See also <option>presend</option>.
+        '';
+        default = null;
+        example = "ssh root@bserv zpool export tank";
+      };
+    };
+
+    config = {
+      label = mkDefault name;
+      plan = mkDefault srcConfig.plan;
+    };
+  });
+
+
+
+  srcType = submodule ({ name, config, ... }: {
+    options = {
+
+      enable = mkOption {
+        type = bool;
+        description = "Whether to enable this source.";
+        default = true;
+      };
+
+      recursive = mkOption {
+        type = bool;
+        description = "Whether to do recursive snapshots.";
+        default = false;
+      };
+
+      mbuffer = {
+        enable = mkOption {
+          type = bool;
+          description = "Whether to use <command>mbuffer</command>.";
+          default = false;
+        };
+
+        port = mkOption {
+          type = nullOr ints.u16;
+          description = ''
+              Port to use for <command>mbuffer</command>.
+            </para>
+            <para>
+              If this is null, it will run <command>mbuffer</command> through
+              ssh.
+            </para>
+            <para>
+              If this is not null, it will run <command>mbuffer</command>
+              directly through TCP, which is not encrypted but faster. In that
+              case the given port needs to be open on the destination host.
+          '';
+          default = null;
+        };
+
+        size = mkOption {
+          type = mbufferSizeType;
+          description = ''
+            The size for <command>mbuffer</command>.
+            Supports the units b, k, M, G.
+          '';
+          default = "1G";
+          example = "128M";
+        };
+      };
+
+      presnap = mkOption {
+        type = nullOr str;
+        description = ''
+          Command to run before snapshots are taken on the source dataset,
+          e.g. for database locking/flushing. See also
+          <option>postsnap</option>.
+        '';
+        default = null;
+        example = literalExample ''
+          ''${pkgs.mariadb}/bin/mysql -e "set autocommit=0;flush tables with read lock;\\! ''${pkgs.coreutils}/bin/sleep 600" &  ''${pkgs.coreutils}/bin/echo $! > /tmp/mariadblock.pid ; sleep 10
+        '';
+      };
+
+      postsnap = mkOption {
+        type = nullOr str;
+        description = ''
+          Command to run after snapshots are taken on the source dataset,
+          e.g. for database unlocking. See also <option>presnap</option>.
+        '';
+        default = null;
+        example = literalExample ''
+          ''${pkgs.coreutils}/bin/kill `''${pkgs.coreutils}/bin/cat /tmp/mariadblock.pid`;''${pkgs.coreutils}/bin/rm /tmp/mariadblock.pid
+        '';
+      };
+
+      timestampFormat = mkOption {
+        type = timestampType;
+        description = ''
+          The timestamp format to use for constructing snapshot names.
+          The syntax is <literal>strftime</literal>-like. The string must
+          consist of the mandatory <literal>%Y %m %d %H %M %S</literal>.
+          Optionally  <literal>- _ . :</literal>  characters as well as any
+          alphanumeric character are allowed. If suffixed by a
+          <literal>Z</literal>, times will be in UTC.
+        '';
+        default = "%Y-%m-%d-%H%M%S";
+        example = "znapzend-%m.%d.%Y-%H%M%SZ";
+      };
+
+      sendDelay = mkOption {
+        type = int;
+        description = ''
+          Specify delay (in seconds) before sending snaps to the destination.
+          May be useful if you want to control sending time.
+        '';
+        default = 0;
+        example = 60;
+      };
+
+      plan = mkOption {
+        type = str;
+        description = planDescription;
+        example = planExample;
+      };
+
+      dataset = mkOption {
+        type = str;
+        description = "The dataset to use for this source.";
+        example = "tank/home";
+      };
+
+      destinations = mkOption {
+        type = loaOf (destType config);
+        description = "Additional destinations.";
+        default = {};
+        example = literalExample ''
+          {
+            local = {
+              dataset = "btank/backup";
+              presend = "zpool import -N btank";
+              postsend = "zpool export btank";
+            };
+            remote = {
+              host = "john@example.com";
+              dataset = "tank/john";
+            };
+          };
+        '';
+      };
+    };
+
+    config = {
+      dataset = mkDefault name;
+    };
+
+  });
+
+  ### Generating the configuration from here
+
   cfg = config.services.znapzend;
+
+  onOff = b: if b then "on" else "off";
+  nullOff = b: if isNull b then "off" else toString b;
+  stripSlashes = replaceStrings [ "/" ] [ "." ];
+
+  attrsToFile = config: concatStringsSep "\n" (builtins.attrValues (
+    mapAttrs (n: v: "${n}=${v}") config));
+
+  mkDestAttrs = dst: with dst;
+    mapAttrs' (n: v: nameValuePair "dst_${label}${n}" v) ({
+      "" = optionalString (! isNull host) "${host}:" + dataset;
+      _plan = plan;
+    } // optionalAttrs (presend != null) {
+      _precmd = presend;
+    } // optionalAttrs (postsend != null) {
+      _pstcmd = postsend;
+    });
+
+  mkSrcAttrs = srcCfg: with srcCfg; {
+    enabled = onOff enable;
+    mbuffer = with mbuffer; if enable then "${pkgs.mbuffer}/bin/mbuffer"
+        + optionalString (port != null) ":${toString port}" else "off";
+    mbuffer_size = mbuffer.size;
+    post_znap_cmd = nullOff postsnap;
+    pre_znap_cmd = nullOff presnap;
+    recursive = onOff recursive;
+    src = dataset;
+    src_plan = plan;
+    tsformat = timestampFormat;
+    zend_delay = toString sendDelay;
+  } // fold (a: b: a // b) {} (
+    map mkDestAttrs (builtins.attrValues destinations)
+  );
+
+  files = mapAttrs' (n: srcCfg: let
+    fileText = attrsToFile (mkSrcAttrs srcCfg);
+  in {
+    name = srcCfg.dataset;
+    value = pkgs.writeText (stripSlashes srcCfg.dataset) fileText;
+  }) cfg.zetup;
+
 in
 {
   options = {
     services.znapzend = {
-      enable = mkEnableOption "ZnapZend daemon";
+      enable = mkEnableOption "ZnapZend ZFS backup daemon";
 
       logLevel = mkOption {
         default = "debug";
         example = "warning";
-        type = lib.types.enum ["debug" "info" "warning" "err" "alert"];
-        description = "The log level when logging to file. Any of debug, info, warning, err, alert. Default in daemonized form is debug.";
+        type = enum ["debug" "info" "warning" "err" "alert"];
+        description = ''
+          The log level when logging to file. Any of debug, info, warning, err,
+          alert. Default in daemonized form is debug.
+        '';
       };
 
       logTo = mkOption {
-        type = types.str;
+        type = str;
         default = "syslog::daemon";
         example = "/var/log/znapzend.log";
-        description = "Where to log to (syslog::&lt;facility&gt; or &lt;filepath&gt;).";
+        description = ''
+          Where to log to (syslog::&lt;facility&gt; or &lt;filepath&gt;).
+        '';
       };
 
       noDestroy = mkOption {
-        type = types.bool;
+        type = bool;
         default = false;
         description = "Does all changes to the filesystem except destroy.";
       };
 
       autoCreation = mkOption {
-        type = types.bool;
+        type = bool;
+        default = false;
+        description = "Automatically create the destination dataset if it does not exists.";
+      };
+
+      zetup = mkOption {
+        type = loaOf srcType;
+        description = "Znapzend configuration.";
+        default = {};
+        example = literalExample ''
+          {
+            "tank/home" = {
+              # Make snapshots of tank/home every hour, keep those for 1 day,
+              # keep every days snapshot for 1 month, etc.
+              plan = "1d=>1h,1m=>1d,1y=>1m";
+              recursive = true;
+              # Send all those snapshots to john@example.com:rtank/john as well
+              destinations.remote = {
+                host = "john@example.com";
+                dataset = "rtank/john";
+              };
+            };
+          };
+        '';
+      };
+
+      pure = mkOption {
+        type = bool;
+        description = ''
+          Do not persist any stateful znapzend setups. If this option is
+          enabled, your previously set znapzend setups will be cleared and only
+          the ones defined with this module will be applied.
+        '';
         default = false;
-        description = "Automatically create the dataset on dest if it does not exists.";
       };
     };
   };
@@ -49,12 +382,30 @@ in
 
         path = with pkgs; [ zfs mbuffer openssh ];
 
+        preStart = optionalString cfg.pure ''
+          echo Resetting znapzend zetups
+          ${pkgs.znapzend}/bin/znapzendzetup list \
+            | grep -oP '(?<=\*\*\* backup plan: ).*(?= \*\*\*)' \
+            | xargs ${pkgs.znapzend}/bin/znapzendzetup delete
+        '' + concatStringsSep "\n" (mapAttrsToList (dataset: config: ''
+          echo Importing znapzend zetup ${config} for dataset ${dataset}
+          ${pkgs.znapzend}/bin/znapzendzetup import --write ${dataset} ${config}
+        '') files);
+
         serviceConfig = {
-          ExecStart = "${pkgs.znapzend}/bin/znapzend --logto=${cfg.logTo} --loglevel=${cfg.logLevel} ${optionalString cfg.noDestroy "--nodestroy"} ${optionalString cfg.autoCreation "--autoCreation"}";
+          ExecStart = let
+            args = concatStringsSep " " [
+              "--logto=${cfg.logTo}"
+              "--loglevel=${cfg.logLevel}"
+              (optionalString cfg.noDestroy "--nodestroy")
+              (optionalString cfg.autoCreation "--autoCreation")
+            ]; in "${pkgs.znapzend}/bin/znapzend ${args}";
           ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
           Restart = "on-failure";
         };
       };
     };
   };
+
+  meta.maintainers = with maintainers; [ infinisil ];
 }
diff --git a/nixos/modules/services/continuous-integration/buildkite-agent.nix b/nixos/modules/services/continuous-integration/buildkite-agent.nix
index dcc5e7174601..1b0198ac93fe 100644
--- a/nixos/modules/services/continuous-integration/buildkite-agent.nix
+++ b/nixos/modules/services/continuous-integration/buildkite-agent.nix
@@ -48,6 +48,15 @@ in
         '';
       };
 
+      hooksPath = mkOption {
+        type = types.path;
+        default = "${pkgs.buildkite-agent}/share/hooks";
+        defaultText = "${pkgs.buildkite-agent}/share/hooks";
+        description = ''
+          Path to the directory storing the hooks.
+        '';
+      };
+
       meta-data = mkOption {
         type = types.str;
         default = "";
@@ -114,8 +123,8 @@ in
             token="$(cat ${toString cfg.tokenPath})"
             name="${cfg.name}"
             meta-data="${cfg.meta-data}"
-            hooks-path="${pkgs.buildkite-agent}/share/hooks"
             build-path="${cfg.dataDir}/builds"
+            hooks-path="${cfg.hooksPath}"
             bootstrap-script="${pkgs.buildkite-agent}/share/bootstrap.sh"
             EOF
           '';
diff --git a/nixos/modules/services/databases/memcached.nix b/nixos/modules/services/databases/memcached.nix
index c6875af506d3..46bc6fc5c132 100644
--- a/nixos/modules/services/databases/memcached.nix
+++ b/nixos/modules/services/databases/memcached.nix
@@ -40,11 +40,7 @@ in
         description = "The port to bind to";
       };
 
-      socket = mkOption {
-        default = "";
-        description = "Unix socket path to listen on. Setting this will disable network support";
-        example = "/var/run/memcached";
-      };
+      enableUnixSocket = mkEnableOption "unix socket at /run/memcached/memcached.sock";
 
       maxMemory = mkOption {
         default = 64;
@@ -68,31 +64,40 @@ in
 
   config = mkIf config.services.memcached.enable {
 
-    users.extraUsers.memcached =
-      { name = cfg.user;
-        uid = config.ids.uids.memcached;
-        description = "Memcached server user";
-      };
+    users.extraUsers = optional (cfg.user == "memcached") {
+      name = "memcached";
+      description = "Memcached server user";
+    };
 
     environment.systemPackages = [ memcached ];
 
-    systemd.services.memcached =
-      { description = "Memcached server";
-
-        wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" ];
-
-        serviceConfig = {
-          ExecStart =
-            let
-              networking = if cfg.socket != ""
-                then "-s ${cfg.socket}"
-                else "-l ${cfg.listen} -p ${toString cfg.port}";
-            in "${memcached}/bin/memcached ${networking} -m ${toString cfg.maxMemory} -c ${toString cfg.maxConnections} ${concatStringsSep " " cfg.extraOptions}";
-
-          User = cfg.user;
-        };
+    systemd.services.memcached = {
+      description = "Memcached server";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+
+      serviceConfig = {
+        PermissionsStartOnly = true;
+        ExecStartPre = optionals cfg.enableUnixSocket [
+          "${pkgs.coreutils}/bin/install -d -o ${cfg.user} /run/memcached/"
+          "${pkgs.coreutils}/bin/chown -R ${cfg.user} /run/memcached/"
+        ];
+        ExecStart =
+        let
+          networking = if cfg.enableUnixSocket
+          then "-s /run/memcached/memcached.sock"
+          else "-l ${cfg.listen} -p ${toString cfg.port}";
+        in "${memcached}/bin/memcached ${networking} -m ${toString cfg.maxMemory} -c ${toString cfg.maxConnections} ${concatStringsSep " " cfg.extraOptions}";
+
+        User = cfg.user;
       };
+    };
   };
+  imports = [
+    (mkRemovedOptionModule ["services" "memcached" "socket"] ''
+      This option was replaced by a fixed unix socket path at /run/memcached/memcached.sock enabled using services.memached.enableUnixSocket.
+    '')
+  ];
 
 }
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index a3bf4f9ba925..36d5340a306f 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -7,14 +7,12 @@ let
   cfg = config.services.mysql;
 
   mysql = cfg.package;
-  
-  isMariaDB = 
+
+  isMariaDB =
     let
       pName = _p: (builtins.parseDrvName (_p.name)).name;
     in pName mysql == pName pkgs.mariadb;
 
-  atLeast55 = versionAtLeast mysql.mysqlVersion "5.5";
-
   pidFile = "${cfg.pidDir}/mysqld.pid";
 
   mysqldOptions =
@@ -28,13 +26,6 @@ let
     ${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" }
     ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "log-bin=mysql-bin"}
     ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "server-id = ${toString cfg.replication.serverId}"}
-    ${optionalString (cfg.replication.role == "slave" && !atLeast55)
-    ''
-      master-host = ${cfg.replication.masterHost}
-      master-user = ${cfg.replication.masterUser}
-      master-password = ${cfg.replication.masterPassword}
-      master-port = ${toString cfg.replication.masterPort}
-    ''}
     ${optionalString (cfg.ensureUsers != [])
     ''
       plugin-load-add = auth_socket.so
@@ -315,7 +306,7 @@ in
                     fi
                   '') cfg.initialDatabases}
 
-                ${optionalString (cfg.replication.role == "master" && atLeast55)
+                ${optionalString (cfg.replication.role == "master")
                   ''
                     # Set up the replication master
 
@@ -326,7 +317,7 @@ in
                     ) | ${mysql}/bin/mysql -u root -N
                   ''}
 
-                ${optionalString (cfg.replication.role == "slave" && atLeast55)
+                ${optionalString (cfg.replication.role == "slave")
                   ''
                     # Set up the replication slave
 
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index a039ad138f6f..e4e38a4364a0 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -219,7 +219,6 @@ in
 
     users.extraUsers.redis =
       { name = cfg.user;
-        uid = config.ids.uids.redis;
         description = "Redis database user";
       };
 
diff --git a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix
index 55ed2d9ee21b..9e382241348b 100644
--- a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix
+++ b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix
@@ -28,14 +28,15 @@ with lib;
 
   ###### implementation
 
-  config = mkIf config.services.gnome3.at-spi2-core.enable {
-
-    environment.systemPackages = [ pkgs.at_spi2_core ];
-
-    services.dbus.packages = [ pkgs.at_spi2_core ];
-
-    systemd.packages = [ pkgs.at_spi2_core ];
-
-  };
-
+  config = mkMerge [
+    (mkIf config.services.gnome3.at-spi2-core.enable {
+      environment.systemPackages = [ pkgs.at_spi2_core ];
+      services.dbus.packages = [ pkgs.at_spi2_core ];
+      systemd.packages = [ pkgs.at_spi2_core ];
+    })
+
+    (mkIf (!config.services.gnome3.at-spi2-core.enable) {
+      environment.variables.NO_AT_BRIDGE = "1";
+    })
+  ];
 }
diff --git a/nixos/modules/services/games/ghost-one.nix b/nixos/modules/services/games/ghost-one.nix
deleted file mode 100644
index 71ff6bb2f3f0..000000000000
--- a/nixos/modules/services/games/ghost-one.nix
+++ /dev/null
@@ -1,105 +0,0 @@
-{ config, lib, pkgs, ... }:
-with lib;
-let
-
-  cfg = config.services.ghostOne;
-  ghostUser = "ghostone";
-  stateDir = "/var/lib/ghost-one";
-
-in
-{
-
-  ###### interface
-
-  options = {
-    services.ghostOne = {
-
-      enable = mkOption {
-        default = false;
-        description = "Enable Ghost-One Warcraft3 game hosting server.";
-      };
-
-      language = mkOption {
-        default = "English";
-        type = types.enum [ "English" "Spanish" "Russian" "Serbian" "Turkish" ];
-        description = "The language of bot messages: English, Spanish, Russian, Serbian or Turkish.";
-      };
-
-      war3path = mkOption {
-        default = "";
-        description = ''
-          The path to your local Warcraft III directory, which must contain war3.exe, storm.dll, and game.dll.
-        '';
-      };
-
-      mappath = mkOption {
-        default = "";
-        description = ''
-          The path to the directory where you keep your map files. GHost One doesn't require
-          map files but if it has access to them it can send them to players and automatically
-          calculate most map config values. GHost One will search [bot_mappath + map_localpath]
-          for the map file (map_localpath is set in each map's config file).
-        '';
-      };
-
-      config = mkOption {
-        default = "";
-        description = "Extra configuration options.";
-      };
-
-    };
-  };
-
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    users.extraUsers = singleton
-      { name = ghostUser;
-        uid = config.ids.uids.ghostone;
-        description = "Ghost One game server user";
-        home = stateDir;
-      };
-
-    users.extraGroups = singleton
-      { name = ghostUser;
-        gid = config.ids.gids.ghostone;
-      };
-
-    services.ghostOne.config = ''
-#      bot_log = /dev/stderr
-      bot_language = ${pkgs.ghostOne}/share/ghost-one/languages/${cfg.language}.cfg
-      bot_war3path = ${cfg.war3path}
-
-      bot_mapcfgpath = mapcfgs
-      bot_savegamepath = savegames
-      bot_mappath = ${cfg.mappath}
-      bot_replaypath = replays
-    '';
-
-    systemd.services."ghost-one" = {
-      wantedBy = [ "multi-user.target" ];
-      script = ''
-        mkdir -p ${stateDir}
-        cd ${stateDir}
-        chown ${ghostUser}:${ghostUser} .
-
-        mkdir -p mapcfgs
-        chown ${ghostUser}:${ghostUser} mapcfgs
-
-        mkdir -p replays
-        chown ${ghostUser}:${ghostUser} replays
-
-        mkdir -p savegames
-        chown ${ghostUser}:${ghostUser} savegames
-
-        ln -sf ${pkgs.writeText "ghost.cfg" cfg.config} ghost.cfg
-        ln -sf ${pkgs.ghostOne}/share/ghost-one/ip-to-country.csv
-        ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${ghostUser} \
-          -c "LANG=C ${pkgs.ghostOne}/bin/ghost++"
-      '';
-    };
-
-  };
-
-}
diff --git a/nixos/modules/services/hardware/80-net-setup-link.rules b/nixos/modules/services/hardware/80-net-setup-link.rules
deleted file mode 100644
index 18547f170a3f..000000000000
--- a/nixos/modules/services/hardware/80-net-setup-link.rules
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copied from systemd 203.
-ACTION=="remove", GOTO="net_name_slot_end"
-SUBSYSTEM!="net", GOTO="net_name_slot_end"
-NAME!="", GOTO="net_name_slot_end"
-
-IMPORT{cmdline}="net.ifnames"
-ENV{net.ifnames}=="0", GOTO="net_name_slot_end"
-
-NAME=="", ENV{ID_NET_NAME_ONBOARD}!="", NAME="$env{ID_NET_NAME_ONBOARD}"
-NAME=="", ENV{ID_NET_NAME_SLOT}!="", NAME="$env{ID_NET_NAME_SLOT}"
-NAME=="", ENV{ID_NET_NAME_PATH}!="", NAME="$env{ID_NET_NAME_PATH}"
-
-LABEL="net_name_slot_end"
diff --git a/nixos/modules/services/hardware/thinkfan.nix b/nixos/modules/services/hardware/thinkfan.nix
index 018e82e58a3d..5a898631e090 100644
--- a/nixos/modules/services/hardware/thinkfan.nix
+++ b/nixos/modules/services/hardware/thinkfan.nix
@@ -55,7 +55,7 @@ in {
       enable = mkOption {
         default = false;
         description = ''
-          Whether to enable thinkfan, fan controller for ibm/lenovo thinkpads.
+          Whether to enable thinkfan, fan controller for IBM/Lenovo ThinkPads.
         '';
       };
 
diff --git a/nixos/modules/services/hardware/u2f.nix b/nixos/modules/services/hardware/u2f.nix
new file mode 100644
index 000000000000..bb4b2f05f890
--- /dev/null
+++ b/nixos/modules/services/hardware/u2f.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.hardware.u2f;
+in {
+  options = {
+    hardware.u2f = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable U2F hardware support.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.udev.packages = [ pkgs.libu2f-host ];
+  };
+}
+
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index 9f42f9e59ad5..730e538e72f6 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -119,7 +119,7 @@ let
       fi
 
       ${optionalString config.networking.usePredictableInterfaceNames ''
-        cp ${./80-net-setup-link.rules} $out/80-net-setup-link.rules
+        cp ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/80-net-setup-link.rules
       ''}
 
       # If auto-configuration is disabled, then remove
diff --git a/nixos/modules/services/hardware/usbmuxd.nix b/nixos/modules/services/hardware/usbmuxd.nix
new file mode 100644
index 000000000000..7ebd49fa01c2
--- /dev/null
+++ b/nixos/modules/services/hardware/usbmuxd.nix
@@ -0,0 +1,74 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  defaultUserGroup = "usbmux";
+  apple = "05ac";
+
+  cfg = config.services.usbmuxd;
+
+in
+
+{
+  options.services.usbmuxd = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable the usbmuxd ("USB multiplexing daemon") service. This daemon is
+        in charge of multiplexing connections over USB to an iOS device. This is
+        needed for transferring data from and to iOS devices (see ifuse). Also
+        this may enable plug-n-play tethering for iPhones.
+      '';
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = defaultUserGroup;
+      description = ''
+        The user usbmuxd should use to run after startup.
+      '';
+    };
+
+    group = mkOption {
+      type = types.str;
+      default = defaultUserGroup;
+      description = ''
+        The group usbmuxd should use to run after startup.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = optional (cfg.user == defaultUserGroup) {
+      name = cfg.user;
+      description = "usbmuxd user";
+      group = cfg.group;
+    };
+
+    users.extraGroups = optional (cfg.group == defaultUserGroup) {
+      name = cfg.group;
+    };
+
+    # Give usbmuxd permission for Apple devices
+    services.udev.extraRules = ''
+      SUBSYSTEM=="usb", ATTR{idVendor}=="${apple}", GROUP="${cfg.group}"
+    '';
+
+    systemd.services.usbmuxd = {
+      description = "usbmuxd";
+      wantedBy = [ "multi-user.target" ];
+      unitConfig.Documentation = "man:usbmuxd(8)";
+      serviceConfig = {
+        # Trigger the udev rule manually. This doesn't require replugging the
+        # device when first enabling the option to get it to work
+        ExecStartPre = "${pkgs.libudev}/bin/udevadm trigger -s usb -a idVendor=${apple}";
+        ExecStart = "${pkgs.usbmuxd}/bin/usbmuxd -U ${cfg.user} -f";
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/logging/logcheck.nix b/nixos/modules/services/logging/logcheck.nix
index 2a8ac414720b..a4cab0c94cdc 100644
--- a/nixos/modules/services/logging/logcheck.nix
+++ b/nixos/modules/services/logging/logcheck.nix
@@ -8,7 +8,7 @@ let
   defaultRules = pkgs.runCommand "logcheck-default-rules" {} ''
                    cp -prd ${pkgs.logcheck}/etc/logcheck $out
                    chmod u+w $out
-                   rm $out/logcheck.*
+                   rm -r $out/logcheck.*
                  '';
 
   rulesDir = pkgs.symlinkJoin
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index b4abd2cd7e5e..28d89a7463ab 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -103,7 +103,7 @@ in
 
       listenAddress = mkOption {
         type = types.str;
-        default = "0.0.0.0";
+        default = "127.0.0.1";
         description = "Address on which to start webserver.";
       };
 
diff --git a/nixos/modules/services/mail/clamsmtp.nix b/nixos/modules/services/mail/clamsmtp.nix
new file mode 100644
index 000000000000..8f4f39aa7288
--- /dev/null
+++ b/nixos/modules/services/mail/clamsmtp.nix
@@ -0,0 +1,179 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.clamsmtp;
+  clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix
+in
+{
+  ##### interface
+  options = {
+    services.clamsmtp = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable clamsmtp.";
+      };
+
+      instances = mkOption {
+        description = "Instances of clamsmtp to run.";
+        type = types.listOf (types.submodule { options = {
+          action = mkOption {
+            type = types.enum [ "bounce" "drop" "pass" ];
+            default = "drop";
+            description =
+              ''
+                Action to take when a virus is detected.
+
+                Note that viruses often spoof sender addresses, so bouncing is
+                in most cases not a good idea.
+              '';
+          };
+
+          header = mkOption {
+            type = types.str;
+            default = "";
+            example = "X-Virus-Scanned: ClamAV using ClamSMTP";
+            description =
+              ''
+                A header to add to scanned messages. See clamsmtpd.conf(5) for
+                more details. Empty means no header.
+              '';
+          };
+
+          keepAlives = mkOption {
+            type = types.int;
+            default = 0;
+            description =
+              ''
+                Number of seconds to wait between each NOOP sent to the sending
+                server. 0 to disable.
+
+                This is meant for slow servers where the sending MTA times out
+                waiting for clamd to scan the file.
+              '';
+          };
+
+          listen = mkOption {
+            type = types.str;
+            example = "127.0.0.1:10025";
+            description =
+              ''
+                Address to wait for incoming SMTP connections on. See
+                clamsmtpd.conf(5) for more details.
+              '';
+          };
+
+          quarantine = mkOption {
+            type = types.bool;
+            default = false;
+            description =
+              ''
+                Whether to quarantine files that contain viruses by leaving them
+                in the temporary directory.
+              '';
+          };
+
+          maxConnections = mkOption {
+            type = types.int;
+            default = 64;
+            description = "Maximum number of connections to accept at once.";
+          };
+
+          outAddress = mkOption {
+            type = types.str;
+            description =
+              ''
+                Address of the SMTP server to send email to once it has been
+                scanned.
+              '';
+          };
+
+          tempDirectory = mkOption {
+            type = types.str;
+            default = "/tmp";
+            description =
+              ''
+                Temporary directory that needs to be accessible to both clamd
+                and clamsmtpd.
+              '';
+          };
+
+          timeout = mkOption {
+            type = types.int;
+            default = 180;
+            description = "Time-out for network connections.";
+          };
+
+          transparentProxy = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Enable clamsmtp's transparent proxy support.";
+          };
+
+          virusAction = mkOption {
+            type = with types; nullOr path;
+            default = null;
+            description =
+              ''
+                Command to run when a virus is found. Please see VIRUS ACTION in
+                clamsmtpd(8) for a discussion of this option and its safe use.
+              '';
+          };
+
+          xClient = mkOption {
+            type = types.bool;
+            default = false;
+            description =
+              ''
+                Send the XCLIENT command to the receiving server, for forwarding
+                client addresses and connection information if the receiving
+                server supports this feature.
+              '';
+          };
+        };});
+      };
+    };
+  };
+
+  ##### implementation
+  config = let
+    configfile = conf: pkgs.writeText "clamsmtpd.conf"
+      ''
+        Action: ${conf.action}
+        ClamAddress: ${clamdSocket}
+        Header: ${conf.header}
+        KeepAlives: ${toString conf.keepAlives}
+        Listen: ${conf.listen}
+        Quarantine: ${if conf.quarantine then "on" else "off"}
+        MaxConnections: ${toString conf.maxConnections}
+        OutAddress: ${conf.outAddress}
+        TempDirectory: ${conf.tempDirectory}
+        TimeOut: ${toString conf.timeout}
+        TransparentProxy: ${if conf.transparentProxy then "on" else "off"}
+        User: clamav
+        ${optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"}
+        XClient: ${if conf.xClient then "on" else "off"}
+      '';
+  in
+    mkIf cfg.enable {
+      assertions = [
+        { assertion = config.services.clamav.daemon.enable;
+          message = "clamsmtp requires clamav to be enabled";
+        }
+      ];
+
+      systemd.services = listToAttrs (imap1 (i: conf:
+        nameValuePair "clamsmtp-${toString i}" {
+          description = "ClamSMTP instance ${toString i}";
+          wantedBy = [ "multi-user.target" ];
+          script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}";
+          after = [ "clamav-daemon.service" ];
+          requires = [ "clamav-daemon.service" ];
+          serviceConfig.Type = "forking";
+          serviceConfig.PrivateTmp = "yes";
+          unitConfig.JoinsNamespaceOf = "clamav-daemon.service";
+        }
+      ) cfg.instances);
+    };
+}
diff --git a/nixos/modules/services/mail/dkimproxy-out.nix b/nixos/modules/services/mail/dkimproxy-out.nix
new file mode 100644
index 000000000000..894b88e25c1b
--- /dev/null
+++ b/nixos/modules/services/mail/dkimproxy-out.nix
@@ -0,0 +1,118 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.dkimproxy-out;
+  keydir = "/var/lib/dkimproxy-out";
+  privkey = "${keydir}/private.key";
+  pubkey = "${keydir}/public.key";
+in
+{
+  ##### interface
+  options = {
+    services.dkimproxy-out = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            Whether to enable dkimproxy_out.
+
+            Note that a key will be auto-generated, and can be found in
+            ${keydir}.
+          '';
+      };
+
+      listen = mkOption {
+        type = types.str;
+        example = "127.0.0.1:10027";
+        description = "Address:port DKIMproxy should listen on.";
+      };
+
+      relay = mkOption {
+        type = types.str;
+        example = "127.0.0.1:10028";
+        description = "Address:port DKIMproxy should forward mail to.";
+      };
+
+      domains = mkOption {
+        type = with types; listOf str;
+        example = [ "example.org" "example.com" ];
+        description = "List of domains DKIMproxy can sign for.";
+      };
+
+      selector = mkOption {
+        type = types.str;
+        example = "selector1";
+        description =
+          ''
+            The selector to use for DKIM key identification.
+
+            For example, if 'selector1' is used here, then for each domain
+            'example.org' given in `domain`, 'selector1._domainkey.example.org'
+            should contain the TXT record indicating the public key is the one
+            in ${pubkey}: "v=DKIM1; t=s; p=[THE PUBLIC KEY]".
+          '';
+      };
+
+      keySize = mkOption {
+        type = types.int;
+        default = 2048;
+        description =
+          ''
+            Size of the RSA key to use to sign outgoing emails. Note that the
+            maximum mandatorily verified as per RFC6376 is 2048.
+          '';
+      };
+
+      # TODO: allow signature for other schemes than dkim(c=relaxed/relaxed)?
+      # This being the scheme used by gmail, maybe nothing more is needed for
+      # reasonable use.
+    };
+  };
+
+  ##### implementation
+  config = let
+    configfile = pkgs.writeText "dkimproxy_out.conf"
+      ''
+        listen ${cfg.listen}
+        relay ${cfg.relay}
+
+        domain ${concatStringsSep "," cfg.domains}
+        selector ${cfg.selector}
+
+        signature dkim(c=relaxed/relaxed)
+
+        keyfile ${privkey}
+      '';
+  in
+    mkIf cfg.enable {
+      users.groups.dkimproxy-out = {};
+      users.users.dkimproxy-out = {
+        description = "DKIMproxy_out daemon";
+        group = "dkimproxy-out";
+        isSystemUser = true;
+      };
+
+      systemd.services.dkimproxy-out = {
+        description = "DKIMproxy_out";
+        wantedBy = [ "multi-user.target" ];
+        preStart = ''
+          if [ ! -d "${keydir}" ]; then
+            mkdir -p "${keydir}"
+            chmod 0700 "${keydir}"
+            ${pkgs.openssl}/bin/openssl genrsa -out "${privkey}" ${toString cfg.keySize}
+            ${pkgs.openssl}/bin/openssl rsa -in "${privkey}" -pubout -out "${pubkey}"
+            chown -R dkimproxy-out:dkimproxy-out "${keydir}"
+          fi
+        '';
+        script = ''
+          exec ${pkgs.dkimproxy}/bin/dkimproxy.out --conf_file=${configfile}
+        '';
+        serviceConfig = {
+          User = "dkimproxy-out";
+          PermissionsStartOnly = true;
+        };
+      };
+    };
+}
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
index 6d403e448e04..b80aa48f2c86 100644
--- a/nixos/modules/services/mail/rspamd.nix
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -31,6 +31,8 @@ let
       ${mkBindSockets cfg.bindUISocket}
         .include "$CONFDIR/worker-controller.inc"
       }
+
+      ${cfg.extraConfig}
    '';
 
 in
@@ -79,6 +81,15 @@ in
         '';
       };
 
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration to add at the end of the rspamd configuration
+          file.
+        '';
+      };
+
       user = mkOption {
         type = types.string;
         default = "rspamd";
diff --git a/nixos/modules/services/misc/dysnomia.nix b/nixos/modules/services/misc/dysnomia.nix
index df44d0a54866..c5c41ad296da 100644
--- a/nixos/modules/services/misc/dysnomia.nix
+++ b/nixos/modules/services/misc/dysnomia.nix
@@ -192,9 +192,11 @@ in
         mysqlPassword = builtins.readFile (config.services.mysql.rootPassword);
       };
     }
-    // lib.optionalAttrs (config.services.postgresql.enable && cfg.enableAuthentication) { postgresql-database = {
-      postgresqlUsername = "root";
-    }; }
+    // lib.optionalAttrs (config.services.postgresql.enable) { postgresql-database = {
+      } // lib.optionalAttrs (cfg.enableAuthentication) {
+        postgresqlUsername = "postgres";
+      };
+    }
     // lib.optionalAttrs (config.services.tomcat.enable) { tomcat-webapplication = {
       tomcatPort = 8080;
     }; }
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index 7b2b40e59232..9ed5875a0191 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -29,8 +29,12 @@ let
 
   gitalyToml = pkgs.writeText "gitaly.toml" ''
     socket_path = "${lib.escape ["\""] gitalySocket}"
+    bin_dir = "${cfg.packages.gitaly}/bin"
     prometheus_listen_addr = "localhost:9236"
 
+    [git]
+    bin_path = "${pkgs.git}/bin/git"
+
     [gitaly-ruby]
     dir = "${cfg.packages.gitaly.ruby}"
 
@@ -70,7 +74,7 @@ let
       secret_key_base: ${cfg.secrets.secret}
       otp_key_base: ${cfg.secrets.otp}
       db_key_base: ${cfg.secrets.db}
-      jws_private_key: ${builtins.toJSON cfg.secrets.jws}
+      openid_connect_signing_key: ${builtins.toJSON cfg.secrets.jws}
   '';
 
   gitlabConfig = {
@@ -104,6 +108,7 @@ let
       ldap.enabled = false;
       omniauth.enabled = false;
       shared.path = "${cfg.statePath}/shared";
+      gitaly.client_path = "${cfg.packages.gitaly}/bin";
       backup.path = "${cfg.backupPath}";
       gitlab_shell = {
         path = "${cfg.packages.gitlab-shell}";
@@ -117,8 +122,6 @@ let
       };
       git = {
         bin_path = "git";
-        max_size = 20971520; # 20MB
-        timeout = 10;
       };
       monitoring = {
         ip_whitelist = [ "127.0.0.0/8" "::1/128" ];
@@ -248,7 +251,6 @@ in {
 
       databasePassword = mkOption {
         type = types.str;
-        default = "";
         description = "Gitlab database user password.";
       };
 
@@ -440,12 +442,6 @@ in {
 
     environment.systemPackages = [ pkgs.git gitlab-rake cfg.packages.gitlab-shell ];
 
-    assertions = [
-      { assertion = cfg.databasePassword != "";
-        message = "databasePassword must be set";
-      }
-    ];
-
     # Redis is required for the sidekiq queue runner.
     services.redis.enable = mkDefault true;
     # We use postgres as the main data store.
@@ -496,7 +492,9 @@ in {
       after = [ "network.target" "gitlab.service" ];
       wantedBy = [ "multi-user.target" ];
       environment.HOME = gitlabEnv.HOME;
-      path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv ];
+      environment.GEM_HOME = "${cfg.packages.gitaly.rubyEnv}/${ruby.gemPath}";
+      environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH;
+      path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv ruby ];
       serviceConfig = {
         #PermissionsStartOnly = true; # preStart must be run as root
         Type = "simple";
diff --git a/nixos/modules/services/misc/gitolite.nix b/nixos/modules/services/misc/gitolite.nix
index f395b9558b5a..6e60316d000c 100644
--- a/nixos/modules/services/misc/gitolite.nix
+++ b/nixos/modules/services/misc/gitolite.nix
@@ -207,7 +207,7 @@ in
             gitolite setup -pk ${pubkeyFile}
           fi
           if [ -n "${hooks}" ]; then
-            cp ${hooks} .gitolite/hooks/common/
+            cp -f ${hooks} .gitolite/hooks/common/
             chmod +x .gitolite/hooks/common/*
           fi
           gitolite setup # Upgrade if needed
diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix
index 81fb024f9094..0888221ab62f 100644
--- a/nixos/modules/services/misc/gollum.nix
+++ b/nixos/modules/services/misc/gollum.nix
@@ -32,6 +32,24 @@ in
       description = "Content of the configuration file";
     };
 
+    mathjax = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Enable support for math rendering using MathJax";
+    };
+
+    allowUploads = mkOption {
+      type = types.nullOr (types.enum [ "dir" "page" ]);
+      default = null;
+      description = "Enable uploads of external files";
+    };
+
+    emoji = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Parse and interpret emoji tags";
+    };
+
     branch = mkOption {
       type = types.str;
       default = "master";
@@ -84,6 +102,9 @@ in
             --host ${cfg.address} \
             --config ${builtins.toFile "gollum-config.rb" cfg.extraConfig} \
             --ref ${cfg.branch} \
+            ${optionalString cfg.mathjax "--mathjax"} \
+            ${optionalString cfg.emoji "--emoji"} \
+            ${optionalString (cfg.allowUploads != null) "--allow-uploads ${cfg.allowUploads}"} \
             ${cfg.stateDir}
         '';
       };
diff --git a/nixos/modules/services/misc/logkeys.nix b/nixos/modules/services/misc/logkeys.nix
index 6051c884465d..df0b3ae24c90 100644
--- a/nixos/modules/services/misc/logkeys.nix
+++ b/nixos/modules/services/misc/logkeys.nix
@@ -1,4 +1,4 @@
-{ config, lib, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 11463cf4500a..80979547d339 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -578,6 +578,18 @@ in {
           Extra config options for matrix-synapse.
         '';
       };
+      extraConfigFiles = mkOption {
+        type = types.listOf types.path;
+        default = [];
+        description = ''
+          Extra config files to include.
+
+          The configuration files will be included based on the command line
+          argument --config-path. This allows to configure secrets without
+          having to go through the Nix store, e.g. based on deployment keys if
+          NixOPS is in use.
+        '';
+      };
       logConfig = mkOption {
         type = types.lines;
         default = readFile ./matrix-synapse-log_config.yaml;
@@ -627,7 +639,11 @@ in {
         Group = "matrix-synapse";
         WorkingDirectory = cfg.dataDir;
         PermissionsStartOnly = true;
-        ExecStart = "${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory ${cfg.dataDir}";
+        ExecStart = ''
+          ${cfg.package}/bin/homeserver \
+            ${ concatMapStringsSep "\n  " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) }
+            --keys-directory ${cfg.dataDir}
+        '';
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/misc/mbpfan.nix b/nixos/modules/services/misc/mbpfan.nix
index 972d8b572d36..50f6f80ad00c 100644
--- a/nixos/modules/services/misc/mbpfan.nix
+++ b/nixos/modules/services/misc/mbpfan.nix
@@ -8,13 +8,7 @@ let
 
 in {
   options.services.mbpfan = {
-    enable = mkOption {
-      default = false;
-      type = types.bool;
-      description = ''
-        Whether to enable the mbpfan daemon.
-      '';
-    };
+    enable = mkEnableOption "mbpfan, fan controller daemon for Apple Macs and MacBooks";
 
     package = mkOption {
       type = types.package;
diff --git a/nixos/modules/services/misc/osrm.nix b/nixos/modules/services/misc/osrm.nix
new file mode 100644
index 000000000000..7ec8b15906fc
--- /dev/null
+++ b/nixos/modules/services/misc/osrm.nix
@@ -0,0 +1,85 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.osrm;
+in
+
+{
+  options.services.osrm = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Enable the OSRM service.";
+    };
+
+    address = mkOption {
+      type = types.str;
+      default = "0.0.0.0";
+      description = "IP address on which the web server will listen.";
+    };
+
+    port = mkOption {
+      type = types.int;
+      default = 5000;
+      description = "Port on which the web server will run.";
+    };
+
+    threads = mkOption {
+      type = types.int;
+      default = 4;
+      description = "Number of threads to use.";
+    };
+
+    algorithm = mkOption {
+      type = types.enum [ "CH" "CoreCH" "MLD" ];
+      default = "MLD";
+      description = "Algorithm to use for the data. Must be one of CH, CoreCH, MLD";
+    };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "--max-table-size 1000" "--max-matching-size 1000" ];
+      description = "Extra command line arguments passed to osrm-routed";
+    };
+
+    dataFile = mkOption {
+      type = types.path;
+      example = "/var/lib/osrm/berlin-latest.osrm";
+      description = "Data file location";
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    users.users.osrm = {
+      group = config.users.users.osrm.name;
+      description = "OSRM user";
+      createHome = false;
+    };
+
+    users.groups.osrm = { };
+
+    systemd.services.osrm = {
+      description = "OSRM service";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        User = config.users.extraUsers.osrm.name;
+        ExecStart = ''
+          ${pkgs.osrm-backend}/bin/osrm-routed \
+            --ip ${cfg.address} \
+            --port ${toString cfg.port} \
+            --threads ${toString cfg.threads} \
+            --algorithm ${cfg.algorithm} \
+            ${toString cfg.extraFlags} \
+            ${cfg.dataFile}
+        '';
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/xmr-stak.nix b/nixos/modules/services/misc/xmr-stak.nix
new file mode 100644
index 000000000000..57f439365471
--- /dev/null
+++ b/nixos/modules/services/misc/xmr-stak.nix
@@ -0,0 +1,73 @@
+{ lib, config, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.xmr-stak;
+
+  pkg = pkgs.xmr-stak.override {
+    inherit (cfg) openclSupport cudaSupport;
+  };
+
+  xmrConfArg = optionalString (cfg.configText != "") ("-c " +
+    pkgs.writeText "xmr-stak-config.txt" cfg.configText);
+
+in
+
+{
+  options = {
+    services.xmr-stak = {
+      enable = mkEnableOption "xmr-stak miner";
+      openclSupport = mkEnableOption "support for OpenCL (AMD/ATI graphics cards)";
+      cudaSupport = mkEnableOption "support for CUDA (NVidia graphics cards)";
+
+      extraArgs = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        example = [ "--noCPU" "--currency monero" ];
+        description = "List of parameters to pass to xmr-stak.";
+      };
+
+      configText = mkOption {
+        type = types.lines;
+        default = "";
+        example = ''
+          "currency" : "monero",
+          "pool_list" :
+            [ { "pool_address" : "pool.supportxmr.com:5555",
+                "wallet_address" : "<long-hash>",
+                "pool_password" : "minername",
+                "pool_weight" : 1,
+              },
+            ],
+        '';
+        description = ''
+          Verbatim xmr-stak config.txt. If empty, the <literal>-c</literal>
+          parameter will not be added to the xmr-stak command.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.xmr-stak = {
+      wantedBy = [ "multi-user.target" ];
+      bindsTo = [ "network-online.target" ];
+      after = [ "network-online.target" ];
+      environment = mkIf cfg.cudaSupport {
+        LD_LIBRARY_PATH = "${pkgs.linuxPackages_latest.nvidia_x11}/lib";
+      };
+      script = ''
+        exec ${pkg}/bin/xmr-stak ${xmrConfArg} ${concatStringsSep " " cfg.extraArgs}
+      '';
+      serviceConfig = let rootRequired = cfg.openclSupport || cfg.cudaSupport; in {
+        # xmr-stak generates cpu and/or gpu configuration files
+        WorkingDirectory = "/tmp";
+        PrivateTmp = true;
+        DynamicUser = !rootRequired;
+        LimitMEMLOCK = toString (1024*1024);
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix
index 1d6940c516a9..b8d9e58a5a82 100644
--- a/nixos/modules/services/monitoring/smartd.nix
+++ b/nixos/modules/services/monitoring/smartd.nix
@@ -64,7 +64,7 @@ let
        "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"}
   '';
 
-  smartdOpts = { name, ... }: {
+  smartdDeviceOpts = { name, ... }: {
 
     options = {
 
@@ -108,6 +108,18 @@ in
         '';
       };
 
+      extraOptions = mkOption {
+        default = [];
+        type = types.listOf types.str;
+        example = ["-A /var/log/smartd/" "--interval=3600"];
+        description = ''
+          Extra command-line options passed to the <literal>smartd</literal>
+          daemon on startup.
+
+          (See <literal>man 8 smartd</literal>.)
+        '';
+      };
+
       notifications = {
 
         mail = {
@@ -197,7 +209,7 @@ in
       devices = mkOption {
         default = [];
         example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ];
-        type = with types; listOf (submodule smartdOpts);
+        type = with types; listOf (submodule smartdDeviceOpts);
         description = "List of devices to monitor.";
       };
 
@@ -222,7 +234,7 @@ in
 
       path = [ pkgs.nettools ]; # for hostname and dnsdomanname calls in smartd
 
-      serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork --configfile=${smartdConf}";
+      serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}";
     };
 
   };
diff --git a/nixos/modules/services/monitoring/statsd.nix b/nixos/modules/services/monitoring/statsd.nix
index df2adb9f2766..7b0e9981cbb1 100644
--- a/nixos/modules/services/monitoring/statsd.nix
+++ b/nixos/modules/services/monitoring/statsd.nix
@@ -9,6 +9,12 @@ let
   isBuiltinBackend = name:
     builtins.elem name [ "graphite" "console" "repeater" ];
 
+  backendsToPackages = let
+    mkMap = list: name:
+      if isBuiltinBackend name then list
+      else list ++ [ pkgs.nodePackages.${name} ];
+  in foldl mkMap [];
+
   configFile = pkgs.writeText "statsd.conf" ''
     {
       address: "${cfg.listenAddress}",
@@ -27,13 +33,21 @@ let
         prettyprint: false
       },
       log: {
-        backend: "syslog"
+        backend: "stdout"
       },
       automaticConfigReload: false${optionalString (cfg.extraConfig != null) ","}
       ${cfg.extraConfig}
     }
   '';
 
+  deps = pkgs.buildEnv {
+    name = "statsd-runtime-deps";
+    pathsToLink = [ "/lib" ];
+    ignoreCollisions = true;
+
+    paths = backendsToPackages cfg.backends;
+  };
+
 in
 
 {
@@ -42,11 +56,7 @@ in
 
   options.services.statsd = {
 
-    enable = mkOption {
-      description = "Whether to enable statsd stats aggregation service";
-      default = false;
-      type = types.bool;
-    };
+    enable = mkEnableOption "statsd";
 
     listenAddress = mkOption {
       description = "Address that statsd listens on over UDP";
@@ -110,6 +120,11 @@ in
 
   config = mkIf cfg.enable {
 
+    assertions = map (backend: {
+      assertion = !isBuiltinBackend backend -> hasAttrByPath [ backend ] pkgs.nodePackages;
+      message = "Only builtin backends (graphite, console, repeater) or backends enumerated in `pkgs.nodePackages` are allowed!";
+    }) cfg.backends;
+
     users.extraUsers = singleton {
       name = "statsd";
       uid = config.ids.uids.statsd;
@@ -120,9 +135,7 @@ in
       description = "Statsd Server";
       wantedBy = [ "multi-user.target" ];
       environment = {
-        NODE_PATH=concatMapStringsSep ":"
-          (pkg: "${builtins.getAttr pkg pkgs.statsd.nodePackages}/lib/node_modules")
-          (filter (name: !isBuiltinBackend name) cfg.backends);
+        NODE_PATH = "${deps}/lib/node_modules";
       };
       serviceConfig = {
         ExecStart = "${pkgs.statsd}/bin/statsd ${configFile}";
diff --git a/nixos/modules/services/network-filesystems/beegfs.nix b/nixos/modules/services/network-filesystems/beegfs.nix
new file mode 100644
index 000000000000..a6a2ec6cbc36
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/beegfs.nix
@@ -0,0 +1,343 @@
+{ config, lib, pkgs, ...} :
+
+with lib;
+
+let
+  cfg = config.services.beegfs;
+
+  # functions for the generations of config files
+
+  configMgmtd = name: cfg: pkgs.writeText "mgmt-${name}.conf" ''
+    storeMgmtdDirectory = ${cfg.mgmtd.storeDir}
+    storeAllowFirstRunInit = false
+    connAuthFile = ${cfg.connAuthFile}
+    connPortShift = ${toString cfg.connPortShift}
+
+    ${cfg.mgmtd.extraConfig}
+  '';
+
+  configAdmon = name: cfg: pkgs.writeText "admon-${name}.conf" ''
+    sysMgmtdHost = ${cfg.mgmtdHost}
+    connAuthFile = ${cfg.connAuthFile}
+    connPortShift = ${toString cfg.connPortShift}
+
+    ${cfg.admon.extraConfig}
+  '';
+
+  configMeta = name: cfg: pkgs.writeText "meta-${name}.conf" ''
+    storeMetaDirectory = ${cfg.meta.storeDir}
+    sysMgmtdHost = ${cfg.mgmtdHost}
+    connAuthFile = ${cfg.connAuthFile}
+    connPortShift = ${toString cfg.connPortShift}
+    storeAllowFirstRunInit = false
+
+    ${cfg.mgmtd.extraConfig}
+  '';
+
+  configStorage = name: cfg: pkgs.writeText "storage-${name}.conf" ''
+    storeStorageDirectory = ${cfg.storage.storeDir}
+    sysMgmtdHost = ${cfg.mgmtdHost}
+    connAuthFile = ${cfg.connAuthFile}
+    connPortShift = ${toString cfg.connPortShift}
+    storeAllowFirstRunInit = false
+
+    ${cfg.storage.extraConfig}
+  '';
+
+  configHelperd = name: cfg: pkgs.writeText "helperd-${name}.conf" ''
+    connAuthFile = ${cfg.connAuthFile}
+    ${cfg.helperd.extraConfig}
+  '';
+
+  configClientFilename = name : "/etc/beegfs/client-${name}.conf";
+
+  configClient = name: cfg: ''
+    sysMgmtdHost = ${cfg.mgmtdHost}
+    connAuthFile = ${cfg.connAuthFile}
+    connPortShift = ${toString cfg.connPortShift}
+
+    ${cfg.client.extraConfig}
+  '';
+
+  serviceList = [
+    { service = "admon"; cfgFile = configAdmon; }
+    { service = "meta"; cfgFile = configMeta; }
+    { service = "mgmtd"; cfgFile = configMgmtd; }
+    { service = "storage"; cfgFile = configStorage; }
+  ];
+
+  # functions to generate systemd.service entries
+
+  systemdEntry = service: cfgFile: (mapAttrs' ( name: cfg:
+    (nameValuePair "beegfs-${service}-${name}" (mkIf cfg."${service}".enable {
+    wantedBy = [ "multi-user.target" ];
+    requires = [ "network-online.target" ];
+    after = [ "network-online.target" ];
+    serviceConfig = rec {
+      ExecStart = ''
+        ${pkgs.beegfs}/bin/beegfs-${service} \
+          cfgFile=${cfgFile name cfg} \
+          pidFile=${PIDFile}
+      '';
+      PIDFile = "/run/beegfs-${service}-${name}.pid";
+      TimeoutStopSec = "300";
+    };
+  }))) cfg);
+
+  systemdHelperd =  mapAttrs' ( name: cfg:
+    (nameValuePair "beegfs-helperd-${name}" (mkIf cfg.client.enable {
+    wantedBy = [ "multi-user.target" ];
+    requires = [ "network-online.target" ];
+    after = [ "network-online.target" ];
+    serviceConfig = rec {
+      ExecStart = ''
+        ${pkgs.beegfs}/bin/beegfs-helperd \
+          cfgFile=${configHelperd name cfg} \
+          pidFile=${PIDFile}
+      '';
+      PIDFile = "/run/beegfs-helperd-${name}.pid";
+      TimeoutStopSec = "300";
+    };
+   }))) cfg;
+
+  # wrappers to beegfs tools. Avoid typing path of config files
+  utilWrappers = mapAttrsToList ( name: cfg:
+      ( pkgs.runCommand "beegfs-utils-${name}" { nativeBuildInputs = [ pkgs.makeWrapper ]; } ''
+        mkdir -p $out/bin
+
+        makeWrapper ${pkgs.beegfs}/bin/beegfs-check-servers \
+                    $out/bin/beegfs-check-servers-${name} \
+                    --add-flags "-c ${configClientFilename name}" \
+                    --prefix PATH : ${lib.makeBinPath [ pkgs.beegfs ]}
+
+        makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
+                    $out/bin/beegfs-ctl-${name} \
+                    --add-flags "--cfgFile=${configClientFilename name}"
+
+        makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \
+                    $out/bin/beegfs-df-${name} \
+                    --add-flags "--cfgFile=${configClientFilename name}" \
+                    --add-flags --listtargets  \
+                    --add-flags --hidenodeid \
+                    --add-flags --pools \
+                    --add-flags --spaceinfo
+
+        makeWrapper ${pkgs.beegfs}/bin/beegfs-fsck \
+                    $out/bin/beegfs-fsck-${name} \
+                    --add-flags "--cfgFile=${configClientFilename name}"
+      ''
+     )) cfg;
+in
+{
+  ###### interface
+
+  options = {
+    services.beegfsEnable = mkEnableOption "BeeGFS";
+
+    services.beegfs = mkOption {
+      default = {};
+      description = ''
+        BeeGFS configurations. Every mount point requires a separate configuration.
+      '';
+      type = with types; attrsOf (submodule ({ config, ... } : {
+        options = {
+          mgmtdHost = mkOption {
+            type = types.str;
+            default = null;
+            example = "master";
+            description = ''Hostname of managament host.'';
+          };
+
+          connAuthFile = mkOption {
+            type = types.str;
+            default = "";
+            example = "/etc/my.key";
+            description = "File containing shared secret authentication.";
+          };
+
+          connPortShift = mkOption {
+            type = types.int;
+            default = 0;
+            example = 5;
+            description = ''
+              For each additional beegfs configuration shift all
+              service TCP/UDP ports by at least 5.
+            '';
+          };
+
+          client = {
+            enable = mkEnableOption "BeeGFS client";
+
+            mount = mkOption {
+              type = types.bool;
+              default = true;
+              description = "Create fstab entry automatically";
+            };
+
+            mountPoint = mkOption {
+              type = types.str;
+              default = "/run/beegfs";
+              description = ''
+                Mount point under which the beegfs filesytem should be mounted.
+                If mounted manually the mount option specifing the config file is needed:
+                cfgFile=/etc/beegfs/beegfs-client-&lt;name&gt;.conf
+              '';
+            };
+
+            extraConfig = mkOption {
+              type = types.lines;
+              default = "";
+              description = ''
+                Additional lines for beegfs-client.conf.
+                See documentation for further details.
+             '';
+            };
+          };
+
+          helperd = {
+            extraConfig = mkOption {
+              type = types.lines;
+              default = "";
+              description = ''
+                Additional lines for beegfs-helperd.conf. See documentation
+                for further details.
+              '';
+            };
+          };
+
+          mgmtd = {
+            enable = mkEnableOption "BeeGFS mgmtd daemon";
+
+            storeDir = mkOption {
+              type = types.path;
+              default = null;
+              example = "/data/beegfs-mgmtd";
+              description = ''
+                Data directory for mgmtd.
+                Must not be shared with other beegfs daemons.
+                This directory must exist and it must be initialized
+                with beegfs-setup-mgmtd, e.g. "beegfs-setup-mgmtd -C -p &lt;storeDir&gt;"
+              '';
+            };
+
+            extraConfig = mkOption {
+              type = types.lines;
+              default = "";
+              description = ''
+                Additional lines for beegfs-mgmtd.conf. See documentation
+                for further details.
+              '';
+            };
+          };
+
+          admon = {
+            enable = mkEnableOption "BeeGFS admon daemon";
+
+            extraConfig = mkOption {
+              type = types.lines;
+              default = "";
+              description = ''
+                Additional lines for beegfs-admon.conf. See documentation
+                for further details.
+              '';
+            };
+          };
+
+          meta = {
+            enable = mkEnableOption "BeeGFS meta data daemon";
+
+            storeDir = mkOption {
+              type = types.path;
+              default = null;
+              example = "/data/beegfs-meta";
+              description = ''
+                Data directory for meta data service.
+                Must not be shared with other beegfs daemons.
+                The underlying filesystem must be mounted with xattr turned on.
+                This directory must exist and it must be initialized
+                with beegfs-setup-meta, e.g.
+                "beegfs-setup-meta -C -s &lt;serviceID&gt; -p &lt;storeDir&gt;"
+              '';
+            };
+
+            extraConfig = mkOption {
+              type = types.str;
+              default = "";
+              description = ''
+                Additional lines for beegfs-meta.conf. See documentation
+                for further details.
+              '';
+            };
+          };
+
+          storage = {
+            enable = mkEnableOption "BeeGFS storage daemon";
+
+            storeDir = mkOption {
+              type = types.path;
+              default = null;
+              example = "/data/beegfs-storage";
+              description = ''
+                Data directories for storage service.
+                Must not be shared with other beegfs daemons.
+                The underlying filesystem must be mounted with xattr turned on.
+                This directory must exist and it must be initialized
+                with beegfs-setup-storage, e.g.
+                "beegfs-setup-storage -C -s &lt;serviceID&gt; -i &lt;storageTargetID&gt; -p &lt;storeDir&gt;"
+              '';
+            };
+
+            extraConfig = mkOption {
+              type = types.str;
+              default = "";
+              description = ''
+                Addional lines for beegfs-storage.conf. See documentation
+                for further details.
+              '';
+            };
+          };
+        };
+      }));
+    };
+  };
+
+  ###### implementation
+
+  config =
+    mkIf config.services.beegfsEnable {
+
+    environment.systemPackages = utilWrappers;
+
+    # Put the client.conf files in /etc since they are needed
+    # by the commandline tools
+    environment.etc = mapAttrs' ( name: cfg:
+      (nameValuePair "beegfs/client-${name}.conf" (mkIf (cfg.client.enable)
+    {
+      enable = true;
+      text = configClient name cfg;
+    }))) cfg;
+
+    # Kernel module, we need it only once per host.
+    boot = mkIf (
+      foldr (a: b: a || b) false
+        (map (x: x.client.enable) (collect (x: x ? client) cfg)))
+    {
+      kernelModules = [ "beegfs" ];
+      extraModulePackages = [ pkgs.linuxPackages.beegfs-module ];
+    };
+
+    # generate fstab entries
+    fileSystems = mapAttrs' (name: cfg:
+      (nameValuePair cfg.client.mountPoint (optionalAttrs cfg.client.mount (mkIf cfg.client.enable {
+      device = "beegfs_nodev";
+      fsType = "beegfs";
+      mountPoint = cfg.client.mountPoint;
+      options = [ "cfgFile=${configClientFilename name}" "_netdev" ];
+    })))) cfg;
+
+    # generate systemd services
+    systemd.services = systemdHelperd //
+      foldr (a: b: a // b) {}
+        (map (x: systemdEntry x.service x.cfgFile) serviceList);
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/davfs2.nix b/nixos/modules/services/network-filesystems/davfs2.nix
new file mode 100644
index 000000000000..6b2a770100c5
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/davfs2.nix
@@ -0,0 +1,74 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.davfs2;
+  cfgFile = pkgs.writeText "davfs2.conf" ''
+    dav_user ${cfg.davUser}
+    dav_group ${cfg.davGroup}
+    ${cfg.extraConfig}
+  '';
+in
+{
+  options.services.davfs2 = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable davfs2.
+      '';
+    };
+
+    davUser = mkOption {
+      type = types.string;
+      default = "davfs2";
+      description = ''
+        When invoked by root the mount.davfs daemon will run as this user.
+        Value must be given as name, not as numerical id.
+      '';
+    };
+
+    davGroup = mkOption {
+      type = types.string;
+      default = "davfs2";
+      description = ''
+        The group of the running mount.davfs daemon. Ordinary users must be
+        member of this group in order to mount a davfs2 file system. Value must
+        be given as name, not as numerical id.
+      '';
+    };
+
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      example = ''
+        kernel_fs coda
+        proxy foo.bar:8080
+        use_locks 0
+      '';
+      description = ''
+        Extra lines appended to the configuration of davfs2.
+      ''  ;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.davfs2 ];
+    environment.etc."davfs2/davfs2.conf".source = cfgFile;
+
+    users.extraGroups = optionalAttrs (cfg.davGroup == "davfs2") (singleton {
+      name = "davfs2";
+      gid = config.ids.gids.davfs2;
+    });
+
+    users.extraUsers = optionalAttrs (cfg.davUser == "davfs2") (singleton {
+      name = "davfs2";
+      createHome = false;
+      group = cfg.davGroup;
+      uid = config.ids.uids.davfs2;
+      description = "davfs2 user";
+    });
+  };
+
+}
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 9b9c91a4f167..09cd9cb22ca8 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -56,6 +56,7 @@ let
       serviceConfig = {
         ExecStart = "${samba}/sbin/${appName} ${args}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        LimitNOFILE = 16384;
         Type = "notify";
       };
 
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index ed658258c7f9..857657eea4db 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -10,7 +10,7 @@ let
   # This is somewhat more flexible than preloading the key as an
   # embedded string.
   upstreamResolverListPubKey = pkgs.fetchurl {
-    url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/minisign.pub;
+    url = https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/minisign.pub;
     sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh";
   };
 
@@ -258,9 +258,9 @@ in
         domain=raw.githubusercontent.com
         get="curl -fSs --resolve $domain:443:$(hostip -r 8.8.8.8 $domain | head -1)"
         $get -o dnscrypt-resolvers.csv.tmp \
-          https://$domain/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv
+          https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv
         $get -o dnscrypt-resolvers.csv.minisig.tmp \
-          https://$domain/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig
+          https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig
         mv dnscrypt-resolvers.csv.minisig{.tmp,}
         if ! minisign -q -V -p ${upstreamResolverListPubKey} \
           -m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig ; then
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index ca2e2a065dcf..8f5aeee4a16b 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -126,6 +126,7 @@ let
         [${tun.name}]
         type = client
         destination = ${tun.destination}
+        destinationport = ${toString tun.destinationPort}
         keys = ${tun.keys}
         address = ${tun.address}
         port = ${toString tun.port}
@@ -137,15 +138,15 @@ let
       '')
     }
     ${flip concatMapStrings
-      (collect (tun: tun ? port && tun ? host) cfg.inTunnels)
-      (tun: let portStr = toString tun.port; in ''
+      (collect (tun: tun ? port && tun ? address) cfg.inTunnels)
+      (tun: ''
         [${tun.name}]
         type = server
         destination = ${tun.destination}
         keys = ${tun.keys}
         host = ${tun.address}
-        port = ${tun.port}
-        inport = ${tun.inPort}
+        port = ${toString tun.port}
+        inport = ${toString tun.inPort}
         accesslist = ${builtins.concatStringsSep "," tun.accessList}
       '')
     }
@@ -405,7 +406,13 @@ in
         default = {};
         type = with types; loaOf (submodule (
           { name, config, ... }: {
-            options = commonTunOpts name;
+            options = {
+              destinationPort = mkOption {
+                type = types.int;
+                default = 0;
+                description = "Connect to particular port at destination.";
+              };
+            } // commonTunOpts name;
             config = {
               name = mkDefault name;
             };
diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix
index 18e2ab9aebf1..011a9b2f58ea 100644
--- a/nixos/modules/services/networking/kresd.nix
+++ b/nixos/modules/services/networking/kresd.nix
@@ -72,6 +72,7 @@ in
         (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53")
         cfg.interfaces;
       socketConfig.ListenDatagram = listenStreams;
+      socketConfig.FreeBind = true;
     };
 
     systemd.sockets.kresd-control = rec {
@@ -82,20 +83,11 @@ in
       socketConfig = {
         FileDescriptorName = "control";
         Service = "kresd.service";
-        SocketMode = "0660"; # only root user/group may connect
+        SocketMode = "0660"; # only root user/group may connect and control kresd
       };
     };
 
-    # Create the cacheDir; tmpfiles don't work on nixos-rebuild switch.
-    systemd.services.kresd-cachedir = {
-      serviceConfig.Type = "oneshot";
-      script = ''
-        if [ ! -d '${cfg.cacheDir}' ]; then
-          mkdir -p '${cfg.cacheDir}'
-          chown kresd:kresd '${cfg.cacheDir}'
-        fi
-      '';
-    };
+    systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ];
 
     systemd.services.kresd = {
       description = "Knot-resolver daemon";
@@ -104,16 +96,15 @@ in
         User = "kresd";
         Type = "notify";
         WorkingDirectory = cfg.cacheDir;
+        Restart = "on-failure";
       };
 
       script = ''
         exec '${package}/bin/kresd' --config '${configFile}' \
-          -k '${cfg.cacheDir}/root.key'
+          -k '${pkgs.dns-root-data}/root.key'
       '';
 
-      after = [ "kresd-cachedir.service" ];
-      requires = [ "kresd.socket" "kresd-cachedir.service" ];
-      wantedBy = [ "sockets.target" ];
+      requires = [ "kresd.socket" ];
     };
   };
 }
diff --git a/nixos/modules/services/networking/lldpd.nix b/nixos/modules/services/networking/lldpd.nix
index ba4e1b1542fe..db1534edfd7c 100644
--- a/nixos/modules/services/networking/lldpd.nix
+++ b/nixos/modules/services/networking/lldpd.nix
@@ -24,6 +24,7 @@ in
       description = "lldpd user";
       group = "_lldpd";
       home = "/var/run/lldpd";
+      isSystemUser = true;
     };
     users.extraGroups._lldpd = {};
 
diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix
index 366bb2ed7a80..df4246d216d8 100644
--- a/nixos/modules/services/networking/nat.nix
+++ b/nixos/modules/services/networking/nat.nix
@@ -19,6 +19,8 @@ let
     iptables -w -t nat -D POSTROUTING -j nixos-nat-post 2>/dev/null || true
     iptables -w -t nat -F nixos-nat-post 2>/dev/null || true
     iptables -w -t nat -X nixos-nat-post 2>/dev/null || true
+
+    ${cfg.extraStopCommands}
   '';
 
   setupNat = ''
@@ -53,6 +55,14 @@ let
         -j DNAT --to-destination ${fwd.destination}
     '') cfg.forwardPorts}
 
+    ${optionalString (cfg.dmzHost != null) ''
+      iptables -w -t nat -A nixos-nat-pre \
+        -i ${cfg.externalInterface} -j DNAT \
+	--to-destination ${cfg.dmzHost}
+    ''}
+
+    ${cfg.extraCommands}
+
     # Append our chains to the nat tables
     iptables -w -t nat -A PREROUTING -j nixos-nat-pre
     iptables -w -t nat -A POSTROUTING -j nixos-nat-post
@@ -125,15 +135,15 @@ in
       type = with types; listOf (submodule {
         options = {
           sourcePort = mkOption {
-            type = types.int;
+            type = types.either types.int (types.strMatching "[[:digit:]]+:[[:digit:]]+");
             example = 8080;
-            description = "Source port of the external interface";
+            description = "Source port of the external interface; to specify a port range, use a string with a colon (e.g. \"60000:61000\")";
           };
 
           destination = mkOption {
             type = types.str;
             example = "10.0.0.1:80";
-            description = "Forward connection to destination ip:port";
+            description = "Forward connection to destination ip:port; to specify a port range, use ip:start-end";
           };
 
           proto = mkOption {
@@ -153,6 +163,39 @@ in
         '';
     };
 
+    networking.nat.dmzHost = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "10.0.0.1";
+      description =
+        ''
+          The local IP address to which all traffic that does not match any
+          forwarding rule is forwarded.
+        '';
+    };
+
+    networking.nat.extraCommands = mkOption {
+      type = types.lines;
+      default = "";
+      example = "iptables -A INPUT -p icmp -j ACCEPT";
+      description =
+        ''
+          Additional shell commands executed as part of the nat
+          initialisation script.
+        '';
+    };
+
+    networking.nat.extraStopCommands = mkOption {
+      type = types.lines;
+      default = "";
+      example = "iptables -D INPUT -p icmp -j ACCEPT || true";
+      description =
+        ''
+          Additional shell commands executed as part of the nat
+          teardown script.
+        '';
+    };
+
   };
 
 
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 6bdae32f72bb..62afbf32c2f6 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -241,6 +241,19 @@ in {
           A list of scripts which will be executed in response to  network  events.
         '';
       };
+
+      enableStrongSwan = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Enable the StrongSwan plugin.
+          </para><para>
+          If you enable this option the
+          <literal>networkmanager_strongswan</literal> plugin will be added to
+          the <option>networking.networkmanager.packages</option> option
+          so you don't need to to that yourself.
+        '';
+      };
     };
   };
 
@@ -333,13 +346,13 @@ in {
       wireless.enable = lib.mkDefault false;
     };
 
-    powerManagement.resumeCommands = ''
-      ${config.systemd.package}/bin/systemctl restart network-manager
-    '';
-
     security.polkit.extraConfig = polkitConf;
 
-    services.dbus.packages = cfg.packages;
+    networking.networkmanager.packages =
+      mkIf cfg.enableStrongSwan [ pkgs.networkmanager_strongswan ];
+
+    services.dbus.packages =
+      optional cfg.enableStrongSwan pkgs.strongswanNM ++ cfg.packages;
 
     services.udev.packages = cfg.packages;
   };
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index c8b8ed547ebb..4241e6fcceab 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -11,6 +11,8 @@ let
 
   # build nsd with the options needed for the given config
   nsdPkg = pkgs.nsd.override {
+    configFile = "${configFile}/nsd.conf";
+
     bind8Stats = cfg.bind8Stats;
     ipv6 = cfg.ipv6;
     ratelimit = cfg.ratelimit.enable;
@@ -788,6 +790,8 @@ in
 
   config = mkIf cfg.enable {
 
+    environment.systemPackages = [ nsdPkg ];
+
     users.extraGroups = singleton {
       name = username;
       gid = config.ids.gids.nsd;
@@ -845,4 +849,6 @@ in
     };
 
   };
+
+  meta.maintainers = with lib.maintainers; [ hrdinka ];
 }
diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix
index fb9c9dc67f24..f34d8e172b46 100644
--- a/nixos/modules/services/networking/prosody.nix
+++ b/nixos/modules/services/networking/prosody.nix
@@ -10,98 +10,126 @@ let
 
     options = {
 
-      # TODO: require attribute
       key = mkOption {
-        type = types.str;
-        description = "Path to the key file";
+        type = types.path;
+        description = "Path to the key file.";
       };
 
-      # TODO: require attribute
       cert = mkOption {
-        type = types.str;
-        description = "Path to the certificate file";
+        type = types.path;
+        description = "Path to the certificate file.";
+      };
+
+      extraOptions = mkOption {
+        type = types.attrs;
+        default = {};
+        description = "Extra SSL configuration options.";
       };
+
     };
   };
 
   moduleOpts = {
 
     roster = mkOption {
+      type = types.bool;
       default = true;
       description = "Allow users to have a roster";
     };
 
     saslauth = mkOption {
+      type = types.bool;
       default = true;
       description = "Authentication for clients and servers. Recommended if you want to log in.";
     };
 
     tls = mkOption {
+      type = types.bool;
       default = true;
       description = "Add support for secure TLS on c2s/s2s connections";
     };
 
     dialback = mkOption {
+      type = types.bool;
       default = true;
       description = "s2s dialback support";
     };
 
     disco = mkOption {
+      type = types.bool;
       default = true;
       description = "Service discovery";
     };
 
     legacyauth = mkOption {
+      type = types.bool;
       default = true;
       description = "Legacy authentication. Only used by some old clients and bots";
     };
 
     version = mkOption {
+      type = types.bool;
       default = true;
       description = "Replies to server version requests";
     };
 
     uptime = mkOption {
+      type = types.bool;
       default = true;
       description = "Report how long server has been running";
     };
 
     time = mkOption {
+      type = types.bool;
       default = true;
       description = "Let others know the time here on this server";
     };
 
     ping = mkOption {
+      type = types.bool;
       default = true;
       description = "Replies to XMPP pings with pongs";
     };
 
     console = mkOption {
+      type = types.bool;
       default = false;
       description = "telnet to port 5582";
     };
 
     bosh = mkOption {
+      type = types.bool;
       default = false;
       description = "Enable BOSH clients, aka 'Jabber over HTTP'";
     };
 
     httpserver = mkOption {
+      type = types.bool;
       default = false;
       description = "Serve static files from a directory over HTTP";
     };
 
     websocket = mkOption {
+      type = types.bool;
       default = false;
       description = "Enable WebSocket support";
     };
 
   };
 
-  createSSLOptsStr = o:
-    if o ? key && o ? cert then
-      ''ssl = { key = "${o.key}"; certificate = "${o.cert}"; };''
-    else "";
+  toLua = x:
+    if builtins.isString x then ''"${x}"''
+    else if builtins.isBool x then toString x
+    else if builtins.isInt x then toString x
+    else throw "Invalid Lua value";
+
+  createSSLOptsStr = o: ''
+    ssl = {
+      key = "${o.key}";
+      certificate = "${o.cert}";
+      ${concatStringsSep "\n" (mapAttrsToList (name: value: "${name} = ${toLua value};") o.extraOptions)}
+    };
+  '';
 
   vHostOpts = { ... }: {
 
@@ -114,18 +142,20 @@ let
       };
 
       enabled = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to enable the virtual host";
       };
 
       ssl = mkOption {
-        description = "Paths to SSL files";
+        type = types.nullOr (types.submodule sslOpts);
         default = null;
-        options = [ sslOpts ];
+        description = "Paths to SSL files";
       };
 
       extraConfig = mkOption {
-        default = '''';
+        type = types.lines;
+        default = "";
         description = "Additional virtual host specific configuration";
       };
 
@@ -144,11 +174,13 @@ in
     services.prosody = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
         description = "Whether to enable the prosody server";
       };
 
       allowRegistration = mkOption {
+        type = types.bool;
         default = false;
         description = "Allow account creation";
       };
@@ -156,8 +188,9 @@ in
       modules = moduleOpts;
 
       extraModules = mkOption {
-        description = "Enable custom modules";
+        type = types.listOf types.str;
         default = [];
+        description = "Enable custom modules";
       };
 
       virtualHosts = mkOption {
@@ -183,20 +216,21 @@ in
       };
 
       ssl = mkOption {
-        description = "Paths to SSL files";
+        type = types.nullOr (types.submodule sslOpts);
         default = null;
-        options = [ sslOpts ];
+        description = "Paths to SSL files";
       };
 
       admins = mkOption {
-        description = "List of administrators of the current host";
-        example = [ "admin1@example.com" "admin2@example.com" ];
+        type = types.listOf types.str;
         default = [];
+        example = [ "admin1@example.com" "admin2@example.com" ];
+        description = "List of administrators of the current host";
       };
 
       extraConfig = mkOption {
         type = types.lines;
-        default = '''';
+        default = "";
         description = "Additional prosody configuration";
       };
 
@@ -263,17 +297,17 @@ in
     };
 
     systemd.services.prosody = {
-
       description = "Prosody XMPP server";
       after = [ "network-online.target" ];
       wants = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
+      restartTriggers = [ config.environment.etc."prosody/prosody.cfg.lua".source ];
       serviceConfig = {
         User = "prosody";
+        Type = "forking";
         PIDFile = "/var/lib/prosody/prosody.pid";
         ExecStart = "${pkgs.prosody}/bin/prosodyctl start";
       };
-
     };
 
   };
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index f0fddcca766f..aa9c0fa1c09f 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -248,13 +248,10 @@ in
       let
         service =
           { description = "SSH Daemon";
-
             wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
-
+            after = [ "network.target" ];
             stopIfChanged = false;
-
             path = [ cfgc.package pkgs.gawk ];
-
             environment.LD_LIBRARY_PATH = nssModulesPath;
 
             preStart =
diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix
index ac589be57736..e3b6b638f5a7 100644
--- a/nixos/modules/services/scheduling/fcron.nix
+++ b/nixos/modules/services/scheduling/fcron.nix
@@ -90,16 +90,24 @@ in
       [ (allowdeny "allow" (cfg.allow))
         (allowdeny "deny" cfg.deny)
         # see man 5 fcron.conf
-        { source = pkgs.writeText "fcron.conf" ''
-            fcrontabs   =       /var/spool/fcron
-            pidfile     =       /var/run/fcron.pid
-            fifofile    =       /var/run/fcron.fifo
-            fcronallow  =       /etc/fcron.allow
-            fcrondeny   =       /etc/fcron.deny
-            shell       =       /bin/sh
-            sendmail    =       /run/wrappers/bin/sendmail
-            editor      =       ${pkgs.vim}/bin/vim
-          '';
+        { source =
+            let
+              isSendmailWrapped =
+                lib.hasAttr "sendmail" config.security.wrappers;
+              sendmailPath =
+                if isSendmailWrapped then "/run/wrappers/bin/sendmail"
+                else "${config.system.path}/bin/sendmail";
+            in
+            pkgs.writeText "fcron.conf" ''
+              fcrontabs   =       /var/spool/fcron
+              pidfile     =       /var/run/fcron.pid
+              fifofile    =       /var/run/fcron.fifo
+              fcronallow  =       /etc/fcron.allow
+              fcrondeny   =       /etc/fcron.deny
+              shell       =       /bin/sh
+              sendmail    =       ${sendmailPath}
+              editor      =       ${pkgs.vim}/bin/vim
+            '';
           target = "fcron.conf";
           gid = config.ids.gids.fcron;
           mode = "0644";
diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix
index 7de2d121e76c..4161c61ed375 100644
--- a/nixos/modules/services/security/clamav.nix
+++ b/nixos/modules/services/security/clamav.nix
@@ -97,8 +97,8 @@ in
 
     systemd.services.clamav-daemon = optionalAttrs cfg.daemon.enable {
       description = "ClamAV daemon (clamd)";
-      after = mkIf cfg.updater.enable [ "clamav-freshclam.service" ];
-      requires = mkIf cfg.updater.enable [ "clamav-freshclam.service" ];
+      after = optional cfg.updater.enable "clamav-freshclam.service";
+      requires = optional cfg.updater.enable "clamav-freshclam.service";
       wantedBy = [ "multi-user.target" ];
       restartTriggers = [ clamdConfigFile ];
 
diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix
index bc79d9f2a590..fa4aeb22ae9d 100644
--- a/nixos/modules/services/security/tor.nix
+++ b/nixos/modules/services/security/tor.nix
@@ -9,6 +9,26 @@ let
   opt    = name: value: optionalString (value != null) "${name} ${value}";
   optint = name: value: optionalString (value != null && value != 0)    "${name} ${toString value}";
 
+  isolationOptions = {
+    type = types.listOf (types.enum [
+      "IsolateClientAddr"
+      "IsolateSOCKSAuth"
+      "IsolateClientProtocol"
+      "IsolateDestPort"
+      "IsolateDestAddr"
+    ]);
+    default = [];
+    example = [
+      "IsolateClientAddr"
+      "IsolateSOCKSAuth"
+      "IsolateClientProtocol"
+      "IsolateDestPort"
+      "IsolateDestAddr"
+    ];
+    description = "Tor isolation options";
+  };
+
+
   torRc = ''
     User tor
     DataDirectory ${torDirectory}
@@ -20,10 +40,20 @@ let
     ${optint "ControlPort" cfg.controlPort}
   ''
   # Client connection config
-  + optionalString cfg.client.enable  ''
-    SOCKSPort ${cfg.client.socksListenAddress} IsolateDestAddr
+  + optionalString cfg.client.enable ''
+    SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions}
     SOCKSPort ${cfg.client.socksListenAddressFaster}
     ${opt "SocksPolicy" cfg.client.socksPolicy}
+
+    ${optionalString cfg.client.transparentProxy.enable ''
+    TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions}
+    ''}
+
+    ${optionalString cfg.client.dns.enable ''
+    DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions}
+    AutomapHostsOnResolve 1
+    AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes}
+    ''}
   ''
   # Relay config
   + optionalString cfg.relay.enable ''
@@ -154,6 +184,55 @@ in
           '';
         };
 
+        socksIsolationOptions = mkOption (isolationOptions // {
+          default = ["IsolateDestAddr"];
+        });
+
+        transparentProxy = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable tor transaprent proxy";
+          };
+
+          listenAddress = mkOption {
+            type = types.str;
+            default = "127.0.0.1:9040";
+            example = "192.168.0.1:9040";
+            description = ''
+              Bind transparent proxy to this address.
+            '';
+          };
+
+          isolationOptions = mkOption isolationOptions;
+        };
+
+        dns = {
+          enable = mkOption {
+            type = types.bool;
+            default = false;
+            description = "Whether to enable tor dns resolver";
+          };
+
+          listenAddress = mkOption {
+            type = types.str;
+            default = "127.0.0.1:9053";
+            example = "192.168.0.1:9053";
+            description = ''
+              Bind tor dns to this address.
+            '';
+          };
+
+          isolationOptions = mkOption isolationOptions;
+
+          automapHostsSuffixes = mkOption {
+            type = types.listOf types.str;
+            default = [".onion" ".exit"];
+            example = [".onion"];
+            description = "List of suffixes to use with automapHostsOnResolve";
+          };
+        };
+
         privoxy.enable = mkOption {
           type = types.bool;
           default = true;
diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix
index 1f2c56a9efa1..4e685e633354 100644
--- a/nixos/modules/services/security/usbguard.nix
+++ b/nixos/modules/services/security/usbguard.nix
@@ -56,7 +56,7 @@ in {
       };
 
       rules = mkOption {
-        type = types.nullOr types.str;
+        type = types.nullOr types.lines;
         default = null;
         example = ''
           allow with-interface equals { 08:*:* }
diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix
new file mode 100644
index 000000000000..b9355bbb9441
--- /dev/null
+++ b/nixos/modules/services/system/localtime.nix
@@ -0,0 +1,60 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.localtime;
+in {
+  options = {
+    services.localtime = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Enable <literal>localtime</literal>, simple daemon for keeping the system
+          timezone up-to-date based on the current location. It uses geoclue2 to
+          determine the current location and systemd-timedated to actually set
+          the timezone.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    services.geoclue2.enable = true;
+
+    security.polkit.extraConfig = ''
+     polkit.addRule(function(action, subject) {
+       if (action.id == "org.freedesktop.timedate1.set-timezone"
+           && subject.user == "localtimed") {
+         return polkit.Result.YES;
+       }
+     });
+    '';
+
+    users.users = [{
+      name = "localtimed";
+      description = "Taskserver user";
+    }];
+
+    systemd.services.localtime = {
+      description = "localtime service";
+      wantedBy = [ "multi-user.target" ];
+      partOf = [ "geoclue.service "];
+
+      serviceConfig = {
+        Restart                 = "on-failure";
+        # TODO: make it work with dbus
+        #DynamicUser             = true;
+        Nice                    = 10;
+        User                    = "localtimed";
+        PrivateTmp              = "yes";
+        PrivateDevices          = true;
+        PrivateNetwork          = "yes";
+        NoNewPrivileges         = "yes";
+        ProtectSystem           = "strict";
+        ProtectHome             = true;
+        ExecStart               = "${pkgs.localtime}/bin/localtimed";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix
index 76b0ee6da968..c784f4756d19 100644
--- a/nixos/modules/services/web-apps/tt-rss.nix
+++ b/nixos/modules/services/web-apps/tt-rss.nix
@@ -99,8 +99,8 @@ let
 
       user = mkOption {
         type = types.str;
-        default = "nginx";
-        example = "nginx";
+        default = "tt_rss";
+        example = "tt_rss";
         description = ''
           User account under which both the update daemon and the web-application run.
         '';
@@ -466,26 +466,28 @@ let
       '';
     };
 
-    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;
-          '';
+    services.nginx = {
+      enable = true;
+      # NOTE: No configuration is done if not using virtual host
+      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;
+            '';
+          };
         };
       };
     };
 
-
     systemd.services.tt-rss = let
       dbService = if cfg.database.type == "pgsql" then "postgresql.service" else "mysql.service";
     in {
@@ -496,7 +498,7 @@ let
           callSql = e:
               if cfg.database.type == "pgsql" then ''
                   ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \
-                  ${pkgs.postgresql95}/bin/psql \
+                  ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.postgresql.package}/bin/psql \
                     -U ${cfg.database.user} \
                     ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \
                     -c '${e}' \
@@ -521,6 +523,14 @@ let
         ''
 
         + (optionalString (cfg.database.type == "pgsql") ''
+          ${optionalString (cfg.database.host == null && cfg.database.password == null) ''
+            if ! [ -e ${cfg.root}/.db-created ]; then
+              ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createuser ${cfg.database.user}
+              ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createdb -O ${cfg.database.user} ${cfg.database.name}
+              touch ${cfg.root}/.db-created
+            fi
+          ''}
+
           exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \
           | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//')
 
@@ -554,5 +564,28 @@ let
         requires = ["${dbService}"];
         after = ["network.target" "${dbService}"];
     };
+
+    services.mysql = optionalAttrs (cfg.database.type == "mysql") {
+      enable = true;
+      package = mkDefault pkgs.mysql;
+      ensureDatabases = [ cfg.database.name ];
+      ensureUsers = [
+        {
+          name = cfg.user;
+          ensurePermissions = {
+            "${cfg.database.name}.*" = "ALL PRIVILEGES";
+          };
+        }
+      ];
+    };
+
+    services.postgresql = optionalAttrs (cfg.database.type == "pgsql") {
+      enable = mkDefault true;
+    };
+
+    users = optionalAttrs (cfg.user == "tt_rss") {
+      extraUsers.tt_rss.group = "tt_rss";
+      extraGroups.tt_rss = {};
+    };
   };
 }
diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix
index 700b4469c565..d23e810dcc62 100644
--- a/nixos/modules/services/web-servers/lighttpd/default.nix
+++ b/nixos/modules/services/web-servers/lighttpd/default.nix
@@ -50,11 +50,14 @@ let
     "mod_geoip"
     "mod_magnet"
     "mod_mysql_vhost"
+    "mod_openssl"  # since v1.4.46
     "mod_scgi"
     "mod_setenv"
     "mod_trigger_b4_dl"
     "mod_uploadprogress"
+    "mod_vhostdb"  # since v1.4.46
     "mod_webdav"
+    "mod_wstunnel"  # since v1.4.46
   ];
 
   maybeModuleString = moduleName:
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 97511aac9737..2951e63e863e 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -167,7 +167,8 @@ let
 
         listenString = { addr, port, ssl, ... }:
           "listen ${addr}:${toString port} "
-          + optionalString ssl "ssl http2 "
+          + optionalString ssl "ssl "
+          + optionalString (ssl && vhost.http2) "http2 "
           + optionalString vhost.default "default_server "
           + ";";
 
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index 801601aafd9d..29f08cc4f307 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -114,6 +114,20 @@ with lib;
       description = "Path to server SSL certificate key.";
     };
 
+    http2 = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to enable HTTP 2.
+        Note that (as of writing) due to nginx's implementation, to disable
+        HTTP 2 you have to disable it on all vhosts that use a given
+        IP address / port.
+        If there is one server block configured to enable http2,then it is
+        enabled for all server blocks on this IP.
+        See https://stackoverflow.com/a/39466948/263061.
+      '';
+    };
+
     root = mkOption {
       type = types.nullOr types.path;
       default = null;
diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix
index 943415e08c64..0b2e5c0b69d9 100644
--- a/nixos/modules/services/web-servers/tomcat.nix
+++ b/nixos/modules/services/web-servers/tomcat.nix
@@ -29,7 +29,7 @@ in
         type = types.package;
         default = pkgs.tomcat85;
         defaultText = "pkgs.tomcat85";
-        example = lib.literalExample "pkgs.tomcatUnstable";
+        example = lib.literalExample "pkgs.tomcat9";
         description = ''
           Which tomcat package to use.
         '';
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 39b27d4ceb61..4622c7b760f0 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -109,9 +109,5 @@ in
 
   };
 
-  config = {
-    services.xserver.displayManager.session = cfg.session.list;
-    environment.systemPackages =
-      mkIf cfg.session.needBGPackages [ pkgs.feh ]; # xsetroot via xserver.enable
-  };
+  config.services.xserver.displayManager.session = cfg.session.list;
 }
diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
index 8a523f0d8036..7f3dc0d7847b 100644
--- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix
+++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -47,7 +47,7 @@ in
         export GTK_DATA_PREFIX=${config.system.path}
         # find theme engines
         export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
-        export XDG_MENU_PREFIX=enlightenment
+        export XDG_MENU_PREFIX=e-
 
         export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}"
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index d2c856fc9332..21d30df5b695 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -136,7 +136,7 @@ in {
           # find theme engines
           export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
 
-          export XDG_MENU_PREFIX=gnome
+          export XDG_MENU_PREFIX=gnome-
 
           ${concatMapStrings (p: ''
             if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix
index ab8a0a48b483..814503ab0bc4 100644
--- a/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -12,6 +12,17 @@ let
     in
       filter (x: !(builtins.elem (pkgName x) ysNames)) xs;
 
+  addToXDGDirs = p: ''
+    if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
+      export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
+    fi
+
+    if [ -d "${p}/lib/girepository-1.0" ]; then
+      export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
+      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
+    fi
+  '';
+
   xcfg = config.services.xserver;
   cfg = xcfg.desktopManager.mate;
 
@@ -20,10 +31,14 @@ in
 {
   options = {
 
-    services.xserver.desktopManager.mate.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = "Enable the MATE desktop environment";
+    services.xserver.desktopManager.mate = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable the MATE desktop environment";
+      };
+
+      debug = mkEnableOption "mate-session debug messages";
     };
 
     environment.mate.excludePackages = mkOption {
@@ -47,15 +62,34 @@ in
         # Find theme engines
         export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0
 
-        export XDG_MENU_PREFIX=mate
+        export XDG_MENU_PREFIX=mate-
 
         # Find the mouse
         export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
 
+        # Let caja find extensions
+        export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
+
+        # Let caja extensions find gsettings schemas
+        ${concatMapStrings (p: ''
+          if [ -d "${p}/lib/caja/extensions-2.0" ]; then
+            ${addToXDGDirs p}
+          fi
+          '')
+          config.environment.systemPackages
+        }
+
+        # Let mate-panel find applets
+        export MATE_PANEL_APPLETS_DIR=$MATE_PANEL_APPLETS_DIR''${MATE_PANEL_APPLETS_DIR:+:}${config.system.path}/share/mate-panel/applets
+        export MATE_PANEL_EXTRA_MODULES=$MATE_PANEL_EXTRA_MODULES''${MATE_PANEL_EXTRA_MODULES:+:}${config.system.path}/lib/mate-panel/applets
+
+        # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
+        ${addToXDGDirs pkgs.mate.mate-control-center}
+
         # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
         ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
 
-        ${pkgs.mate.mate-session-manager}/bin/mate-session &
+        ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} &
         waitPID=$!
       '';
     };
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index bb4f4e868fea..17a2cde3a65d 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -25,8 +25,8 @@ in
         type = types.bool;
         default = true;
         description = ''
-          Enable support for Qt 4-based applications. Particularly, install the
-          Qt 4 version of the Breeze theme and a default backend for Phonon.
+          Enable support for Qt 4-based applications. Particularly, install a
+          default backend for Phonon.
         '';
       };
 
@@ -142,11 +142,13 @@ in
 
           kde-gtk-config breeze-gtk
 
+          qtvirtualkeyboard
+
           libsForQt56.phonon-backend-gstreamer
           libsForQt5.phonon-backend-gstreamer
         ]
 
-        ++ lib.optionals cfg.enableQt4Support [ breeze-qt4 pkgs.phonon-backend-gstreamer ]
+        ++ lib.optionals cfg.enableQt4Support [ pkgs.phonon-backend-gstreamer ]
 
         # Optional hardware support features
         ++ lib.optional config.hardware.bluetooth.enable bluedevil
@@ -193,16 +195,6 @@ in
         theme = mkDefault "breeze";
       };
 
-      boot.plymouth = {
-        theme = mkDefault "breeze";
-        themePackages = mkDefault [
-          (pkgs.breeze-plymouth.override {
-            nixosBranding = true;
-            nixosVersion = config.system.nixosRelease;
-          })
-        ];
-      };
-
       security.pam.services.kde = { allowNullPassword = true; };
 
       # Doing these one by one seems silly, but we currently lack a better
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 9c42dc8781b9..9d5d03638e04 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -3,15 +3,13 @@
 with lib;
 
 let
-
   xcfg = config.services.xserver;
+  pcfg = config.hardware.pulseaudio;
   cfg = xcfg.desktopManager.xfce;
-
 in
 
 {
   options = {
-
     services.xserver.desktopManager.xfce = {
       enable = mkOption {
         type = types.bool;
@@ -96,8 +94,8 @@ in
         pkgs.xfce.xfce4icontheme
         pkgs.xfce.xfce4session
         pkgs.xfce.xfce4settings
-        pkgs.xfce.xfce4mixer
-        pkgs.xfce.xfce4volumed
+       (if pcfg.enable then pkgs.xfce.xfce4mixer_pulse else pkgs.xfce.xfce4mixer)
+       (if pcfg.enable then pkgs.xfce.xfce4volumed_pulse else pkgs.xfce.xfce4volumed)
         pkgs.xfce.xfce4-screenshooter
         pkgs.xfce.xfconf
         # This supplies some "abstract" icons such as
@@ -124,6 +122,7 @@ in
       [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ];
 
     environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ];
+    environment.variables.GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache";
 
     # Enable helpful DBus services.
     services.udisks2.enable = true;
diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
index 1d5dcb2c7cbe..35b715b98fcd 100644
--- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -45,6 +45,8 @@ let
     theme-name = ${cfg.theme.name}
     icon-theme-name = ${cfg.iconTheme.name}
     background = ${ldmcfg.background}
+    ${optionalString (cfg.clock-format != null) "clock-format = ${cfg.clock-format}"}
+    ${optionalString (cfg.indicators != null) "indicators = ${concatStringsSep ";" cfg.indicators}"}
     ${cfg.extraConfig}
     '';
 
@@ -104,6 +106,35 @@ in
 
       };
 
+      clock-format = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "%F";
+        description = ''
+          Clock format string (as expected by strftime, e.g. "%H:%M")
+          to use with the lightdm gtk greeter panel.
+
+          If set to null the default clock format is used.
+        '';
+      };
+
+      indicators = mkOption {
+        type = types.nullOr (types.listOf types.str);
+        default = null;
+        example = [ "~host" "~spacer" "~clock" "~spacer" "~session" "~language" "~a11y" "~power" ];
+        description = ''
+          List of allowed indicator modules to use for the lightdm gtk
+          greeter panel.
+
+          Built-in indicators include "~a11y", "~language", "~session",
+          "~power", "~clock", "~host", "~spacer". Unity indicators can be
+          represented by short name (e.g. "sound", "power"), service file name,
+          or absolute path.
+
+          If set to null the default indicators are used.
+        '';
+      };
+
       extraConfig = mkOption {
         type = types.lines;
         default = "";
diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/x11/hardware/libinput.nix
index 5aecdef812e6..d0a87f183b6f 100644
--- a/nixos/modules/services/x11/hardware/libinput.nix
+++ b/nixos/modules/services/x11/hardware/libinput.nix
@@ -170,7 +170,7 @@ in {
 
       disableWhileTyping = mkOption {
         type = types.bool;
-        default = true;
+        default = false;
         description =
           ''
             Disable input method while typing.
diff --git a/nixos/modules/services/x11/window-managers/awesome.nix b/nixos/modules/services/x11/window-managers/awesome.nix
index eb97449c6bd9..71eb02ec5954 100644
--- a/nixos/modules/services/x11/window-managers/awesome.nix
+++ b/nixos/modules/services/x11/window-managers/awesome.nix
@@ -6,7 +6,11 @@ let
 
   cfg = config.services.xserver.windowManager.awesome;
   awesome = cfg.package;
-  inherit (pkgs.luaPackages) getLuaPath getLuaCPath;
+  getLuaPath = lib : dir : "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}";
+  makeSearchPath = lib.concatMapStrings (path:
+    " --search " + (getLuaPath path "share") +
+    " --search " + (getLuaPath path "lib")
+  );
 in
 
 {
@@ -46,10 +50,7 @@ in
       { name = "awesome";
         start =
           ''
-            export LUA_CPATH="${lib.concatStringsSep ";" (map getLuaCPath cfg.luaModules)}"
-            export LUA_PATH="${lib.concatStringsSep ";" (map getLuaPath cfg.luaModules)}"
-
-            ${awesome}/bin/awesome &
+            ${awesome}/bin/awesome ${makeSearchPath cfg.luaModules} &
             waitPID=$!
           '';
       };
diff --git a/nixos/modules/system/boot/grow-partition.nix b/nixos/modules/system/boot/grow-partition.nix
new file mode 100644
index 000000000000..c4c6d82dc5c8
--- /dev/null
+++ b/nixos/modules/system/boot/grow-partition.nix
@@ -0,0 +1,43 @@
+# This module automatically grows the root partition.
+# This allows an instance to be created with a bigger root filesystem
+# than provided by the machine image.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options = {
+    boot.growPartition = mkEnableOption "grow the root partition on boot";
+  };
+
+  config = mkIf config.boot.growPartition {
+
+    boot.initrd.extraUtilsCommands = ''
+      copy_bin_and_libs ${pkgs.gawk}/bin/gawk
+      copy_bin_and_libs ${pkgs.gnused}/bin/sed
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
+      copy_bin_and_libs ${pkgs.utillinux}/sbin/lsblk
+
+      substitute "${pkgs.cloud-utils}/bin/.growpart-wrapped" "$out/bin/growpart" \
+        --replace "${pkgs.bash}/bin/sh" "/bin/sh" \
+        --replace "awk" "gawk" \
+        --replace "sed" "gnused"
+
+      ln -s sed $out/bin/gnused
+    '';
+
+    boot.initrd.postDeviceCommands = ''
+      rootDevice="${config.fileSystems."/".device}"
+      if [ -e "$rootDevice" ]; then
+        rootDevice="$(readlink -f "$rootDevice")"
+        parentDevice="$(lsblk -npo PKNAME "$rootDevice")"
+        TMPDIR=/run sh $(type -P growpart) "$parentDevice" "''${rootDevice#$parentDevice}"
+        udevadm settle
+      fi
+    '';
+
+  };
+
+}
diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix
index d78775c27582..cdeff4845948 100644
--- a/nixos/modules/system/boot/initrd-ssh.nix
+++ b/nixos/modules/system/boot/initrd-ssh.nix
@@ -89,9 +89,6 @@ in
 
   config = mkIf (config.boot.initrd.network.enable && cfg.enable) {
     assertions = [
-      { assertion = cfg.hostRSAKey != null || cfg.hostDSSKey != null || cfg.hostECDSAKey != null;
-        message = "You should specify at least one host key for initrd SSH";
-      }
       { assertion = cfg.authorizedKeys != [];
         message = "You should specify at least one authorized key for initrd SSH";
       }
@@ -121,7 +118,7 @@ in
         echo ${escapeShellArg key} >> /root/.ssh/authorized_keys
       '') cfg.authorizedKeys)}
 
-      dropbear -s -j -k -E -m -p ${toString cfg.port}
+      dropbear -s -j -k -E -m -p ${toString cfg.port} ${optionalString (cfg.hostRSAKey == null && cfg.hostDSSKey == null && cfg.hostECDSAKey == null) "-R"}
     '';
 
     boot.initrd.secrets =
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index 4db9631743e3..90074a1ba77b 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -197,7 +197,7 @@ in
         "mmc_block"
 
         # Support USB keyboards, in case the boot fails and we only have
-        # a USB keyboard.
+        # a USB keyboard, or for LUKS passphrase prompt.
         "uhci_hcd"
         "ehci_hcd"
         "ehci_pci"
@@ -206,7 +206,7 @@ in
         "xhci_hcd"
         "xhci_pci"
         "usbhid"
-        "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
+        "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp"
 
         # Misc. keyboard stuff.
         "pcips2" "atkbd" "i8042"
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 06f004fb06ec..eefee5a479e7 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -227,6 +227,11 @@ in
       default =
         [ "aes" "aes_generic" "blowfish" "twofish"
           "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
+
+          # workaround until https://marc.info/?l=linux-crypto-vger&m=148783562211457&w=4 is merged
+          # remove once 'modprobe --show-depends xts' shows ecb as a dependency
+          "ecb"
+
           (if pkgs.stdenv.system == "x86_64-linux" then "aes_x86_64" else "aes_i586")
         ];
       description = ''
@@ -434,7 +439,9 @@ in
       ["firewire_ohci" "firewire_core" "firewire_sbp2"];
 
     # Some modules that may be needed for mounting anything ciphered
-    boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" ] ++ luks.cryptoModules;
+    # Also load input_leds to get caps lock light working (#12456)
+    boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" "input_leds" ]
+      ++ luks.cryptoModules;
 
     # copy the cryptsetup binary and it's dependencies
     boot.initrd.extraUtilsCommands = ''
diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix
index 4b0c498424b5..e78fdf1311d3 100644
--- a/nixos/modules/system/boot/plymouth.nix
+++ b/nixos/modules/system/boot/plymouth.nix
@@ -8,9 +8,14 @@ let
 
   cfg = config.boot.plymouth;
 
+  breezePlymouth = pkgs.breeze-plymouth.override {
+    nixosBranding = true;
+    nixosVersion = config.system.nixosRelease;
+  };
+
   themesEnv = pkgs.buildEnv {
     name = "plymouth-themes";
-    paths = [ plymouth ] ++ cfg.themePackages;
+    paths = [ plymouth breezePlymouth ] ++ cfg.themePackages;
   };
 
   configFile = pkgs.writeText "plymouthd.conf" ''
@@ -38,7 +43,7 @@ in
       };
 
       theme = mkOption {
-        default = "fade-in";
+        default = "breeze";
         type = types.str;
         description = ''
           Splash screen theme.
diff --git a/nixos/modules/tasks/filesystems/btrfs.nix b/nixos/modules/tasks/filesystems/btrfs.nix
index 8cfa1b6921d3..1384873b6631 100644
--- a/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixos/modules/tasks/filesystems/btrfs.nix
@@ -1,35 +1,132 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, utils, ... }:
 
 with lib;
 
 let
 
   inInitrd = any (fs: fs == "btrfs") config.boot.initrd.supportedFilesystems;
+  inSystem = any (fs: fs == "btrfs") config.boot.supportedFilesystems;
+
+  cfgScrub = config.services.btrfs.autoScrub;
+
+  enableAutoScrub = cfgScrub.enable;
+  enableBtrfs = inInitrd || inSystem || enableAutoScrub;
 
 in
 
 {
-  config = mkIf (any (fs: fs == "btrfs") config.boot.supportedFilesystems) {
+  options = {
+    # One could also do regular btrfs balances, but that shouldn't be necessary
+    # during normal usage and as long as the filesystems aren't filled near capacity
+    services.btrfs.autoScrub = {
+      enable = mkEnableOption "Enable regular btrfs scrub";
 
-    system.fsPackages = [ pkgs.btrfs-progs ];
+      fileSystems = mkOption {
+        type = types.listOf types.path;
+        example = [ "/" ];
+        description = ''
+          List of paths to btrfs filesystems to regularily call <command>btrfs scrub</command> on.
+          Defaults to all mount points with btrfs filesystems.
+          If you mount a filesystem multiple times or additionally mount subvolumes,
+          you need to manually specify this list to avoid scrubbing multiple times.
+        '';
+      };
 
-    boot.initrd.kernelModules = mkIf inInitrd [ "btrfs" "crc32c" ];
+      interval = mkOption {
+        default = "monthly";
+        type = types.str;
+        example = "weekly";
+        description = ''
+          Systemd calendar expression for when to scrub btrfs filesystems.
+          The recommended period is a month but could be less
+          (<citerefentry><refentrytitle>btrfs-scrub</refentrytitle>
+          <manvolnum>8</manvolnum></citerefentry>).
+          See
+          <citerefentry><refentrytitle>systemd.time</refentrytitle>
+          <manvolnum>7</manvolnum></citerefentry>
+          for more information on the syntax.
+        '';
+      };
+
+    };
+  };
 
-    boot.initrd.extraUtilsCommands = mkIf inInitrd
+  config = mkMerge [
+    (mkIf enableBtrfs {
+      system.fsPackages = [ pkgs.btrfs-progs ];
+
+      boot.initrd.kernelModules = mkIf inInitrd [ "btrfs" "crc32c" ];
+
+      boot.initrd.extraUtilsCommands = mkIf inInitrd
       ''
         copy_bin_and_libs ${pkgs.btrfs-progs}/bin/btrfs
         ln -sv btrfs $out/bin/btrfsck
         ln -sv btrfsck $out/bin/fsck.btrfs
       '';
 
-    boot.initrd.extraUtilsCommandsTest = mkIf inInitrd
+      boot.initrd.extraUtilsCommandsTest = mkIf inInitrd
       ''
         $out/bin/btrfs --version
       '';
 
-    boot.initrd.postDeviceCommands = mkIf inInitrd
+      boot.initrd.postDeviceCommands = mkIf inInitrd
       ''
         btrfs device scan
       '';
-  };
+    })
+
+    (mkIf enableAutoScrub {
+      assertions = [
+        {
+          assertion = cfgScrub.enable -> (cfgScrub.fileSystems != []);
+          message = ''
+            If 'services.btrfs.autoScrub' is enabled, you need to have at least one
+            btrfs file system mounted via 'fileSystems' or specify a list manually
+            in 'services.btrfs.autoScrub.fileSystems'.
+          '';
+        }
+      ];
+
+      # This will yield duplicated units if the user mounts a filesystem multiple times
+      # or additionally mounts subvolumes, but going the other way around via devices would
+      # yield duplicated units when a filesystem spans multiple devices.
+      # This way around seems like the more sensible default.
+      services.btrfs.autoScrub.fileSystems = mkDefault (mapAttrsToList (name: fs: fs.mountPoint)
+      (filterAttrs (name: fs: fs.fsType == "btrfs") config.fileSystems));
+
+      # TODO: Did not manage to do it via the usual btrfs-scrub@.timer/.service
+      # template units due to problems enabling the parameterized units,
+      # so settled with many units and templating via nix for now.
+      # https://github.com/NixOS/nixpkgs/pull/32496#discussion_r156527544
+      systemd.timers = let
+        scrubTimer = fs: let
+          fs' = utils.escapeSystemdPath fs;
+        in nameValuePair "btrfs-scrub-${fs'}" {
+          description = "regular btrfs scrub timer on ${fs}";
+
+          wantedBy = [ "timers.target" ];
+          timerConfig = {
+            OnCalendar = cfgScrub.interval;
+            AccuracySec = "1d";
+            Persistent = true;
+          };
+        };
+      in listToAttrs (map scrubTimer cfgScrub.fileSystems);
+
+      systemd.services = let
+        scrubService = fs: let
+          fs' = utils.escapeSystemdPath fs;
+        in nameValuePair "btrfs-scrub-${fs'}" {
+          description = "btrfs scrub on ${fs}";
+
+          serviceConfig = {
+            Type = "oneshot";
+            Nice = 19;
+            IOSchedulingClass = "idle";
+            ExecStart = "${pkgs.btrfs-progs}/bin/btrfs scrub start -B ${fs}";
+          };
+        };
+      in listToAttrs (map scrubService cfgScrub.fileSystems);
+    })
+  ];
 }
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 7fee99115329..2c0a165887bd 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -268,7 +268,7 @@ in
       assertions = [
         {
           assertion = config.networking.hostId != null;
-          message = "ZFS requires config.networking.hostId to be set";
+          message = "ZFS requires networking.hostId to be set";
         }
         {
           assertion = !cfgZfs.forceImportAll || cfgZfs.forceImportRoot;
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 1d6c41406107..9b4136223c0f 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -128,7 +128,7 @@ in
     # Make it easy to log in as root when running the test interactively.
     users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
 
-    services.xserver.displayManager.logToJournal = true;
+    services.xserver.displayManager.job.logToJournal = true;
   };
 
 }
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index 6cb9e07ae820..f74c42a777f5 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -11,7 +11,7 @@ with lib;
 let cfg = config.ec2; in
 
 {
-  imports = [ ../profiles/headless.nix ./ec2-data.nix ./grow-partition.nix ./amazon-init.nix ];
+  imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-init.nix ];
 
   config = {
 
@@ -21,7 +21,7 @@ let cfg = config.ec2; in
       }
     ];
 
-    virtualisation.growPartition = cfg.hvm;
+    boot.growPartition = cfg.hvm;
 
     fileSystems."/" = {
       device = "/dev/disk/by-label/nixos";
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index e68bfd860601..4038454b2d2f 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -726,6 +726,11 @@ in
 
     networking.dhcpcd.denyInterfaces = [ "ve-*" "vb-*" ];
 
+    services.udev.extraRules = optionalString config.networking.networkmanager.enable ''
+      # Don't manage interfaces created by nixos-container.
+      ENV{INTERFACE}=="v[eb]-*", ENV{NM_UNMANAGED}="1"
+    '';
+
     environment.systemPackages = [ pkgs.nixos-container ];
   });
 }
diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix
index 14826b6272f7..01512911a057 100644
--- a/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixos/modules/virtualisation/ec2-amis.nix
@@ -223,21 +223,22 @@ let self = {
   "17.03".us-west-2.hvm-ebs = "ami-a93daac9";
   "17.03".us-west-2.hvm-s3 = "ami-5139ae31";
 
-  # 17.09.1483.d0f0657ca0
-  "17.09".eu-west-1.hvm-ebs = "ami-cf33e7b6";
-  "17.09".eu-west-2.hvm-ebs = "ami-7d061419";
-  "17.09".eu-central-1.hvm-ebs = "ami-7548fa1a";
-  "17.09".us-east-1.hvm-ebs = "ami-6f669d15";
-  "17.09".us-east-2.hvm-ebs = "ami-cbe1ccae";
-  "17.09".us-west-1.hvm-ebs = "ami-9d95a5fd";
-  "17.09".us-west-2.hvm-ebs = "ami-d3956fab";
-  "17.09".ca-central-1.hvm-ebs = "ami-ee4ef78a";
-  "17.09".ap-southeast-1.hvm-ebs = "ami-1dfc807e";
-  "17.09".ap-southeast-2.hvm-ebs = "ami-dcb350be";
-  "17.09".ap-northeast-1.hvm-ebs = "ami-00ec3d66";
-  "17.09".ap-northeast-2.hvm-ebs = "ami-1107dd7f";
-  "17.09".sa-east-1.hvm-ebs = "ami-0377086f";
-  "17.09".ap-south-1.hvm-ebs = "ami-4a064625";
+  # 17.09.2681.59661f21be6
+  "17.09".eu-west-1.hvm-ebs = "ami-a30192da";
+  "17.09".eu-west-2.hvm-ebs = "ami-295a414d";
+  "17.09".eu-west-3.hvm-ebs = "ami-8c0eb9f1";
+  "17.09".eu-central-1.hvm-ebs = "ami-266cfe49";
+  "17.09".us-east-1.hvm-ebs = "ami-40bee63a";
+  "17.09".us-east-2.hvm-ebs = "ami-9d84aff8";
+  "17.09".us-west-1.hvm-ebs = "ami-d14142b1";
+  "17.09".us-west-2.hvm-ebs = "ami-3eb40346";
+  "17.09".ca-central-1.hvm-ebs = "ami-ca8207ae";
+  "17.09".ap-southeast-1.hvm-ebs = "ami-84bccff8";
+  "17.09".ap-southeast-2.hvm-ebs = "ami-0dc5386f";
+  "17.09".ap-northeast-1.hvm-ebs = "ami-89b921ef";
+  "17.09".ap-northeast-2.hvm-ebs = "ami-179b3b79";
+  "17.09".sa-east-1.hvm-ebs = "ami-4762202b";
+  "17.09".ap-south-1.hvm-ebs = "ami-4e376021";
 
   latest = self."17.09";
 }; in self
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index e3b3e6a5f4ab..75717e08ab2a 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -6,7 +6,7 @@ let
   gce = pkgs.google-compute-engine;
 in
 {
-  imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ./grow-partition.nix ];
+  imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ];
 
   system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
     name = "google-compute-image";
@@ -29,6 +29,7 @@ in
     autoResize = true;
   };
 
+  boot.growPartition = true;
   boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
   boot.initrd.kernelModules = [ "virtio_scsi" ];
   boot.kernelModules = [ "virtio_pci" "virtio_net" ];
diff --git a/nixos/modules/virtualisation/grow-partition.nix b/nixos/modules/virtualisation/grow-partition.nix
index 2cb932d208f0..444c0bc1630e 100644
--- a/nixos/modules/virtualisation/grow-partition.nix
+++ b/nixos/modules/virtualisation/grow-partition.nix
@@ -1,48 +1,3 @@
-# This module automatically grows the root partition on virtual machines.
-# This allows an instance to be created with a bigger root filesystem
-# than provided by the machine image.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-{
-
-  options = {
-
-    virtualisation.growPartition = mkOption {
-      type = types.bool;
-      default = true;
-    };
-
-  };
-
-  config = mkIf config.virtualisation.growPartition {
-
-    boot.initrd.extraUtilsCommands = ''
-      copy_bin_and_libs ${pkgs.gawk}/bin/gawk
-      copy_bin_and_libs ${pkgs.gnused}/bin/sed
-      copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk
-      copy_bin_and_libs ${pkgs.utillinux}/sbin/lsblk
-
-      substitute "${pkgs.cloud-utils}/bin/.growpart-wrapped" "$out/bin/growpart" \
-        --replace "${pkgs.bash}/bin/sh" "/bin/sh" \
-        --replace "awk" "gawk" \
-        --replace "sed" "gnused"
-
-      ln -s sed $out/bin/gnused
-    '';
-
-    boot.initrd.postDeviceCommands = ''
-      rootDevice="${config.fileSystems."/".device}"
-      if [ -e "$rootDevice" ]; then
-        rootDevice="$(readlink -f "$rootDevice")"
-        parentDevice="$(lsblk -npo PKNAME "$rootDevice")"
-        TMPDIR=/run sh $(type -P growpart) "$parentDevice" "''${rootDevice#$parentDevice}"
-        udevadm settle
-      fi
-    '';
-
-  };
-
-}
+# This profile is deprecated, use boot.growPartition directly.
+builtins.trace "the profile <nixos/modules/virtualisation/grow-partition.nix> is deprecated, use boot.growPartition instead"
+{ }
diff --git a/nixos/modules/virtualisation/hyperv-guest.nix b/nixos/modules/virtualisation/hyperv-guest.nix
new file mode 100644
index 000000000000..ecd2a8117710
--- /dev/null
+++ b/nixos/modules/virtualisation/hyperv-guest.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.virtualisation.hypervGuest;
+
+in {
+  options = {
+    virtualisation.hypervGuest = {
+      enable = mkEnableOption "Hyper-V Guest Support";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ config.boot.kernelPackages.hyperv-daemons.bin ];
+
+    security.rngd.enable = false;
+
+    # enable hotadding memory
+    services.udev.packages = lib.singleton (pkgs.writeTextFile {
+      name = "hyperv-memory-hotadd-udev-rules";
+      destination = "/etc/udev/rules.d/99-hyperv-memory-hotadd.rules";
+      text = ''
+        ACTION="add", SUBSYSTEM=="memory", ATTR{state}="online"
+      '';
+    });
+
+    systemd = {
+      packages = [ config.boot.kernelPackages.hyperv-daemons.lib ];
+
+      targets.hyperv-daemons = {
+        wantedBy = [ "multi-user.target" ];
+      };
+    };
+  };
+}
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index 8aa7ad8e3911..64465ae18522 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -37,11 +37,13 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.enableKVM = mkOption {
-      type = types.bool;
-      default = true;
+    virtualisation.libvirtd.qemuPackage = mkOption {
+      type = types.package;
+      default = pkgs.qemu;
       description = ''
-        This option enables support for QEMU/KVM in libvirtd.
+        Qemu package to use with libvirt.
+        `pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86)
+        `pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures.
       '';
     };
 
@@ -102,7 +104,7 @@ in {
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = with pkgs; [ libvirt netcat-openbsd qemu_kvm ];
+    environment.systemPackages = with pkgs; [ libvirt netcat-openbsd cfg.qemuPackage ];
 
     boot.kernelModules = [ "tun" ];
 
@@ -154,9 +156,9 @@ in {
 
         # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs
         mkdir -p /run/libvirt/nix-emulators
-        ln -s --force ${pkgs.libvirt}/libexec/libvirt_lxc /run/libvirt/nix-emulators/
-        ${optionalString pkgs.stdenv.isAarch64 "ln -s --force ${pkgs.qemu}/bin/qemu-system-aarch64 /run/libvirt/nix-emulators/"}
-        ${optionalString cfg.enableKVM         "ln -s --force ${pkgs.qemu_kvm}/bin/qemu-kvm        /run/libvirt/nix-emulators/"}
+        for emulator in ${pkgs.libvirt}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do
+          ln -s --force "$emulator" /run/libvirt/nix-emulators/
+        done
 
         ${optionalString cfg.qemuOvmf ''
             mkdir -p /run/libvirt/nix-ovmf
diff --git a/nixos/modules/virtualisation/lxcfs.nix b/nixos/modules/virtualisation/lxcfs.nix
index 48462dc66da8..b2457403463a 100644
--- a/nixos/modules/virtualisation/lxcfs.nix
+++ b/nixos/modules/virtualisation/lxcfs.nix
@@ -28,13 +28,9 @@ in {
 
   ###### implementation
   config = mkIf cfg.enable {
-    services.cgmanager.enable = true;
-
     systemd.services.lxcfs = {
       description = "FUSE filesystem for LXC";
       wantedBy = [ "multi-user.target" ];
-      requires = [ "cgmanager.service" ];
-      after = [ "cgmanager.service" ];
       before = [ "lxc.service" ];
       restartIfChanged = false;
       serviceConfig = {
diff --git a/nixos/modules/virtualisation/nova-config.nix b/nixos/modules/virtualisation/nova-config.nix
index c865cf451e40..c1d2a314daf2 100644
--- a/nixos/modules/virtualisation/nova-config.nix
+++ b/nixos/modules/virtualisation/nova-config.nix
@@ -6,7 +6,6 @@ with lib;
   imports = [
     ../profiles/qemu-guest.nix
     ../profiles/headless.nix
-    ./grow-partition.nix
   ];
 
   config = {
@@ -15,8 +14,7 @@ with lib;
       autoResize = true;
     };
 
-    virtualisation.growPartition = true;
-
+    boot.growPartition = true;
     boot.kernelParams = [ "console=ttyS0" ];
     boot.loader.grub.device = "/dev/vda";
     boot.loader.timeout = 0;
diff --git a/nixos/modules/virtualisation/nova.nix b/nixos/modules/virtualisation/nova.nix
deleted file mode 100644
index c2837d0e2e24..000000000000
--- a/nixos/modules/virtualisation/nova.nix
+++ /dev/null
@@ -1,174 +0,0 @@
-# Module for Nova, a.k.a. OpenStack Compute.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  cfg = config.virtualisation.nova;
-
-  nova = pkgs.nova;
-
-  novaConf = pkgs.writeText "nova.conf"
-    ''
-      --nodaemon
-      --verbose
-      ${cfg.extraConfig}
-    '';
-
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    virtualisation.nova.enableSingleNode =
-      mkOption {
-        default = false;
-        description =
-          ''
-            This option enables Nova, also known as OpenStack Compute,
-            a cloud computing system, as a single-machine
-            installation.  That is, all of Nova's components are
-            enabled on this machine, using SQLite as Nova's database.
-            This is useful for evaluating and experimenting with Nova.
-            However, for a real cloud computing environment, you'll
-            want to enable some of Nova's services on other machines,
-            and use a database such as MySQL.
-          '';
-      };
-
-    virtualisation.nova.extraConfig =
-      mkOption {
-        default = "";
-        description =
-          ''
-            Additional text appended to <filename>nova.conf</filename>,
-            the main Nova configuration file.
-          '';
-      };
-
-  };
-
-
-  ###### implementation
-
-  config = mkIf cfg.enableSingleNode {
-
-    environment.systemPackages = [ nova pkgs.euca2ools pkgs.novaclient ];
-
-    environment.etc =
-      [ { source = novaConf;
-          target = "nova/nova.conf";
-        }
-      ];
-
-    # Nova requires libvirtd and RabbitMQ.
-    virtualisation.libvirtd.enable = true;
-    services.rabbitmq.enable = true;
-
-    # `qemu-nbd' required the `nbd' kernel module.
-    boot.kernelModules = [ "nbd" ];
-
-    system.activationScripts.nova =
-      ''
-        mkdir -m 755 -p /var/lib/nova
-        mkdir -m 755 -p /var/lib/nova/networks
-        mkdir -m 700 -p /var/lib/nova/instances
-        mkdir -m 700 -p /var/lib/nova/keys
-
-        # Allow the CA certificate generation script (called by
-        # nova-api) to work.
-        mkdir -m 700 -p /var/lib/nova/CA /var/lib/nova/CA/private
-
-        # Initialise the SQLite database.
-        ${nova}/bin/nova-manage db sync
-      '';
-
-    # `nova-api' receives and executes external client requests from
-    # tools such as euca2ools.  It listens on port 8773 (XML) and 8774
-    # (JSON).
-    jobs.nova_api =
-      { name = "nova-api";
-
-        description = "Nova API service";
-
-        startOn = "ip-up";
-
-        # `openssl' is required to generate the CA.  `openssh' is
-        # required to generate key pairs.
-        path = [ pkgs.openssl config.programs.ssh.package pkgs.bash ];
-
-        respawn = false;
-
-        exec = "${nova}/bin/nova-api --flagfile=${novaConf} --api_paste_config=${nova}/etc/nova/api-paste.ini";
-      };
-
-    # `nova-objectstore' is a simple image server.  Useful if you're
-    # not running the OpenStack Imaging Service (Swift).  It serves
-    # images placed in /var/lib/nova/images/.
-    jobs.nova_objectstore =
-      { name = "nova-objectstore";
-
-        description = "Nova Simple Object Store Service";
-
-        startOn = "ip-up";
-
-        preStart =
-          ''
-            mkdir -m 700 -p /var/lib/nova/images
-          '';
-
-        exec = "${nova}/bin/nova-objectstore --flagfile=${novaConf}";
-      };
-
-    # `nova-scheduler' schedules VM execution requests.
-    jobs.nova_scheduler =
-      { name = "nova-scheduler";
-
-        description = "Nova Scheduler Service";
-
-        startOn = "ip-up";
-
-        exec = "${nova}/bin/nova-scheduler --flagfile=${novaConf}";
-      };
-
-    # `nova-compute' starts and manages virtual machines.
-    jobs.nova_compute =
-      { name = "nova-compute";
-
-        description = "Nova Compute Service";
-
-        startOn = "ip-up";
-
-        path =
-          [ pkgs.sudo pkgs.vlan pkgs.nettools pkgs.iptables pkgs.qemu_kvm
-            pkgs.e2fsprogs pkgs.utillinux pkgs.multipath-tools pkgs.iproute
-            pkgs.bridge-utils
-          ];
-
-        exec = "${nova}/bin/nova-compute --flagfile=${novaConf}";
-      };
-
-    # `nova-network' manages networks and allocates IP addresses.
-    jobs.nova_network =
-      { name = "nova-network";
-
-        description = "Nova Network Service";
-
-        startOn = "ip-up";
-
-        path =
-          [ pkgs.sudo pkgs.vlan pkgs.dnsmasq pkgs.nettools pkgs.iptables
-            pkgs.iproute pkgs.bridge-utils pkgs.radvd
-          ];
-
-        exec = "${nova}/bin/nova-network --flagfile=${novaConf}";
-      };
-
-  };
-
-}
diff --git a/nixos/modules/virtualisation/openstack/common.nix b/nixos/modules/virtualisation/openstack/common.nix
deleted file mode 100644
index 2feb0a873951..000000000000
--- a/nixos/modules/virtualisation/openstack/common.nix
+++ /dev/null
@@ -1,84 +0,0 @@
-{ lib }:
-
-with lib;
-
-rec {
-  # A shell script string helper to get the value of a secret at
-  # runtime.
-  getSecret = secretOption:
-    if secretOption.storage == "fromFile"
-    then ''$(cat ${secretOption.value})''
-    else ''${secretOption.value}'';
-
-
-  # A shell script string help to replace at runtime in a file the
-  # pattern of a secret by its value.
-  replaceSecret = secretOption: filename: ''
-    sed -i "s/${secretOption.pattern}/${getSecret secretOption}/g" ${filename}
-    '';
-
-  # This generates an option that can be used to declare secrets which
-  # can be stored in the nix store, or not. A pattern is written in
-  # the nix store to represent the secret. The pattern can
-  # then be overwritten with the value of the secret at runtime.
-  mkSecretOption = {name, description ? ""}:
-    mkOption {
-      description = description;
-      type = types.submodule ({
-        options = {
-          pattern = mkOption {
-            type = types.str;
-            default = "##${name}##";
-            description = "The pattern that represent the secret.";
-            };
-          storage = mkOption {
-            type = types.enum [ "fromNixStore" "fromFile" ];
-            description = ''
-            Choose the way the password is provisionned. If
-            fromNixStore is used, the value is the password and it is
-            written in the nix store. If fromFile is used, the value
-            is a path from where the password will be read at
-            runtime. This is generally used with <link
-            xlink:href="https://nixos.org/nixops/manual/#opt-deployment.keys">
-            deployment keys</link> of Nixops.
-           '';};
-            value = mkOption {
-              type = types.str;
-	      description = ''
-	      If the storage is fromNixStore, the value is the password itself,
-	      otherwise it is a path to the file that contains the password.
-	      '';
-	      };
-            };});
-  };
-  
-  databaseOption = name: {
-    host = mkOption {
-      type = types.str;
-      default = "localhost";
-      description = ''
-        Host of the database.
-      '';
-    };
-
-    name = mkOption {
-      type = types.str;
-      default = name;
-      description = ''
-        Name of the existing database.
-      '';
-    };
-
-    user = mkOption {
-      type = types.str;
-      default = name;
-      description = ''
-        The database user. The user must exist and has access to
-        the specified database.
-      '';
-    };
-    password = mkSecretOption {
-      name = name + "MysqlPassword";
-      description = "The database user's password";};
-  };
-}
diff --git a/nixos/modules/virtualisation/openstack/glance.nix b/nixos/modules/virtualisation/openstack/glance.nix
deleted file mode 100644
index 7862409a65ec..000000000000
--- a/nixos/modules/virtualisation/openstack/glance.nix
+++ /dev/null
@@ -1,245 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib; with import ./common.nix {inherit lib;};
-
-let
-  cfg = config.virtualisation.openstack.glance;
-  commonConf = ''
-    [database]
-    connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}"
-    notification_driver = noop
-
-    [keystone_authtoken]
-    auth_url = ${cfg.authUrl}
-    auth_plugin = password
-    project_name = service
-    project_domain_id = default
-    user_domain_id = default
-    username = ${cfg.serviceUsername}
-    password = ${cfg.servicePassword.pattern}
-
-    [glance_store]
-    default_store = file
-    filesystem_store_datadir = /var/lib/glance/images/
-  '';
-  glanceApiConfTpl = pkgs.writeText "glance-api.conf" ''
-    ${commonConf}
-
-    [paste_deploy]
-    flavor = keystone
-    config_file = ${cfg.package}/etc/glance-api-paste.ini
-  '';
-  glanceRegistryConfTpl = pkgs.writeText "glance-registry.conf" ''
-    ${commonConf}
-
-    [paste_deploy]
-    config_file = ${cfg.package}/etc/glance-registry-paste.ini
-  '';
-  glanceApiConf = "/var/lib/glance/glance-api.conf";
-  glanceRegistryConf = "/var/lib/glance/glance-registry.conf";
-
-in {
-  options.virtualisation.openstack.glance = {
-    package = mkOption {
-      type = types.package;
-      default = pkgs.glance;
-      defaultText = "pkgs.glance";
-      description = ''
-        Glance package to use.
-      '';
-    };
-
-    enable = mkOption {
-      default = false;
-      type = types.bool;
-      description = ''
-        This option enables Glance as a single-machine
-        installation. That is, all of Glance's components are
-        enabled on this machine. This is useful for evaluating and
-        experimenting with Glance. Note we are currently not
-        providing any configurations for a multi-node setup.
-      '';
-    };
-
-    authUrl = mkOption {
-      type = types.str;
-      default = http://localhost:5000;
-      description = ''
-        Complete public Identity (Keystone) API endpoint. Note this is
-        unversionned.
-      '';
-    };
-
-    serviceUsername = mkOption {
-      type = types.str;
-      default = "glance";
-      description = ''
-        The Glance service username. This user is created if bootstrap
-        is enable, otherwise it has to be manually created before
-        starting this service.
-      '';
-    };
-
-    servicePassword = mkSecretOption {
-      name = "glanceAdminPassword";
-      description = ''
-        The Glance service user's password.
-      '';
-    };
-
-    database = databaseOption "glance";
-
-    bootstrap = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Bootstrap the Glance service by creating the service tenant,
-          an admin account and a public endpoint. This option provides
-          a ready-to-use glance service. This is only done at the
-          first Glance execution by the systemd post start section.
-          The keystone admin account is used to create required
-          Keystone resource for the Glance service.
-
-          <note><para> This option is a helper for setting up
-          development or testing environments.</para></note>
-        '';
-      };
-
-      endpointPublic = mkOption {
-        type = types.str;
-        default = "http://localhost:9292";
-        description = ''
-          The public image endpoint. The link <link
-          xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html">
-          create endpoint</link> provides more informations
-          about that.
-        '';
-      };
-
-      keystoneAdminUsername = mkOption {
-        type = types.str;
-        default = "admin";
-        description = ''
-          The keystone admin user name used to create the Glance account.
-        '';
-      };
-
-      keystoneAdminPassword = mkSecretOption {
-        name = "keystoneAdminPassword";
-        description = ''
-          The keystone admin user's password.
-        '';
-      };
-
-      keystoneAdminTenant = mkOption {
-        type = types.str;
-        default = "admin";
-        description = ''
-          The keystone admin tenant used to create the Glance account.
-        '';
-      };
-      keystoneAuthUrl = mkOption {
-        type = types.str;
-        default = "http://localhost:5000/v2.0";
-        description = ''
-          The keystone auth url used to create the Glance account.
-        '';
-      };
-    };
-  };
-
-  config = mkIf cfg.enable {
-    users.extraUsers = [{
-      name = "glance";
-      group = "glance";
-      uid = config.ids.gids.glance;
-
-    }];
-    users.extraGroups = [{
-      name = "glance";
-      gid = config.ids.gids.glance;
-    }];
-
-    systemd.services.glance-registry = {
-      description = "OpenStack Glance Registry Daemon";
-      after = [ "network.target"];
-      path = [ pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ];
-      wantedBy = [ "multi-user.target" ];
-      preStart = ''
-        mkdir -m 775 -p /var/lib/glance/{images,scrubber,image_cache}
-        chown glance:glance /var/lib/glance/{images,scrubber,image_cache}
-
-        # Secret file managment
-        cp ${glanceRegistryConfTpl} ${glanceRegistryConf};
-        chown glance:glance ${glanceRegistryConf};
-        chmod 640 ${glanceRegistryConf}
-        ${replaceSecret cfg.database.password glanceRegistryConf}
-        ${replaceSecret cfg.servicePassword glanceRegistryConf}
-
-        cp ${glanceApiConfTpl} ${glanceApiConf};
-        chown glance:glance ${glanceApiConf};
-        chmod 640 ${glanceApiConf}
-        ${replaceSecret cfg.database.password glanceApiConf}
-        ${replaceSecret cfg.servicePassword glanceApiConf}
-
-        # Initialise the database
-        ${cfg.package}/bin/glance-manage --config-file=${glanceApiConf} --config-file=${glanceRegistryConf} db_sync
-      '';
-      postStart = ''
-        set -eu
-        export OS_AUTH_URL=${cfg.bootstrap.keystoneAuthUrl}
-        export OS_USERNAME=${cfg.bootstrap.keystoneAdminUsername}
-        export OS_PASSWORD=${getSecret cfg.bootstrap.keystoneAdminPassword}
-        export OS_TENANT_NAME=${cfg.bootstrap.keystoneAdminTenant}
-
-        # Wait until the keystone is available for use
-        count=0
-        while ! keystone user-get ${cfg.bootstrap.keystoneAdminUsername} > /dev/null
-        do
-            if [ $count -eq 30 ]
-            then
-                echo "Tried 30 times, giving up..."
-                exit 1
-            fi
-
-            echo "Keystone not yet started. Waiting for 1 second..."
-            count=$((count++))
-            sleep 1
-        done
-
-        # If the service glance doesn't exist, we consider glance is
-        # not initialized
-        if ! keystone service-get glance
-        then
-            keystone service-create --type image --name glance
-            ID=$(keystone service-get glance | awk '/ id / { print $4 }')
-            keystone endpoint-create --region RegionOne --service $ID --internalurl http://localhost:9292 --adminurl http://localhost:9292 --publicurl ${cfg.bootstrap.endpointPublic}
-
-            keystone user-create --name ${cfg.serviceUsername} --tenant service --pass ${getSecret cfg.servicePassword}
-            keystone user-role-add --tenant service --user ${cfg.serviceUsername} --role admin
-        fi
-        '';
-      serviceConfig = {
-        PermissionsStartOnly = true; # preStart must be run as root
-        TimeoutStartSec = "600"; # 10min for initial db migrations
-        User = "glance";
-        Group = "glance";
-        ExecStart = "${cfg.package}/bin/glance-registry --config-file=${glanceRegistryConf}";
-      };
-    };
-    systemd.services.glance-api = {
-      description = "OpenStack Glance API Daemon";
-      after = [ "glance-registry.service" "network.target"];
-      requires = [ "glance-registry.service" "network.target"]; 
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        PermissionsStartOnly = true; # preStart must be run as root
-        User = "glance";
-        Group = "glance";
-        ExecStart = "${cfg.package}/bin/glance-api --config-file=${glanceApiConf}";
-      };
-    };
-  };
-
-}
diff --git a/nixos/modules/virtualisation/openstack/keystone.nix b/nixos/modules/virtualisation/openstack/keystone.nix
deleted file mode 100644
index e32c5a4cae1b..000000000000
--- a/nixos/modules/virtualisation/openstack/keystone.nix
+++ /dev/null
@@ -1,220 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib; with import ./common.nix {inherit lib;};
-
-let
-  cfg = config.virtualisation.openstack.keystone;
-  keystoneConfTpl = pkgs.writeText "keystone.conf" ''
-    [DEFAULT]
-    admin_token = ${cfg.adminToken.pattern}
-    policy_file=${cfg.package}/etc/policy.json
-
-    [database]
-
-    connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}"
-
-    [paste_deploy]
-    config_file = ${cfg.package}/etc/keystone-paste.ini
-
-    ${cfg.extraConfig}
-  '';
-  keystoneConf = "/var/lib/keystone/keystone.conf";
-
-in {
-  options.virtualisation.openstack.keystone = {
-    package = mkOption {
-      type = types.package;
-      example = literalExample "pkgs.keystone";
-      description = ''
-        Keystone package to use.
-      '';
-    };
-
-    enable = mkOption {
-      default = false;
-      type = types.bool;
-      description = ''
-        Enable Keystone, the OpenStack Identity Service
-      '';
-    };
-
-    extraConfig = mkOption {
-      default = "";
-      type = types.lines;
-      description = ''
-        Additional text appended to <filename>keystone.conf</filename>,
-        the main Keystone configuration file.
-      '';
-    };
-
-    adminToken = mkSecretOption {
-      name = "adminToken";
-      description = ''
-        This is the admin token used to boostrap keystone,
-        ie. to provision first resources.
-      '';
-    };
-
-    bootstrap = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Bootstrap the Keystone service by creating the service
-          tenant, an admin account and a public endpoint. This options
-          provides a ready-to-use admin account. This is only done at
-          the first Keystone execution by the systemd post start.
-
-          Note this option is a helper for setting up development or
-          testing environments.
-        '';
-      };
-
-      endpointPublic = mkOption {
-        type = types.str;
-        default = "http://localhost:5000/v2.0";
-        description = ''
-          The public identity endpoint. The link <link
-          xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html">
-          create keystone endpoint</link> provides more informations
-          about that.
-        '';
-      };
-
-      adminUsername = mkOption {
-        type = types.str;
-        default = "admin";
-        description = ''
-          A keystone admin username.
-        '';
-      };
-
-      adminPassword = mkSecretOption {
-        name = "keystoneAdminPassword";
-        description = ''
-          The keystone admin user's password.
-        '';
-      };
-
-      adminTenant = mkOption {
-        type = types.str;
-        default = "admin";
-        description = ''
-          A keystone admin tenant name.
-        '';
-      };
-    };
-
-    database = {
-      host = mkOption {
-        type = types.str;
-        default = "localhost";
-        description = ''
-          Host of the database.
-        '';
-      };
-
-      name = mkOption {
-        type = types.str;
-        default = "keystone";
-        description = ''
-          Name of the existing database.
-        '';
-      };
-
-      user = mkOption {
-        type = types.str;
-        default = "keystone";
-        description = ''
-          The database user. The user must exist and has access to
-          the specified database.
-        '';
-      };
-      password = mkSecretOption {
-        name = "mysqlPassword";
-        description = "The database user's password";};
-    };
-  };
-
-  config = mkIf cfg.enable {
-    # Note: when changing the default, make it conditional on
-    # ‘system.stateVersion’ to maintain compatibility with existing
-    # systems!
-    virtualisation.openstack.keystone.package = mkDefault pkgs.keystone;
-
-    users.extraUsers = [{
-      name = "keystone";
-      group = "keystone";
-      uid = config.ids.uids.keystone;
-    }];
-    users.extraGroups = [{
-      name = "keystone";
-      gid = config.ids.gids.keystone;
-    }];
-
-    systemd.services.keystone-all = {
-        description = "OpenStack Keystone Daemon";
-        after = [ "network.target"];
-        path = [ cfg.package pkgs.mysql pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ];
-        wantedBy = [ "multi-user.target" ];
-        preStart = ''
-          mkdir -m 755 -p /var/lib/keystone
-
-          cp ${keystoneConfTpl} ${keystoneConf};
-          chown keystone:keystone ${keystoneConf};
-          chmod 640 ${keystoneConf}
-
-          ${replaceSecret cfg.database.password keystoneConf}
-          ${replaceSecret cfg.adminToken keystoneConf}
-
-          # Initialise the database
-          ${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} db_sync
-          # Set up the keystone's PKI infrastructure
-          ${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} pki_setup --keystone-user keystone --keystone-group keystone
-        '';
-        postStart = optionalString cfg.bootstrap.enable ''
-          set -eu
-          # Wait until the keystone is available for use
-          count=0
-          while ! curl --fail -s  http://localhost:35357/v2.0 > /dev/null 
-          do
-              if [ $count -eq 30 ]
-              then
-                  echo "Tried 30 times, giving up..."
-                  exit 1
-              fi
-
-              echo "Keystone not yet started. Waiting for 1 second..."
-              count=$((count++))
-              sleep 1
-          done
-
-          # We use the service token to create a first admin user
-          export OS_SERVICE_ENDPOINT=http://localhost:35357/v2.0
-          export OS_SERVICE_TOKEN=${getSecret cfg.adminToken}
-
-          # If the tenant service doesn't exist, we consider
-          # keystone is not initialized
-          if ! keystone tenant-get service
-          then
-              keystone tenant-create --name service
-              keystone tenant-create --name ${cfg.bootstrap.adminTenant}
-              keystone user-create --name ${cfg.bootstrap.adminUsername} --tenant ${cfg.bootstrap.adminTenant} --pass ${getSecret cfg.bootstrap.adminPassword}
-              keystone role-create --name admin
-              keystone role-create --name Member
-              keystone user-role-add --tenant ${cfg.bootstrap.adminTenant} --user ${cfg.bootstrap.adminUsername} --role admin
-              keystone service-create --type identity --name keystone
-              ID=$(keystone service-get keystone | awk '/ id / { print $4 }')
-              keystone endpoint-create --region RegionOne --service $ID --publicurl ${cfg.bootstrap.endpointPublic} --adminurl http://localhost:35357/v2.0 --internalurl http://localhost:5000/v2.0
-          fi
-        '';
-        serviceConfig = {
-          PermissionsStartOnly = true; # preStart must be run as root
-          TimeoutStartSec = "600"; # 10min for initial db migrations
-          User = "keystone";
-          Group = "keystone";
-          ExecStart = "${cfg.package}/bin/keystone-all --config-file=${keystoneConf}";
-        };
-      };
-  };
-}
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 770e5fb848a9..26f7945a4eda 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -18,7 +18,7 @@ let
     "i686-linux" = "${qemu}/bin/qemu-kvm";
     "x86_64-linux" = "${qemu}/bin/qemu-kvm -cpu kvm64";
     "armv7l-linux" = "${qemu}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
-    "aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt -cpu host";
+    "aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
   }.${pkgs.stdenv.system};
 
   # FIXME: figure out a common place for this instead of copy pasting
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index d68b3bb73904..00381c426d23 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -8,8 +8,6 @@ let
 
 in {
 
-  imports = [ ./grow-partition.nix ];
-
   options = {
     virtualbox = {
       baseImageSize = mkOption {
@@ -23,7 +21,6 @@ in {
   };
 
   config = {
-
     system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix {
       name = "nixos-ova-${config.system.nixosLabel}-${pkgs.stdenv.system}";
 
@@ -71,6 +68,7 @@ in {
       autoResize = true;
     };
 
+    boot.growPartition = true;
     boot.loader.grub.device = "/dev/sda";
 
     virtualisation.virtualbox.guest.enable = true;
diff --git a/nixos/release.nix b/nixos/release.nix
index bb6a73eb68ec..3dd670c30bad 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -1,6 +1,6 @@
 { nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; }
 , stableBranch ? false
-, supportedSystems ? [ "x86_64-linux" ]
+, supportedSystems ? [ "x86_64-linux" "aarch64-linux" ]
 }:
 
 with import ../lib;
@@ -89,6 +89,27 @@ let
       });
   }).config));
 
+  makeNetboot = config:
+    let
+      config_evaled = import lib/eval-config.nix config;
+      build = config_evaled.config.system.build;
+      kernelTarget = config_evaled.pkgs.stdenv.platform.kernelTarget;
+    in
+      pkgs.symlinkJoin {
+        name="netboot";
+        paths=[
+          build.netbootRamdisk
+          build.kernel
+          build.netbootIpxeScript
+        ];
+        postBuild = ''
+          mkdir -p $out/nix-support
+          echo "file ${kernelTarget} $out/${kernelTarget}" >> $out/nix-support/hydra-build-products
+          echo "file initrd $out/initrd" >> $out/nix-support/hydra-build-products
+          echo "file ipxe $out/netboot.ipxe" >> $out/nix-support/hydra-build-products
+        '';
+      };
+
 
 in rec {
 
@@ -103,28 +124,22 @@ in rec {
   # Build the initial ramdisk so Hydra can keep track of its size over time.
   initialRamdisk = buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.initialRamdisk);
 
-  netboot.x86_64-linux = let build = (import lib/eval-config.nix {
+  netboot = {
+    x86_64-linux = makeNetboot {
       system = "x86_64-linux";
       modules = [
         ./modules/installer/netboot/netboot-minimal.nix
         versionModule
       ];
-    }).config.system.build;
-  in
-    pkgs.symlinkJoin {
-      name="netboot";
-      paths=[
-        build.netbootRamdisk
-        build.kernel
-        build.netbootIpxeScript
-      ];
-      postBuild = ''
-        mkdir -p $out/nix-support
-        echo "file bzImage $out/bzImage" >> $out/nix-support/hydra-build-products
-        echo "file initrd $out/initrd" >> $out/nix-support/hydra-build-products
-        echo "file ipxe $out/netboot.ipxe" >> $out/nix-support/hydra-build-products
-      '';
     };
+  } // (optionalAttrs (elem "aarch64-linux" supportedSystems) {
+    aarch64-linux = makeNetboot {
+      system = "aarch64-linux";
+      modules = [
+        ./modules/installer/netboot/netboot-minimal.nix
+        versionModule
+      ];
+    };});
 
   iso_minimal = forAllSystems (system: makeIso {
     module = ./modules/installer/cd-dvd/installation-cd-minimal.nix;
@@ -217,6 +232,7 @@ in rec {
   tests.atd = callTest tests/atd.nix {};
   tests.acme = callTest tests/acme.nix {};
   tests.avahi = callTest tests/avahi.nix {};
+  tests.beegfs = callTest tests/beegfs.nix {};
   tests.bittorrent = callTest tests/bittorrent.nix {};
   tests.blivet = callTest tests/blivet.nix {};
   tests.boot = callSubTests tests/boot.nix {};
@@ -252,7 +268,6 @@ in rec {
   tests.fleet = hydraJob (import tests/fleet.nix { system = "x86_64-linux"; });
   #tests.gitlab = callTest tests/gitlab.nix {};
   tests.gitolite = callTest tests/gitolite.nix {};
-  tests.glance = callTest tests/glance.nix {};
   tests.gocd-agent = callTest tests/gocd-agent.nix {};
   tests.gocd-server = callTest tests/gocd-server.nix {};
   tests.gnome3 = callTest tests/gnome3.nix {};
@@ -279,7 +294,6 @@ in rec {
   tests.kernel-copperhead = callTest tests/kernel-copperhead.nix {};
   tests.kernel-latest = callTest tests/kernel-latest.nix {};
   tests.kernel-lts = callTest tests/kernel-lts.nix {};
-  tests.keystone = callTest tests/keystone.nix {};
   tests.kubernetes = hydraJob (import tests/kubernetes/default.nix { system = "x86_64-linux"; });
   tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; };
   tests.ldap = callTest tests/ldap.nix {};
@@ -333,10 +347,12 @@ in rec {
   tests.slim = callTest tests/slim.nix {};
   tests.smokeping = callTest tests/smokeping.nix {};
   tests.snapper = callTest tests/snapper.nix {};
+  tests.statsd = callTest tests/statsd.nix {};
   tests.switchTest = callTest tests/switch-test.nix {};
   tests.taskserver = callTest tests/taskserver.nix {};
   tests.tomcat = callTest tests/tomcat.nix {};
   tests.udisks2 = callTest tests/udisks2.nix {};
+  tests.vault = callTest tests/vault.nix {};
   tests.virtualbox = callSubTests tests/virtualbox.nix { system = "x86_64-linux"; };
   tests.wordpress = callTest tests/wordpress.nix {};
   tests.xfce = callTest tests/xfce.nix {};
diff --git a/nixos/tests/beegfs.nix b/nixos/tests/beegfs.nix
new file mode 100644
index 000000000000..433910feafe3
--- /dev/null
+++ b/nixos/tests/beegfs.nix
@@ -0,0 +1,115 @@
+import ./make-test.nix ({ pkgs, ... } :
+
+let
+  connAuthFile="beegfs/auth-def.key";
+
+  client = { config, pkgs, lib, ... } : {
+    networking.firewall.enable = false;
+    services.beegfsEnable = true;
+    services.beegfs.default = {
+      mgmtdHost = "mgmt";
+      connAuthFile = "/etc/${connAuthFile}";
+      client = {
+        mount = false;
+        enable = true;
+      };
+    };
+
+    fileSystems = pkgs.lib.mkVMOverride # FIXME: this should be creatd by the module
+      [ { mountPoint = "/beegfs";
+          device = "default";
+          fsType = "beegfs";
+          options = [ "cfgFile=/etc/beegfs/client-default.conf" "_netdev" ];
+        }
+      ];
+
+    environment.etc."${connAuthFile}" = {
+      enable = true;
+      text = "ThisIsALousySecret";
+      mode = "0600";
+    };
+  };
+
+
+  server = service : { config, pkgs, lib, ... } : {
+    networking.firewall.enable = false;
+    boot.initrd.postDeviceCommands = ''
+      ${pkgs.e2fsprogs}/bin/mkfs.ext4 -L data /dev/vdb
+    '';
+
+    virtualisation.emptyDiskImages = [ 4096 ];
+
+    fileSystems = pkgs.lib.mkVMOverride
+      [ { mountPoint = "/data";
+          device = "/dev/disk/by-label/data";
+          fsType = "ext4";
+        }
+      ];
+
+    environment.systemPackages = with pkgs; [ beegfs ];
+    environment.etc."${connAuthFile}" = {
+      enable = true;
+      text = "ThisIsALousySecret";
+      mode = "0600";
+    };
+
+    services.beegfsEnable = true;
+    services.beegfs.default = {
+      mgmtdHost = "mgmt";
+      connAuthFile = "/etc/${connAuthFile}";
+      "${service}" = {
+        enable = true;
+        storeDir = "/data";
+      };
+    };
+  };
+
+in
+{
+  name = "beegfs";
+
+  nodes = {
+    meta = server "meta";
+    mgmt = server "mgmtd";
+    storage1 = server "storage";
+    storage2 = server "storage";
+    client1 = client;
+    client2 = client;
+  };
+
+  testScript = ''
+    # Initalize the data directories
+    $mgmt->waitForUnit("default.target");
+    $mgmt->succeed("beegfs-setup-mgmtd -C -f -p /data");
+    $mgmt->succeed("systemctl start beegfs-mgmtd-default");
+
+    $meta->waitForUnit("default.target");
+    $meta->succeed("beegfs-setup-meta -C -f -s 1 -p /data");
+    $meta->succeed("systemctl start beegfs-meta-default");
+
+    $storage1->waitForUnit("default.target");
+    $storage1->succeed("beegfs-setup-storage -C -f -s 1 -i 1 -p /data");
+    $storage1->succeed("systemctl start beegfs-storage-default");
+
+    $storage2->waitForUnit("default.target");
+    $storage2->succeed("beegfs-setup-storage -C -f -s 2 -i 2 -p /data");
+    $storage2->succeed("systemctl start beegfs-storage-default");
+
+    #
+
+    # Basic test
+    $client1->waitForUnit("beegfs.mount");
+    $client1->succeed("beegfs-check-servers-default");
+    $client1->succeed("echo test > /beegfs/test");
+    $client2->waitForUnit("beegfs.mount");
+    $client2->succeed("test -e /beegfs/test");
+    $client2->succeed("cat /beegfs/test | grep test");
+
+    # test raid0/stripping
+    $client1->succeed("dd if=/dev/urandom bs=1M count=10 of=/beegfs/striped");
+    $client2->succeed("cat /beegfs/striped > /dev/null");
+
+    # check if fs is still healthy
+    $client1->succeed("beegfs-fsck-default --checkfs");
+  '';
+})
diff --git a/nixos/tests/glance.nix b/nixos/tests/glance.nix
deleted file mode 100644
index 992b77227a4b..000000000000
--- a/nixos/tests/glance.nix
+++ /dev/null
@@ -1,77 +0,0 @@
-{ system ? builtins.currentSystem }:
-
-with import ../lib/testing.nix { inherit system; };
-with pkgs.lib;
-
-let
-  glanceMysqlPassword = "glanceMysqlPassword";
-  glanceAdminPassword = "glanceAdminPassword";
-
-  createDb = pkgs.writeText "db-provisionning.sql" ''
-    create database keystone;
-    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';
-    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';
-
-    create database glance;
-    GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY '${glanceMysqlPassword}';
-    GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY '${glanceMysqlPassword}';
-  '';
-
-  image =
-    (import ../lib/eval-config.nix {
-      inherit system;
-      modules = [ ../../nixos/modules/virtualisation/nova-image.nix ];
-    }).config.system.build.novaImage;
-
-  # The admin keystone account
-  adminOpenstackCmd = "OS_TENANT_NAME=admin OS_USERNAME=admin OS_PASSWORD=keystone OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack";
-
-in makeTest {
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ lewo ];
-  };
-  machine =
-    { config, pkgs, ... }:
-    {
-      services.mysql.enable = true;
-      services.mysql.package = pkgs.mysql;
-      services.mysql.initialScript = createDb;
-
-      virtualisation = {
-        openstack.keystone = {
-          enable = true;
-          database.password = { value = "keystone"; storage = "fromNixStore"; };
-          adminToken = { value = "adminToken"; storage = "fromNixStore"; };
-          bootstrap.enable = true;
-          bootstrap.adminPassword = { value = "keystone"; storage = "fromNixStore"; };
-        };
-
-        openstack.glance = {
-          enable = true;
-          database.password = { value = glanceMysqlPassword; storage = "fromNixStore"; };
-          servicePassword = { value = glanceAdminPassword; storage = "fromNixStore"; };
-
-          bootstrap = {
-            enable = true;
-            keystoneAdminPassword = { value = "keystone"; storage = "fromNixStore"; };
-          };
-        };
-
-        memorySize = 2096;
-        diskSize = 4 * 1024;
-        };
-
-      environment.systemPackages = with pkgs.pythonPackages; with pkgs; [
-        openstackclient
-      ];
-    };
-
-  testScript =
-    ''
-     $machine->waitForUnit("glance-api.service");
-
-     # Since Glance api can take time to start, we retry until success
-     $machine->waitUntilSucceeds("${adminOpenstackCmd} image create nixos --file ${image}/nixos.img --disk-format qcow2 --container-format bare --public");
-     $machine->succeed("${adminOpenstackCmd} image list") =~ /nixos/ or die;
-    '';
-}
diff --git a/nixos/tests/jenkins.nix b/nixos/tests/jenkins.nix
index a9833058f378..ed55b2ff5871 100644
--- a/nixos/tests/jenkins.nix
+++ b/nixos/tests/jenkins.nix
@@ -36,6 +36,9 @@ import ./make-test.nix ({ pkgs, ...} : {
     startAll;
 
     $master->waitForUnit("jenkins");
+
+    $master->mustSucceed("curl http://localhost:8080 | grep 'Authentication required'");
+
     print $master->execute("sudo -u jenkins groups");
     $master->mustSucceed("sudo -u jenkins groups | grep jenkins | grep users");
 
@@ -44,4 +47,4 @@ import ./make-test.nix ({ pkgs, ...} : {
 
     $slave->mustFail("systemctl is-enabled jenkins.service");
   '';
-})
\ No newline at end of file
+})
diff --git a/nixos/tests/keystone.nix b/nixos/tests/keystone.nix
deleted file mode 100644
index 358e352f776f..000000000000
--- a/nixos/tests/keystone.nix
+++ /dev/null
@@ -1,82 +0,0 @@
-{ system ? builtins.currentSystem }:
-
-with import ../lib/testing.nix { inherit system; };
-with pkgs.lib;
-
-let
-  keystoneMysqlPassword = "keystoneMysqlPassword";
-  keystoneMysqlPasswordFile = "/var/run/keystoneMysqlPassword";
-  keystoneAdminPassword = "keystoneAdminPassword";
-
-  createKeystoneDb = pkgs.writeText "create-keystone-db.sql" ''
-    create database keystone;
-    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY '${keystoneMysqlPassword}';
-    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY '${keystoneMysqlPassword}';
-  '';
-  # The admin keystone account
-  adminOpenstackCmd = "OS_TENANT_NAME=admin OS_USERNAME=admin OS_PASSWORD=${keystoneAdminPassword} OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack";
-  # The created demo keystone account
-  demoOpenstackCmd = "OS_TENANT_NAME=demo OS_USERNAME=demo OS_PASSWORD=demo OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack";
-
-in makeTest {
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ lewo ];
-  };
-  machine =
-    { config, pkgs, ... }:
-    {
-      # This is to simulate nixops deployment process.
-      # https://nixos.org/nixops/manual/#opt-deployment.keys
-      boot.postBootCommands = "echo ${keystoneMysqlPassword} > ${keystoneMysqlPasswordFile}";
-
-      services.mysql.enable = true;
-      services.mysql.initialScript = createKeystoneDb;
-
-      virtualisation = {
-
-        openstack.keystone = {
-	  enable = true;
-	  # Check if we can get the secret from a file
-	  database.password = {
-	    value = keystoneMysqlPasswordFile;
-	    storage = "fromFile";
-	  };
-	  adminToken = {
-	    value = "adminToken";
-	    storage = "fromNixStore";
-	  };
-
-	  bootstrap.enable = true;
-	  # Check if we can get the secret from the store
-	  bootstrap.adminPassword = {
-	    value = keystoneAdminPassword;
-	    storage = "fromNixStore";
-	  };
-	};
-
-        memorySize = 2096;
-        diskSize = 4 * 1024;
-	};
-
-      environment.systemPackages = with pkgs.pythonPackages; with pkgs; [
-        openstackclient
-      ];
-    };
-
-  testScript =
-    ''
-     $machine->waitForUnit("keystone-all.service");
-
-     # Verify that admin ccount is working
-     $machine->succeed("${adminOpenstackCmd} token issue");
-
-     # Try to create a new user
-     $machine->succeed("${adminOpenstackCmd} project create --domain default --description 'Demo Project' demo");
-     $machine->succeed("${adminOpenstackCmd} user create --domain default --password demo demo");
-     $machine->succeed("${adminOpenstackCmd} role create user");
-     $machine->succeed("${adminOpenstackCmd} role add --project demo --user demo user");
-
-     # Verify this new account is working
-     $machine->succeed("${demoOpenstackCmd} token issue");
-    '';
-}
diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix
index e44e5bf11d33..2d3ecaf94cfa 100644
--- a/nixos/tests/printing.nix
+++ b/nixos/tests/printing.nix
@@ -39,7 +39,7 @@ import ./make-test.nix ({pkgs, ... }: {
       $client->waitForUnit("cups.service");
       $client->sleep(10); # wait until cups is fully initialized
       $client->succeed("lpstat -r") =~ /scheduler is running/ or die;
-      $client->succeed("lpstat -H") =~ "/var/run/cups/cups.sock" or die;
+      $client->succeed("lpstat -H") =~ "localhost:631" or die;
       $client->succeed("curl --fail http://localhost:631/");
       $client->succeed("curl --fail http://server:631/");
       $server->fail("curl --fail --connect-timeout 2  http://client:631/");
diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix
index f694fc75ef77..8ac0639c6a8c 100644
--- a/nixos/tests/radicale.nix
+++ b/nixos/tests/radicale.nix
@@ -20,7 +20,7 @@ let
       '';
     };
     # WARNING: DON'T DO THIS IN PRODUCTION!
-    # This puts secrets (albeit hashed) directly into the Nix store for ease of testing.
+    # This puts unhashed secrets directly into the Nix store for ease of testing.
     environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} ''
       ${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
     '';
diff --git a/nixos/tests/statsd.nix b/nixos/tests/statsd.nix
new file mode 100644
index 000000000000..d6bbc3901630
--- /dev/null
+++ b/nixos/tests/statsd.nix
@@ -0,0 +1,40 @@
+import ./make-test.nix ({ pkgs, lib }:
+
+with lib;
+
+{
+  name = "statsd";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ ma27 ];
+  };
+
+  nodes.statsd1 = {
+    services.statsd.enable = true;
+    services.statsd.backends = [ "statsd-influxdb-backend" "console" ];
+    services.statsd.extraConfig = ''
+      influxdb: {
+        username: "root",
+        password: "root",
+        database: "statsd"
+      }
+    '';
+
+    services.influxdb.enable = true;
+
+    systemd.services.influx-init = {
+      description = "Setup Influx Test Base";
+      after = [ "influxdb.service" ];
+      before = [ "statsd.service" ];
+
+      script = ''
+        echo "CREATE DATABASE statsd" | ${pkgs.influxdb}/bin/influx
+      '';
+    };
+  };
+
+  testScript = ''
+    $statsd1->start();
+    $statsd1->waitForUnit("statsd.service");
+    $statsd1->succeed("nc -z 127.0.0.1 8126");
+  '';
+})
diff --git a/nixos/tests/vault.nix b/nixos/tests/vault.nix
new file mode 100644
index 000000000000..2c08d06f286b
--- /dev/null
+++ b/nixos/tests/vault.nix
@@ -0,0 +1,23 @@
+import ./make-test.nix ({ pkgs, ... }:
+{
+  name = "vault";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ lnl7 ];
+  };
+  machine = { config, pkgs, ... }: {
+    environment.systemPackages = [ pkgs.vault ];
+    environment.variables.VAULT_ADDR = "http://127.0.0.1:8200";
+    services.vault.enable = true;
+  };
+
+  testScript =
+    ''
+      startAll;
+
+      $machine->waitForUnit('multi-user.target');
+      $machine->waitForUnit('vault.service');
+      $machine->waitForOpenPort(8200);
+      $machine->succeed('vault init');
+      $machine->succeed('vault status | grep "Sealed: true"');
+    '';
+})
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index c519d7dae8be..5574293ba377 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -109,9 +109,6 @@ let
   } ''
     ${pkgs.parted}/sbin/parted --script /dev/vda mklabel msdos
     ${pkgs.parted}/sbin/parted --script /dev/vda -- mkpart primary ext2 1M -1s
-    . /sys/class/block/vda1/uevent
-    mknod /dev/vda1 b $MAJOR $MINOR
-
     ${pkgs.e2fsprogs}/sbin/mkfs.ext4 /dev/vda1
     ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1
     mkdir /mnt