about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/installation/installing.xml7
-rw-r--r--nixos/doc/manual/manual.xml4
-rw-r--r--nixos/doc/manual/release-notes/rl-1809.xml48
-rw-r--r--nixos/lib/make-ext4-fs.nix7
-rw-r--r--nixos/lib/qemu-flags.nix8
-rw-r--r--nixos/modules/config/users-groups.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix11
-rw-r--r--nixos/modules/installer/netboot/netboot.nix3
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/module-list.nix5
-rw-r--r--nixos/modules/profiles/all-hardware.nix2
-rw-r--r--nixos/modules/profiles/installation-device.nix3
-rw-r--r--nixos/modules/programs/zsh/zsh.nix15
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/services/desktops/accountsservice.nix10
-rw-r--r--nixos/modules/services/desktops/geoclue2.nix39
-rw-r--r--nixos/modules/services/desktops/zeitgeist.nix26
-rw-r--r--nixos/modules/services/development/jupyter/default.nix184
-rw-r--r--nixos/modules/services/development/jupyter/kernel-options.nix60
-rw-r--r--nixos/modules/services/games/terraria.nix16
-rw-r--r--nixos/modules/services/hardware/thermald.nix36
-rw-r--r--nixos/modules/services/hardware/undervolt.nix134
-rw-r--r--nixos/modules/services/logging/logstash.nix43
-rw-r--r--nixos/modules/services/logging/syslog-ng.nix2
-rw-r--r--nixos/modules/services/misc/gitea.nix11
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/misc/redmine.nix294
-rw-r--r--nixos/modules/services/misc/synergy.nix12
-rw-r--r--nixos/modules/services/monitoring/datadog-agent.nix236
-rw-r--r--nixos/modules/services/monitoring/dd-agent/dd-agent.nix80
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix10
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix5
-rw-r--r--nixos/modules/services/networking/iwd.nix9
-rw-r--r--nixos/modules/services/search/elasticsearch-curator.nix93
-rw-r--r--nixos/modules/services/search/elasticsearch.nix63
-rw-r--r--nixos/modules/services/search/kibana.nix38
-rw-r--r--nixos/modules/services/security/cfssl.nix4
-rw-r--r--nixos/modules/services/system/localtime.nix10
-rw-r--r--nixos/modules/services/web-servers/hydron.nix12
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/lightdm.nix7
-rw-r--r--nixos/modules/services/x11/redshift.nix3
-rw-r--r--nixos/modules/system/activation/top-level.nix6
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir.nix2
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix2
-rw-r--r--nixos/modules/system/boot/networkd.nix189
-rw-r--r--nixos/modules/system/boot/stage-1.nix2
-rw-r--r--nixos/modules/system/boot/systemd.nix1
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix35
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix3
-rw-r--r--nixos/modules/virtualisation/virtualbox-host.nix16
-rw-r--r--nixos/release.nix4
-rw-r--r--nixos/tests/ec2.nix4
-rw-r--r--nixos/tests/elk.nix32
-rw-r--r--nixos/tests/home-assistant.nix9
-rw-r--r--nixos/tests/hydra/default.nix13
-rw-r--r--nixos/tests/matrix-synapse.nix17
-rw-r--r--nixos/tests/munin.nix22
-rw-r--r--nixos/tests/netdata.nix3
-rw-r--r--nixos/tests/networking.nix12
-rw-r--r--nixos/tests/virtualbox.nix39
-rw-r--r--nixos/tests/wordpress.nix5
63 files changed, 1486 insertions, 494 deletions
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index 6066d025adbf..6f8e0f613b19 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -326,10 +326,9 @@ Retype new UNIX password: ***
     </screen>
     <note>
      <para>
-      To prevent the password prompt, set
-      <code><xref linkend="opt-users.mutableUsers"/> = false;</code> in
-      <filename>configuration.nix</filename>, which allows unattended
-      installation necessary in automation.
+      For unattended installations, it is possible to use
+      <command>nixos-install --no-root-passwd</command>
+      in order to disable the password prompt entirely.
      </para>
     </note>
    </para>
diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml
index 61b21203f500..e9338efbc025 100644
--- a/nixos/doc/manual/manual.xml
+++ b/nixos/doc/manual/manual.xml
@@ -17,8 +17,8 @@
   <para>
    If you encounter problems, please report them on the
    <literal
-    xlink:href="https://groups.google.com/forum/#!forum/nix-devel">nix-devel</literal>
-   mailing list or on the <link
+    xlink:href="https://discourse.nixos.org">Discourse</literal>
+   or on the <link
     xlink:href="irc://irc.freenode.net/#nixos">
    <literal>#nixos</literal> channel on Freenode</link>. Bugs should be
    reported in
diff --git a/nixos/doc/manual/release-notes/rl-1809.xml b/nixos/doc/manual/release-notes/rl-1809.xml
index 0cb4874a1a21..db9e13da0654 100644
--- a/nixos/doc/manual/release-notes/rl-1809.xml
+++ b/nixos/doc/manual/release-notes/rl-1809.xml
@@ -111,6 +111,12 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
       <link xlink:href="https://github.com/strongswan/strongswan/blob/master/README_LEGACY.md">stroke configuration interface</link>.
     </para>
    </listitem>
+   <listitem>
+    <para>
+      The new <varname>services.elasticsearch-curator</varname> service
+      periodically curates or manages, your Elasticsearch indices and snapshots.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
@@ -192,6 +198,39 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
    </listitem>
    <listitem>
     <para>
+     The ELK stack: <varname>elasticsearch</varname>, <varname>logstash</varname> and <varname>kibana</varname>
+     has been upgraded from 2.* to 6.3.*.
+     The 2.* versions have been <link xlink:href="https://www.elastic.co/support/eol">unsupported since last year</link>
+     so they have been removed. You can still use the 5.* versions under the names
+     <varname>elasticsearch5</varname>, <varname>logstash5</varname> and
+     <varname>kibana5</varname>.
+    </para>
+    <para>
+     The elastic beats:
+     <varname>filebeat</varname>, <varname>heartbeat</varname>,
+     <varname>metricbeat</varname> and <varname>packetbeat</varname>
+     have had the same treatment: they now target 6.3.* as well.
+     The 5.* versions are available under the names:
+     <varname>filebeat5</varname>, <varname>heartbeat5</varname>,
+     <varname>metricbeat5</varname> and <varname>packetbeat5</varname>
+    </para>
+    <para>
+     The ELK-6.3 stack now comes with
+     <link xlink:href="https://www.elastic.co/products/x-pack/open">X-Pack by default</link>.
+     Since X-Pack is licensed under the
+     <link xlink:href="https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE.txt">Elastic License</link>
+     the ELK packages now have an unfree license. To use them you need to specify
+     <literal>allowUnfree = true;</literal> in your nixpkgs configuration.
+    </para>
+    <para>
+     Fortunately there is also a free variant of the ELK stack without X-Pack.
+     The packages are available under the names:
+     <varname>elasticsearch-oss</varname>, <varname>logstash-oss</varname> and
+     <varname>kibana-oss</varname>.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
       Options
       <literal>boot.initrd.luks.devices.<replaceable>name</replaceable>.yubikey.ramfsMountPoint</literal>
       <literal>boot.initrd.luks.devices.<replaceable>name</replaceable>.yubikey.storage.mountPoint</literal>
@@ -278,6 +317,8 @@ inherit (pkgs.nixos {
      <literal>lib.traceCallXml</literal> has been deprecated. Please complain
      if you use the function regularly.
     </para>
+   </listitem>
+   <listitem>
     <para>
      The attribute <literal>lib.nixpkgsVersion</literal> has been deprecated in
      favor of <literal>lib.version</literal>. Please refer to the discussion in
@@ -287,6 +328,13 @@ inherit (pkgs.nixos {
    </listitem>
    <listitem>
     <para>
+     <literal>lib.recursiveUpdateUntil</literal> was not acting according to its
+     specification. It has been fixed to act according to the docstring, and a
+     test has been added.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
      The module for <option>security.dhparams</option> has two new options now:
     </para>
     <variablelist>
diff --git a/nixos/lib/make-ext4-fs.nix b/nixos/lib/make-ext4-fs.nix
index 35a8afae4a7a..88be8b73ab37 100644
--- a/nixos/lib/make-ext4-fs.nix
+++ b/nixos/lib/make-ext4-fs.nix
@@ -6,16 +6,19 @@
 , storePaths
 , volumeLabel
 , uuid ? "44444444-4444-4444-8888-888888888888"
+, e2fsprogs
+, libfaketime
+, perl
 }:
 
 let
-  sdClosureInfo = pkgs.closureInfo { rootPaths = storePaths; };
+  sdClosureInfo = pkgs.buildPackages.closureInfo { rootPaths = storePaths; };
 in
 
 pkgs.stdenv.mkDerivation {
   name = "ext4-fs.img";
 
-  nativeBuildInputs = with pkgs; [e2fsprogs.bin libfaketime perl];
+  nativeBuildInputs = [e2fsprogs.bin libfaketime perl];
 
   buildCommand =
     ''
diff --git a/nixos/lib/qemu-flags.nix b/nixos/lib/qemu-flags.nix
index 6f61c64a832e..f115ca5ac000 100644
--- a/nixos/lib/qemu-flags.nix
+++ b/nixos/lib/qemu-flags.nix
@@ -1,11 +1,15 @@
 # QEMU flags shared between various Nix expressions.
 { pkgs }:
 
+let
+  zeroPad = n: if n < 10 then "0${toString n}" else toString n;
+in
+
 {
 
   qemuNICFlags = nic: net: machine:
-    [ "-net nic,vlan=${toString nic},macaddr=52:54:00:12:${toString net}:${toString machine},model=virtio"
-      "-net vde,vlan=${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
+    [ "-device virtio-net-pci,netdev=vlan${toString nic},mac=52:54:00:12:${zeroPad net}:${zeroPad machine}"
+      "-netdev vde,id=vlan${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
     ];
 
   qemuSerialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index ddec21b5f6e5..426e1666a814 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -524,6 +524,8 @@ in {
       utmp.gid = ids.gids.utmp;
       adm.gid = ids.gids.adm;
       input.gid = ids.gids.input;
+      kvm.gid = ids.gids.kvm;
+      render.gid = ids.gids.render;
     };
 
     system.activationScripts.users = stringAfter [ "stdio" ]
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 08923970cd38..1ac9e5c5c74b 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -318,7 +318,7 @@ in
         options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
       };
 
-    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" "uas" ];
+    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ];
 
     boot.blacklistedKernelModules = [ "nouveau" ];
 
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
index 311a5ff69670..2371be9d89a1 100644
--- a/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -12,13 +12,12 @@
 with lib;
 
 let
-  rootfsImage = import ../../../lib/make-ext4-fs.nix {
-    inherit pkgs;
+  rootfsImage = pkgs.callPackage ../../../lib/make-ext4-fs.nix ({
     inherit (config.sdImage) storePaths;
     volumeLabel = "NIXOS_SD";
   } // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
     uuid = config.sdImage.rootPartitionUUID;
-  };
+  });
 in
 {
   options.sdImage = {
@@ -94,10 +93,10 @@ in
 
     sdImage.storePaths = [ config.system.build.toplevel ];
 
-    system.build.sdImage = pkgs.stdenv.mkDerivation {
+    system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: stdenv.mkDerivation {
       name = config.sdImage.imageName;
 
-      buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
+      nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux ];
 
       buildCommand = ''
         mkdir -p $out/nix-support $out/sd-image
@@ -138,7 +137,7 @@ in
         (cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::)
         dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS
       '';
-    };
+    }) {};
 
     boot.postBootCommands = ''
       # On the first boot do some maintenance tasks
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index a4eda3c52dce..ea640173c6dd 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -28,7 +28,6 @@ with lib;
       ++ (if pkgs.stdenv.system == "aarch64-linux"
           then []
           else [ pkgs.grub2 pkgs.syslinux ]);
-    system.boot.loader.kernelFile = pkgs.stdenv.platform.kernelTarget;
 
     fileSystems."/" =
       { fsType = "tmpfs";
@@ -86,7 +85,7 @@ with lib;
 
     system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
       #!ipxe
-      kernel ${pkgs.stdenv.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+      kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
       initrd initrd
       boot
     '';
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index bffd8aff78b9..0928e368d80f 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -326,6 +326,8 @@
       cfssl = 299;
       cassandra = 300;
       qemu-libvirtd = 301;
+      # kvm = 302; # unused
+      # render = 303; # unused
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -612,6 +614,8 @@
       cfssl = 299;
       cassandra = 300;
       qemu-libvirtd = 301;
+      kvm = 302; # default udev rules from systemd requires these
+      render = 303; # default udev rules from systemd requires these
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index e19853efd73c..12944857af4e 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -247,8 +247,10 @@
   ./services/desktops/gnome3/tracker-miners.nix
   ./services/desktops/profile-sync-daemon.nix
   ./services/desktops/telepathy.nix
+  ./services/desktops/zeitgeist.nix
   ./services/development/bloop.nix
   ./services/development/hoogle.nix
+  ./services/development/jupyter/default.nix
   ./services/editors/emacs.nix
   ./services/editors/infinoted.nix
   ./services/games/factorio.nix
@@ -280,6 +282,7 @@
   ./services/hardware/upower.nix
   ./services/hardware/usbmuxd.nix
   ./services/hardware/thermald.nix
+  ./services/hardware/undervolt.nix
   ./services/logging/SystemdJournal2Gelf.nix
   ./services/logging/awstats.nix
   ./services/logging/fluentd.nix
@@ -407,6 +410,7 @@
   ./services/monitoring/cadvisor.nix
   ./services/monitoring/collectd.nix
   ./services/monitoring/das_watchdog.nix
+  ./services/monitoring/datadog-agent.nix
   ./services/monitoring/dd-agent/dd-agent.nix
   ./services/monitoring/fusion-inventory.nix
   ./services/monitoring/grafana.nix
@@ -620,6 +624,7 @@
   ./services/scheduling/fcron.nix
   ./services/scheduling/marathon.nix
   ./services/search/elasticsearch.nix
+  ./services/search/elasticsearch-curator.nix
   ./services/search/hound.nix
   ./services/search/kibana.nix
   ./services/search/solr.nix
diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix
index 0d7124be0a5c..19f821ae17f3 100644
--- a/nixos/modules/profiles/all-hardware.nix
+++ b/nixos/modules/profiles/all-hardware.nix
@@ -33,7 +33,7 @@
 
       # USB support, especially for booting from USB CD-ROM
       # drives.
-      "usb_storage"
+      "uas"
 
       # Firewire support.  Not tested.
       "ohci1394" "sbp2"
diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix
index 57d947b52684..ff4a23a18d06 100644
--- a/nixos/modules/profiles/installation-device.nix
+++ b/nixos/modules/profiles/installation-device.nix
@@ -31,7 +31,8 @@ with lib;
     #services.rogue.enable = true;
 
     # Disable some other stuff we don't need.
-    security.sudo.enable = false;
+    security.sudo.enable = mkDefault false;
+    services.udisks2.enable = mkDefault false;
 
     # Automatically log in at the virtual consoles.
     services.mingetty.autologinUser = "root";
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index 42d4e1d4ada0..d30b3415411f 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -87,6 +87,19 @@ in
         type = types.bool;
       };
 
+
+      enableGlobalCompInit = mkOption {
+        default = cfg.enableCompletion;
+        description = ''
+          Enable execution of compinit call for all interactive zsh shells.
+
+          This option can be disabled if the user wants to extend its
+          <literal>fpath</literal> and a custom <literal>compinit</literal>
+          call in the local config is required.
+        '';
+        type = types.bool;
+      };
+
     };
 
   };
@@ -159,7 +172,7 @@ in
           fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
         done
 
-        ${optionalString cfg.enableCompletion "autoload -U compinit && compinit"}
+        ${optionalString cfg.enableGlobalCompInit "autoload -U compinit && compinit"}
 
         ${cfge.interactiveShellInit}
 
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 75f02ea78e64..b51dcd2976f4 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -256,6 +256,8 @@ with lib;
     (mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
     (mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
     (mkRemovedOptionModule [ "virtualisation" "xen" "qemu" ] "You don't need this option anymore, it will work without it.")
+    (mkRemovedOptionModule [ "services" "logstash" "enableWeb" ] "The web interface was removed from logstash")
+    (mkRemovedOptionModule [ "boot" "zfs" "enableLegacyCrypto" ] "The corresponding package was removed from nixpkgs.")
 
     # ZSH
     (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
diff --git a/nixos/modules/services/desktops/accountsservice.nix b/nixos/modules/services/desktops/accountsservice.nix
index 2a7450669ea0..933b9da2c83c 100644
--- a/nixos/modules/services/desktops/accountsservice.nix
+++ b/nixos/modules/services/desktops/accountsservice.nix
@@ -32,15 +32,21 @@ with lib;
 
     environment.systemPackages = [ pkgs.accountsservice ];
 
+    # Accounts daemon looks for dbus interfaces in $XDG_DATA_DIRS/accountsservice
+    environment.pathsToLink = [ "/share/accountsservice" ];
+
     services.dbus.packages = [ pkgs.accountsservice ];
 
     systemd.packages = [ pkgs.accountsservice ];
 
-    systemd.services.accounts-daemon= {
+    systemd.services.accounts-daemon = {
 
       wantedBy = [ "graphical.target" ];
 
-    } // (mkIf (!config.users.mutableUsers) {
+      # Accounts daemon looks for dbus interfaces in $XDG_DATA_DIRS/accountsservice
+      environment.XDG_DATA_DIRS = "${config.system.path}/share";
+
+    } // (optionalAttrs (!config.users.mutableUsers) {
       environment.NIXOS_USERS_PURE = "true";
     });
   };
diff --git a/nixos/modules/services/desktops/geoclue2.nix b/nixos/modules/services/desktops/geoclue2.nix
index c5a000d5c6a7..dafb0af20756 100644
--- a/nixos/modules/services/desktops/geoclue2.nix
+++ b/nixos/modules/services/desktops/geoclue2.nix
@@ -4,6 +4,10 @@
 
 with lib;
 
+let
+  # the demo agent isn't built by default, but we need it here
+  package = pkgs.geoclue2.override { withDemoAgent = config.services.geoclue2.enableDemoAgent; };
+in
 {
 
   ###### interface
@@ -21,21 +25,42 @@ with lib;
         '';
       };
 
+      enableDemoAgent = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to use the GeoClue demo agent. This should be
+          overridden by desktop environments that provide their own
+          agent.
+        '';
+      };
+
     };
 
   };
 
 
   ###### implementation
-
   config = mkIf config.services.geoclue2.enable {
 
-    environment.systemPackages = [ pkgs.geoclue2 ];
-
-    services.dbus.packages = [ pkgs.geoclue2 ];
-
-    systemd.packages = [ pkgs.geoclue2 ];
-
+    environment.systemPackages = [ package ];
+
+    services.dbus.packages = [ package ];
+
+    systemd.packages = [ package ];
+  
+    # this needs to run as a user service, since it's associated with the
+    # user who is making the requests
+    systemd.user.services = mkIf config.services.geoclue2.enableDemoAgent { 
+      "geoclue-agent" = {
+        description = "Geoclue agent";
+        script = "${package}/libexec/geoclue-2.0/demos/agent";
+        # this should really be `partOf = [ "geoclue.service" ]`, but
+        # we can't be part of a system service, and the agent should
+        # be okay with the main service coming and going
+        wantedBy = [ "default.target" ];
+      };
+    };
   };
 
 }
diff --git a/nixos/modules/services/desktops/zeitgeist.nix b/nixos/modules/services/desktops/zeitgeist.nix
new file mode 100644
index 000000000000..20c82ccdd56c
--- /dev/null
+++ b/nixos/modules/services/desktops/zeitgeist.nix
@@ -0,0 +1,26 @@
+# Zeitgeist
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  ###### interface
+
+  options = {
+    services.zeitgeist = {
+      enable = mkEnableOption "zeitgeist";
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf config.services.zeitgeist.enable {
+
+    environment.systemPackages = [ pkgs.zeitgeist ];
+
+    services.dbus.packages = [ pkgs.zeitgeist ];
+
+    systemd.packages = [ pkgs.zeitgeist ];
+  };
+}
diff --git a/nixos/modules/services/development/jupyter/default.nix b/nixos/modules/services/development/jupyter/default.nix
new file mode 100644
index 000000000000..9fcc00431865
--- /dev/null
+++ b/nixos/modules/services/development/jupyter/default.nix
@@ -0,0 +1,184 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.jupyter;
+
+  # NOTE: We don't use top-level jupyter because we don't
+  # want to pass in JUPYTER_PATH but use .environment instead,
+  # saving a rebuild.
+  package = pkgs.python3.pkgs.notebook;
+
+  kernels = (pkgs.jupyter-kernel.create  {
+    definitions = if cfg.kernels != null
+      then cfg.kernels
+      else  pkgs.jupyter-kernel.default;
+  });
+
+  notebookConfig = pkgs.writeText "jupyter_config.py" ''
+    ${cfg.notebookConfig}
+
+    c.NotebookApp.password = ${cfg.password}
+  '';
+
+in {
+  meta.maintainers = with maintainers; [ aborsu ];
+
+  options.services.jupyter = {
+    enable = mkEnableOption "Jupyter development server";
+
+    ip = mkOption {
+      type = types.str;
+      default = "localhost";
+      description = ''
+        IP address Jupyter will be listening on.
+      '';
+    };
+
+    port = mkOption {
+      type = types.int;
+      default = 8888;
+      description = ''
+        Port number Jupyter will be listening on.
+      '';
+    };
+
+    notebookDir = mkOption {
+      type = types.str;
+      default = "~/";
+      description = ''
+        Root directory for notebooks.
+      '';
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = "jupyter";
+      description = ''
+        Name of the user used to run the jupyter service.
+        For security reason, jupyter should really not be run as root.
+        If not set (jupyter), the service will create a jupyter user with appropriate settings.
+      '';
+      example = "aborsu";
+    };
+
+    group = mkOption {
+      type = types.str;
+      default = "jupyter";
+      description = ''
+        Name of the group used to run the jupyter service.
+        Use this if you want to create a group of users that are able to view the notebook directory's content.
+      '';
+      example = "users";
+    };
+
+    password = mkOption {
+      type = types.str;
+      description = ''
+        Password to use with notebook.
+        Can be generated using:
+          In [1]: from notebook.auth import passwd
+          In [2]: passwd('test')
+          Out[2]: 'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'
+          NOTE: you need to keep the single quote inside the nix string.
+        Or you can use a python oneliner:
+          "open('/path/secret_file', 'r', encoding='utf8').read().strip()"
+        It will be interpreted at the end of the notebookConfig.
+      '';
+      example = [
+        "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'"
+        "open('/path/secret_file', 'r', encoding='utf8').read().strip()"
+      ];
+    };
+
+    notebookConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Raw jupyter config.
+      '';
+    };
+
+    kernels = mkOption {
+      type = types.nullOr (types.attrsOf(types.submodule (import ./kernel-options.nix {
+        inherit lib;
+      })));
+
+      default = null;
+      example = literalExample ''
+        {
+          python3 = let
+            env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [
+                    ipykernel
+                    pandas
+                    scikitlearn
+                  ]));
+          in {
+            displayName = "Python 3 for machine learning";
+            argv = [
+              "$ {env.interpreter}"
+              "-m"
+              "ipykernel_launcher"
+              "-f"
+              "{connection_file}"
+            ];
+            language = "python";
+            logo32 = "$ {env.sitePackages}/ipykernel/resources/logo-32x32.png";
+            logo64 = "$ {env.sitePackages}/ipykernel/resources/logo-64x64.png";
+          };
+        }
+      '';
+      description = "Declarative kernel config
+
+      Kernels can be declared in any language that supports and has the required
+      dependencies to communicate with a jupyter server.
+      In python's case, it means that ipykernel package must always be included in
+      the list of packages of the targeted environment.
+      ";
+    };
+  };
+
+  config = mkMerge [
+    (mkIf cfg.enable  {
+      systemd.services.jupyter = {
+        description = "Jupyter development server";
+
+        wantedBy = [ "multi-user.target" ];
+
+        # TODO: Patch notebook so we can explicitly pass in a shell
+        path = [ pkgs.bash ]; # needed for sh in cell magic to work
+
+        environment = {
+          JUPYTER_PATH = toString kernels;
+        };
+
+        serviceConfig = {
+          Restart = "always";
+          ExecStart = ''${package}/bin/jupyter-notebook \
+            --no-browser \
+            --ip=${cfg.ip} \
+            --port=${toString cfg.port} --port-retries 0 \
+            --notebook-dir=${cfg.notebookDir} \
+            --NotebookApp.config_file=${notebookConfig}
+          '';
+          User = cfg.user;
+          Group = cfg.group;
+          WorkingDirectory = "~";
+        };
+      };
+    })
+    (mkIf (cfg.enable && (cfg.group == "jupyter")) {
+      users.groups.jupyter = {};
+    })
+    (mkIf (cfg.enable && (cfg.user == "jupyter")) {
+      users.extraUsers.jupyter = {
+        extraGroups = [ cfg.group ];
+        home = "/var/lib/jupyter";
+        createHome = true;
+        useDefaultShell = true; # needed so that the user can start a terminal.
+      };
+    })
+  ];
+}
diff --git a/nixos/modules/services/development/jupyter/kernel-options.nix b/nixos/modules/services/development/jupyter/kernel-options.nix
new file mode 100644
index 000000000000..03547637449a
--- /dev/null
+++ b/nixos/modules/services/development/jupyter/kernel-options.nix
@@ -0,0 +1,60 @@
+# Options that can be used for creating a jupyter kernel.
+{lib }:
+
+with lib;
+
+{
+  options = {
+
+    displayName = mkOption {
+      type = types.str;
+      default = "";
+      example = [
+        "Python 3"
+        "Python 3 for Data Science"
+      ];
+      description = ''
+        Name that will be shown to the user.
+      '';
+    };
+
+    argv = mkOption {
+      type = types.listOf types.str;
+      example = [
+        "{customEnv.interpreter}"
+        "-m"
+        "ipykernel_launcher"
+        "-f"
+        "{connection_file}"
+      ];
+      description = ''
+        Command and arguments to start the kernel.
+      '';
+    };
+
+    language = mkOption {
+      type = types.str;
+      example = "python";
+      description = ''
+        Language of the environment. Typically the name of the binary.
+      '';
+    };
+
+    logo32 = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      example = "{env.sitePackages}/ipykernel/resources/logo-32x32.png";
+      description = ''
+        Path to 32x32 logo png.
+      '';
+    };
+    logo64 = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      example = "{env.sitePackages}/ipykernel/resources/logo-64x64.png";
+      description = ''
+        Path to 64x64 logo png.
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/games/terraria.nix b/nixos/modules/services/games/terraria.nix
index ddf17599296a..31f8edca20ce 100644
--- a/nixos/modules/services/games/terraria.nix
+++ b/nixos/modules/services/games/terraria.nix
@@ -18,6 +18,16 @@ let
     (boolFlag "secure" cfg.secure)
     (boolFlag "noupnp" cfg.noUPnP)
   ];
+  stopScript = pkgs.writeScript "terraria-stop" ''
+    #!${pkgs.runtimeShell}
+
+    if ! [ -d "/proc/$1" ]; then
+      exit 0
+    fi
+
+    ${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter exit Enter
+    ${getBin pkgs.coreutils}/bin/tail --pid="$1" -f /dev/null
+  '';
 in
 {
   options = {
@@ -124,10 +134,10 @@ in
 
       serviceConfig = {
         User    = "terraria";
-        Type = "oneshot";
-        RemainAfterExit = true;
+        Type = "forking";
+        GuessMainPID = true;
         ExecStart = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock new -d ${pkgs.terraria-server}/bin/TerrariaServer ${concatStringsSep " " flags}";
-        ExecStop = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter \"exit\" Enter";
+        ExecStop = "${stopScript} $MAINPID";
       };
 
       postStart = ''
diff --git a/nixos/modules/services/hardware/thermald.nix b/nixos/modules/services/hardware/thermald.nix
index 88c3f99aed4e..69577bbe0181 100644
--- a/nixos/modules/services/hardware/thermald.nix
+++ b/nixos/modules/services/hardware/thermald.nix
@@ -6,16 +6,30 @@ let
   cfg = config.services.thermald;
 in {
   ###### interface
-  options = { 
-    services.thermald = { 
+  options = {
+    services.thermald = {
       enable = mkOption {
         default = false;
         description = ''
           Whether to enable thermald, the temperature management daemon.
-        ''; 
-      };  
-    };  
-  };  
+        '';
+      };
+
+      debug = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable debug logging.
+        '';
+      };
+
+      configFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        description = "the thermald manual configuration file.";
+      };
+    };
+  };
 
   ###### implementation
   config = mkIf cfg.enable {
@@ -24,7 +38,15 @@ in {
     systemd.services.thermald = {
       description = "Thermal Daemon Service";
       wantedBy = [ "multi-user.target" ];
-      script = "exec ${pkgs.thermald}/sbin/thermald --no-daemon --dbus-enable";
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.thermald}/sbin/thermald \
+            --no-daemon \
+            ${optionalString cfg.debug "--loglevel=debug"} \
+            ${optionalString (cfg.configFile != null) "--config-file ${cfg.configFile}"} \
+            --dbus-enable
+        '';
+      };
     };
   };
 }
diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix
new file mode 100644
index 000000000000..e5ef0601de3c
--- /dev/null
+++ b/nixos/modules/services/hardware/undervolt.nix
@@ -0,0 +1,134 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.undervolt;
+in {
+  options.services.undervolt = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to undervolt intel cpus.
+      '';
+    };
+
+    verbose = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable verbose logging.
+      '';
+    };
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.undervolt;
+      defaultText = "pkgs.undervolt";
+      description = ''
+        undervolt derivation to use.
+      '';
+    };
+
+    coreOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset the CPU cores by. Accepts a floating point number.
+      '';
+    };
+
+    gpuOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset the GPU by. Accepts a floating point number.
+      '';
+    };
+
+    uncoreOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset uncore by. Accepts a floating point number.
+      '';
+    };
+
+    analogioOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset analogio by. Accepts a floating point number.
+      '';
+    };
+
+    temp = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target. Accepts a floating point number.
+      '';
+    };
+
+    tempAc = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target on AC power. Accepts a floating point number.
+      '';
+    };
+
+    tempBat = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target on battery power. Accepts a floating point number.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    boot.kernelModules = [ "msr" ];
+
+    environment.systemPackages = [ cfg.package ];
+
+    systemd.services.undervolt = {
+      path = [ pkgs.undervolt ];
+
+      description = "Intel Undervolting Service";
+      serviceConfig = {
+        Type = "oneshot";
+        Restart = "no";
+
+        # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
+        #
+        #     Core or Cache offsets have no effect. It is not possible to set different offsets for
+        #     CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
+        #     both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
+        ExecStart = ''
+          ${pkgs.undervolt}/bin/undervolt \
+            ${optionalString cfg.verbose "--verbose"} \
+            ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \
+            ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \
+            ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \
+            ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \
+            ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \
+            ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \
+            ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \
+            ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"}
+        '';
+      };
+    };
+
+    systemd.timers.undervolt = {
+      description = "Undervolt timer to ensure voltage settings are always applied";
+      partOf = [ "undervolt.service" ];
+      wantedBy = [ "multi-user.target" ];
+      timerConfig = {
+        OnBootSec = "2min";
+        OnUnitActiveSec = "30";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 28d89a7463ab..aa019d855ea9 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -4,25 +4,12 @@ with lib;
 
 let
   cfg = config.services.logstash;
-  atLeast54 = versionAtLeast (builtins.parseDrvName cfg.package.name).version "5.4";
   pluginPath = lib.concatStringsSep ":" cfg.plugins;
   havePluginPath = lib.length cfg.plugins > 0;
   ops = lib.optionalString;
-  verbosityFlag =
-    if atLeast54
-    then "--log.level " + cfg.logLevel
-    else {
-      debug = "--debug";
-      info  = "--verbose";
-      warn  = ""; # intentionally empty
-      error = "--quiet";
-      fatal = "--silent";
-    }."${cfg.logLevel}";
-
-  pluginsPath =
-    if atLeast54
-    then "--path.plugins ${pluginPath}"
-    else "--pluginpath ${pluginPath}";
+  verbosityFlag = "--log.level " + cfg.logLevel;
+
+  pluginsPath = "--path.plugins ${pluginPath}";
 
   logstashConf = pkgs.writeText "logstash.conf" ''
     input {
@@ -63,7 +50,7 @@ in
         type = types.package;
         default = pkgs.logstash;
         defaultText = "pkgs.logstash";
-        example = literalExample "pkgs.logstash";
+        example = literalExample "pkgs.logstash5";
         description = "Logstash package to use.";
       };
 
@@ -95,12 +82,6 @@ in
         description = "The quantity of filter workers to run.";
       };
 
-      enableWeb = mkOption {
-        type = types.bool;
-        default = false;
-        description = "Enable the logstash web interface.";
-      };
-
       listenAddress = mkOption {
         type = types.str;
         default = "127.0.0.1";
@@ -174,16 +155,6 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
-    assertions = [
-      { assertion = atLeast54 -> !cfg.enableWeb;
-        message = ''
-          The logstash web interface is only available for versions older than 5.4.
-          So either set services.logstash.enableWeb = false,
-          or set services.logstash.package to an older logstash.
-        '';
-      }
-    ];
-
     systemd.services.logstash = with pkgs; {
       description = "Logstash Daemon";
       wantedBy = [ "multi-user.target" ];
@@ -193,14 +164,12 @@ in
         ExecStartPre = ''${pkgs.coreutils}/bin/mkdir -p "${cfg.dataDir}" ; ${pkgs.coreutils}/bin/chmod 700 "${cfg.dataDir}"'';
         ExecStart = concatStringsSep " " (filter (s: stringLength s != 0) [
           "${cfg.package}/bin/logstash"
-          (ops (!atLeast54) "agent")
           "-w ${toString cfg.filterWorkers}"
           (ops havePluginPath pluginsPath)
           "${verbosityFlag}"
           "-f ${logstashConf}"
-          (ops atLeast54 "--path.settings ${logstashSettingsDir}")
-          (ops atLeast54 "--path.data ${cfg.dataDir}")
-          (ops cfg.enableWeb "-- web -a ${cfg.listenAddress} -p ${cfg.port}")
+          "--path.settings ${logstashSettingsDir}"
+          "--path.data ${cfg.dataDir}"
         ]);
       };
     };
diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix
index 21be286a6e98..65e103ac2ba5 100644
--- a/nixos/modules/services/logging/syslog-ng.nix
+++ b/nixos/modules/services/logging/syslog-ng.nix
@@ -85,9 +85,11 @@ in {
       after = [ "multi-user.target" ]; # makes sure hostname etc is set
       serviceConfig = {
         Type = "notify";
+        PIDFile = pidFile;
         StandardOutput = "null";
         Restart = "on-failure";
         ExecStart = "${cfg.package}/sbin/syslog-ng ${concatStringsSep " " syslogngOptions}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
       };
     };
   };
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index 5d664728e0b5..dc63f1a6c052 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -261,7 +261,8 @@ in
         runConfig = "${cfg.stateDir}/custom/conf/app.ini";
         secretKey = "${cfg.stateDir}/custom/conf/secret_key";
       in ''
-        mkdir -p ${cfg.stateDir}
+        # Make sure that the stateDir exists, as well as the conf dir in there
+        mkdir -p ${cfg.stateDir}/conf
 
         # copy custom configuration and generate a random secret key if needed
         ${optionalString (cfg.useWizard == false) ''
@@ -290,11 +291,13 @@ in
           sed -ri 's,/nix/store/[a-z0-9.-]+/bin/bash,${pkgs.bash}/bin/bash,g' $HOOKS
           sed -ri 's,/nix/store/[a-z0-9.-]+/bin/perl,${pkgs.perl}/bin/perl,g' $HOOKS
         fi
-        if [ ! -d ${cfg.stateDir}/conf/locale ]
+        # If we have a folder or symlink with gitea locales, remove it
+        if [ -e ${cfg.stateDir}/conf/locale ]
         then
-          mkdir -p ${cfg.stateDir}/conf
-          cp -r ${gitea.out}/locale ${cfg.stateDir}/conf/locale
+          rm -r ${cfg.stateDir}/conf/locale
         fi
+        # And symlink the current gitea locales in place
+        ln -s ${gitea.out}/locale ${cfg.stateDir}/conf/locale
         # update command option in authorized_keys
         if [ -r ${cfg.stateDir}/.ssh/authorized_keys ]
         then
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 5ca879bf2664..c0eb882c58f3 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -88,7 +88,7 @@ in
       };
 
       maxJobs = mkOption {
-        type = types.int;
+        type = types.either types.int (types.enum ["auto"]);
         default = 1;
         example = 64;
         description = ''
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index 9a9424449f80..f763ba21d0b2 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -1,121 +1,124 @@
 { config, lib, pkgs, ... }:
 
-# TODO: support non-postgresql
-
 with lib;
 
 let
   cfg = config.services.redmine;
 
-  ruby = pkgs.ruby;
+  bundle = "${pkgs.redmine}/share/redmine/bin/bundle";
 
-  databaseYml = ''
+  databaseYml = pkgs.writeText "database.yml" ''
     production:
-      adapter: postgresql
-      database: ${cfg.databaseName}
-      host: ${cfg.databaseHost}
-      password: ${cfg.databasePassword}
-      username: ${cfg.databaseUsername}
-      encoding: utf8
+      adapter: ${cfg.database.type}
+      database: ${cfg.database.name}
+      host: ${cfg.database.host}
+      port: ${toString cfg.database.port}
+      username: ${cfg.database.user}
+      password: #dbpass#
   '';
 
-  configurationYml = ''
+  configurationYml = pkgs.writeText "configuration.yml" ''
     default:
-      # Absolute path to the directory where attachments are stored.
-      # The default is the 'files' directory in your Redmine instance.
-      # Your Redmine instance needs to have write permission on this
-      # directory.
-      # Examples:
-      # attachments_storage_path: /var/redmine/files
-      # attachments_storage_path: D:/redmine/files
-      attachments_storage_path: ${cfg.stateDir}/files
-
-      # Absolute path to the SCM commands errors (stderr) log file.
-      # The default is to log in the 'log' directory of your Redmine instance.
-      # Example:
-      # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
-      scm_stderr_log_file: ${cfg.stateDir}/redmine_scm_stderr.log
-
-      ${cfg.extraConfig}
+      scm_subversion_command: ${pkgs.subversion}/bin/svn
+      scm_mercurial_command: ${pkgs.mercurial}/bin/hg
+      scm_git_command: ${pkgs.gitAndTools.git}/bin/git
+      scm_cvs_command: ${pkgs.cvs}/bin/cvs
+      scm_bazaar_command: ${pkgs.bazaar}/bin/bzr
+      scm_darcs_command: ${pkgs.darcs}/bin/darcs
+
+    ${cfg.extraConfig}
   '';
 
-  unpackTheme = unpack "theme";
-  unpackPlugin = unpack "plugin";
-  unpack = id: (name: source:
-    pkgs.stdenv.mkDerivation {
-      name = "redmine-${id}-${name}";
-      buildInputs = [ pkgs.unzip ];
-      buildCommand = ''
-        mkdir -p $out
-        cd $out
-        unpackFile ${source}
-      '';
-    });
-
-in {
+in
 
+{
   options = {
     services.redmine = {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
-          Enable the redmine service.
-        '';
+        description = "Enable the Redmine service.";
       };
 
-      stateDir = mkOption {
+      user = mkOption {
         type = types.str;
-        default = "/var/redmine";
-        description = "The state directory, logs and plugins are stored here";
-      };
-
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Extra configuration in configuration.yml";
-      };
-
-      themes = mkOption {
-        type = types.attrsOf types.path;
-        default = {};
-        description = "Set of themes";
+        default = "redmine";
+        description = "User under which Redmine is ran.";
       };
 
-      plugins = mkOption {
-        type = types.attrsOf types.path;
-        default = {};
-        description = "Set of plugins";
+      group = mkOption {
+        type = types.str;
+        default = "redmine";
+        description = "Group under which Redmine is ran.";
       };
 
-      #databaseType = mkOption {
-      #  type = types.str;
-      #  default = "postgresql";
-      #  description = "Type of database";
-      #};
-
-      databaseHost = mkOption {
+      stateDir = mkOption {
         type = types.str;
-        default = "127.0.0.1";
-        description = "Database hostname";
+        default = "/var/lib/redmine";
+        description = "The state directory, logs and plugins are stored here.";
       };
 
-      databasePassword = mkOption {
-        type = types.str;
+      extraConfig = mkOption {
+        type = types.lines;
         default = "";
-        description = "Database user password";
-      };
+        description = ''
+          Extra configuration in configuration.yml.
 
-      databaseName = mkOption {
-        type = types.str;
-        default = "redmine";
-        description = "Database name";
+          See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
+        '';
       };
 
-      databaseUsername = mkOption {
-        type = types.str;
-        default = "redmine";
-        description = "Database user";
+      database = {
+        type = mkOption {
+          type = types.enum [ "mysql2" "postgresql" ];
+          example = "postgresql";
+          default = "mysql2";
+          description = "Database engine to use.";
+        };
+
+        host = mkOption {
+          type = types.str;
+          default = "127.0.0.1";
+          description = "Database host address.";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = 3306;
+          description = "Database host port.";
+        };
+
+        name = mkOption {
+          type = types.str;
+          default = "redmine";
+          description = "Database name.";
+        };
+
+        user = mkOption {
+          type = types.str;
+          default = "redmine";
+          description = "Database user.";
+        };
+
+        password = mkOption {
+          type = types.str;
+          default = "";
+          description = ''
+            The password corresponding to <option>database.user</option>.
+            Warning: this is stored in cleartext in the Nix store!
+            Use <option>database.passwordFile</option> instead.
+          '';
+        };
+
+        passwordFile = mkOption {
+          type = types.nullOr types.path;
+          default = null;
+          example = "/run/keys/redmine-dbpassword";
+          description = ''
+            A file containing the password corresponding to
+            <option>database.user</option>.
+          '';
+        };
       };
     };
   };
@@ -123,99 +126,106 @@ in {
   config = mkIf cfg.enable {
 
     assertions = [
-      { assertion = cfg.databasePassword != "";
-        message = "services.redmine.databasePassword must be set";
+      { assertion = cfg.database.passwordFile != null || cfg.database.password != "";
+        message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set";
       }
     ];
 
-    users.users = [
-      { name = "redmine";
-        group = "redmine";
-        uid = config.ids.uids.redmine;
-      } ];
-
-    users.groups = [
-      { name = "redmine";
-        gid = config.ids.gids.redmine;
-      } ];
+    environment.systemPackages = [ pkgs.redmine ];
 
     systemd.services.redmine = {
-      after = [ "network.target" "postgresql.service" ];
+      after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
       wantedBy = [ "multi-user.target" ];
+      environment.HOME = "${pkgs.redmine}/share/redmine";
       environment.RAILS_ENV = "production";
-      environment.RAILS_ETC = "${cfg.stateDir}/config";
-      environment.RAILS_LOG = "${cfg.stateDir}/log";
-      environment.RAILS_VAR = "${cfg.stateDir}/var";
       environment.RAILS_CACHE = "${cfg.stateDir}/cache";
-      environment.RAILS_PLUGINS = "${cfg.stateDir}/plugins";
-      environment.RAILS_PUBLIC = "${cfg.stateDir}/public";
-      environment.RAILS_TMP = "${cfg.stateDir}/tmp";
-      environment.SCHEMA = "${cfg.stateDir}/cache/schema.db";
-      environment.HOME = "${pkgs.redmine}/share/redmine";
       environment.REDMINE_LANG = "en";
-      environment.GEM_HOME = "${pkgs.redmine}/share/redmine/vendor/bundle/ruby/1.9.1";
-      environment.GEM_PATH = "${pkgs.bundler}/${pkgs.bundler.ruby.gemPath}";
+      environment.SCHEMA = "${cfg.stateDir}/cache/schema.db";
       path = with pkgs; [
         imagemagickBig
-        subversion
-        mercurial
-        cvs
-        config.services.postgresql.package
         bazaar
+        cvs
+        darcs
         gitAndTools.git
-        # once we build binaries for darc enable it
-        #darcs
+        mercurial
+        subversion
       ];
       preStart = ''
-        # TODO: use env vars
-        for i in plugins public/plugin_assets db files log config cache var/files tmp; do
+        # start with a fresh config directory every time
+        rm -rf ${cfg.stateDir}/config
+        cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config
+
+        # create the basic state directory layout pkgs.redmine expects
+        mkdir -p /run/redmine
+
+        for i in config files log plugins tmp; do
           mkdir -p ${cfg.stateDir}/$i
+          ln -fs ${cfg.stateDir}/$i /run/redmine/$i
         done
 
-        chown -R redmine:redmine ${cfg.stateDir}
-        chmod -R 755 ${cfg.stateDir}
+        # ensure cache directory exists for db:migrate command
+        mkdir -p ${cfg.stateDir}/cache
 
-        rm -rf ${cfg.stateDir}/public/*
-        cp -R ${pkgs.redmine}/share/redmine/public/* ${cfg.stateDir}/public/
-        for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do
-          ln -fs $theme/* ${cfg.stateDir}/public/themes/
-        done
+        # link in the application configuration
+        ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml
 
-        rm -rf ${cfg.stateDir}/plugins/*
-        for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do
-          ln -fs $plugin/* ${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-}
-        done
+        chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/
 
-        ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml
-        ln -fs ${pkgs.writeText "configuration.yml" configurationYml} ${cfg.stateDir}/config/configuration.yml
+        # handle database.passwordFile
+        DBPASS=$(head -n1 ${cfg.database.passwordFile})
+        cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml
+        sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml
+        chmod 440 ${cfg.stateDir}/config/database.yml
 
-        if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
-          if ! test -e "${cfg.stateDir}/db-created"; then
-            psql postgres -c "CREATE ROLE redmine WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'"
-            ${config.services.postgresql.package}/bin/createdb --owner redmine redmine || true
-            touch "${cfg.stateDir}/db-created"
-          fi
+        # generate a secret token if required
+        if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then
+          ${bundle} exec rake generate_secret_token
+          chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb
         fi
 
-        cd ${pkgs.redmine}/share/redmine/
-        ${ruby}/bin/rake db:migrate
-        ${ruby}/bin/rake redmine:plugins:migrate
-        ${ruby}/bin/rake redmine:load_default_data
-        ${ruby}/bin/rake generate_secret_token
+        # ensure everything is owned by ${cfg.user}
+        chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
+
+        ${bundle} exec rake db:migrate
+        ${bundle} exec rake redmine:load_default_data
       '';
 
       serviceConfig = {
         PermissionsStartOnly = true; # preStart must be run as root
         Type = "simple";
-        User = "redmine";
-        Group = "redmine";
+        User = cfg.user;
+        Group = cfg.group;
         TimeoutSec = "300";
         WorkingDirectory = "${pkgs.redmine}/share/redmine";
-        ExecStart="${ruby}/bin/ruby ${pkgs.redmine}/share/redmine/script/rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
+        ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
       };
 
     };
 
+    users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton
+      { name = "redmine";
+        group = cfg.group;
+        home = cfg.stateDir;
+        createHome = true;
+        uid = config.ids.uids.redmine;
+      });
+
+    users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton
+      { name = "redmine";
+        gid = config.ids.gids.redmine;
+      });
+
+    warnings = optional (cfg.database.password != "")
+      ''config.services.redmine.database.password will be stored as plaintext
+      in the Nix store. Use database.passwordFile instead.'';
+
+    # Create database passwordFile default when password is configured.
+    services.redmine.database.passwordFile =
+      (mkDefault (toString (pkgs.writeTextFile {
+        name = "redmine-database-password";
+        text = cfg.database.password;
+      })));
+
   };
 
 }
diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix
index 7e8eadbe5f37..b89cb41ac3ad 100644
--- a/nixos/modules/services/misc/synergy.nix
+++ b/nixos/modules/services/misc/synergy.nix
@@ -83,20 +83,20 @@ in
 
   config = mkMerge [
     (mkIf cfgC.enable {
-      systemd.services."synergy-client" = {
-        after = [ "network.target" ];
+      systemd.user.services."synergy-client" = {
+        after = [ "network.target" "graphical-session.target" ];
         description = "Synergy client";
-        wantedBy = optional cfgC.autoStart "multi-user.target";
+        wantedBy = optional cfgC.autoStart "graphical-session.target";
         path = [ pkgs.synergy ];
         serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}'';
         serviceConfig.Restart = "on-failure";
       };
     })
     (mkIf cfgS.enable {
-      systemd.services."synergy-server" = {
-        after = [ "network.target" ];
+      systemd.user.services."synergy-server" = {
+        after = [ "network.target" "graphical-session.target" ];
         description = "Synergy server";
-        wantedBy = optional cfgS.autoStart "multi-user.target";
+        wantedBy = optional cfgS.autoStart "graphical-session.target";
         path = [ pkgs.synergy ];
         serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }'';
         serviceConfig.Restart = "on-failure";
diff --git a/nixos/modules/services/monitoring/datadog-agent.nix b/nixos/modules/services/monitoring/datadog-agent.nix
new file mode 100644
index 000000000000..e545e06b3495
--- /dev/null
+++ b/nixos/modules/services/monitoring/datadog-agent.nix
@@ -0,0 +1,236 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.datadog-agent;
+
+  ddConf = {
+    dd_url              = "https://app.datadoghq.com";
+    skip_ssl_validation = "no";
+    api_key             = "";
+    confd_path          = "/etc/datadog-agent/conf.d";
+    additional_checksd  = "/etc/datadog-agent/checks.d";
+    use_dogstatsd       = true;
+  }
+  // optionalAttrs (cfg.logLevel != null) { log_level = cfg.logLevel; }
+  // optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; }
+  // optionalAttrs (cfg.tags != null ) { tags = concatStringsSep ", " cfg.tags; }
+  // cfg.extraConfig;
+
+  # Generate Datadog configuration files for each configured checks.
+  # This works because check configurations have predictable paths,
+  # and because JSON is a valid subset of YAML.
+  makeCheckConfigs = entries: mapAttrsToList (name: conf: {
+    source = pkgs.writeText "${name}-check-conf.yaml" (builtins.toJSON conf);
+    target = "datadog-agent/conf.d/${name}.d/conf.yaml";
+  }) entries;
+
+  defaultChecks = {
+    disk = cfg.diskCheck;
+    network = cfg.networkCheck;
+  };
+
+  # Assemble all check configurations and the top-level agent
+  # configuration.
+  etcfiles = with pkgs; with builtins; [{
+    source = writeText "datadog.yaml" (toJSON ddConf);
+    target = "datadog-agent/datadog.yaml";
+  }] ++ makeCheckConfigs (cfg.checks // defaultChecks);
+
+  # Apply the configured extraIntegrations to the provided agent
+  # package. See the documentation of `dd-agent/integrations-core.nix`
+  # for detailed information on this.
+  datadogPkg = cfg.package.overrideAttrs(_: {
+    python = (pkgs.datadog-integrations-core cfg.extraIntegrations).python;
+  });
+in {
+  options.services.datadog-agent = {
+    enable = mkOption {
+      description = ''
+        Whether to enable the datadog-agent v6 monitoring service
+      '';
+      default = false;
+      type = types.bool;
+    };
+
+    package = mkOption {
+      default = pkgs.datadog-agent;
+      defaultText = "pkgs.datadog-agent";
+      description = ''
+        Which DataDog v6 agent package to use. Note that the provided
+        package is expected to have an overridable `python`-attribute
+        which configures the Python environment with the Datadog
+        checks.
+      '';
+      type = types.package;
+    };
+
+    apiKeyFile = mkOption {
+      description = ''
+        Path to a file containing the Datadog API key to associate the
+        agent with your account.
+      '';
+      example = "/run/keys/datadog_api_key";
+      type = types.path;
+    };
+
+    tags = mkOption {
+      description = "The tags to mark this Datadog agent";
+      example = [ "test" "service" ];
+      default = null;
+      type = types.nullOr (types.listOf types.str);
+    };
+
+    hostname = mkOption {
+      description = "The hostname to show in the Datadog dashboard (optional)";
+      default = null;
+      example = "mymachine.mydomain";
+      type = types.uniq (types.nullOr types.string);
+    };
+
+    logLevel = mkOption {
+      description = "Logging verbosity.";
+      default = null;
+      type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]);
+    };
+
+    extraIntegrations = mkOption {
+      default = {};
+      type    = types.attrs;
+
+      description = ''
+        Extra integrations from the Datadog core-integrations
+        repository that should be built and included.
+
+        By default the included integrations are disk, mongo, network,
+        nginx and postgres.
+
+        To include additional integrations the name of the derivation
+        and a function to filter its dependencies from the Python
+        package set must be provided.
+      '';
+
+      example = {
+        ntp = (pythonPackages: [ pythonPackages.ntplib ]);
+      };
+    };
+
+    extraConfig = mkOption {
+      default = {};
+      type = types.attrs;
+      description = ''
+        Extra configuration options that will be merged into the
+        main config file <filename>datadog.yaml</filename>.
+      '';
+     };
+
+    checks = mkOption {
+      description = ''
+        Configuration for all Datadog checks. Keys of this attribute
+        set will be used as the name of the check to create the
+        appropriate configuration in `conf.d/$check.d/conf.yaml`.
+
+        The configuration is converted into JSON from the plain Nix
+        language configuration, meaning that you should write
+        configuration adhering to Datadog's documentation - but in Nix
+        language.
+
+        Refer to the implementation of this module (specifically the
+        definition of `defaultChecks`) for an example.
+
+        Note: The 'disk' and 'network' check are configured in
+        separate options because they exist by default. Attempting to
+        override their configuration here will have no effect.
+      '';
+
+      example = {
+        http_check = {
+          init_config = null; # sic!
+          instances = [
+            {
+              name = "some-service";
+              url = "http://localhost:1337/healthz";
+              tags = [ "some-service" ];
+            }
+          ];
+        };
+      };
+
+      default = {};
+
+      # sic! The structure of the values is up to the check, so we can
+      # not usefully constrain the type further.
+      type = with types; attrsOf attrs;
+    };
+
+    diskCheck = mkOption {
+      description = "Disk check config";
+      type = types.attrs;
+      default = {
+        init_config = {};
+        instances = [ { use-mount = "no"; } ];
+      };
+    };
+
+    networkCheck = mkOption {
+      description = "Network check config";
+      type = types.attrs;
+      default = {
+        init_config = {};
+        # Network check only supports one configured instance
+        instances = [ { collect_connection_state = false;
+          excluded_interfaces = [ "lo" "lo0" ]; } ];
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps ];
+
+    users.extraUsers.datadog = {
+      description = "Datadog Agent User";
+      uid = config.ids.uids.datadog;
+      group = "datadog";
+      home = "/var/log/datadog/";
+      createHome = true;
+    };
+
+    users.extraGroups.datadog.gid = config.ids.gids.datadog;
+
+    systemd.services = let
+      makeService = attrs: recursiveUpdate {
+        path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          User = "datadog";
+          Group = "datadog";
+          Restart = "always";
+          RestartSec = 2;
+          PrivateTmp = true;
+        };
+        restartTriggers = [ datadogPkg ] ++ map (etc: etc.source) etcfiles;
+      } attrs;
+    in {
+      datadog-agent = makeService {
+        description = "Datadog agent monitor";
+        preStart = ''
+          chown -R datadog: /etc/datadog-agent
+          rm -f /etc/datadog-agent/auth_token
+        '';
+        script = ''
+          export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile})
+          exec ${datadogPkg}/bin/agent start -c /etc/datadog-agent/datadog.yaml
+        '';
+        serviceConfig.PermissionsStartOnly = true;
+      };
+
+      dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService {
+        description = "Datadog JMX Fetcher";
+        path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ];
+        serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch";
+      });
+    };
+
+    environment.etc = etcfiles;
+  };
+}
diff --git a/nixos/modules/services/monitoring/dd-agent/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent/dd-agent.nix
index cf65b6c28cf2..abc8d65d58f2 100644
--- a/nixos/modules/services/monitoring/dd-agent/dd-agent.nix
+++ b/nixos/modules/services/monitoring/dd-agent/dd-agent.nix
@@ -114,13 +114,22 @@ let
 in {
   options.services.dd-agent = {
     enable = mkOption {
-      description = "Whether to enable the dd-agent montioring service";
+      description = ''
+        Whether to enable the dd-agent v5 monitoring service.
+        For datadog-agent v6, see <option>services.datadog-agent.enable</option>.
+      '';
       default = false;
       type = types.bool;
     };
 
     api_key = mkOption {
-      description = "The Datadog API key to associate the agent with your account";
+      description = ''
+        The Datadog API key to associate the agent with your account.
+
+        Warning: this key is stored in cleartext within the world-readable
+        Nix store! Consider using the new v6
+        <option>services.datadog-agent</option> module instead.
+      '';
       example = "ae0aa6a8f08efa988ba0a17578f009ab";
       type = types.str;
     };
@@ -188,48 +197,41 @@ in {
 
     users.groups.datadog.gid = config.ids.gids.datadog;
 
-    systemd.services.dd-agent = {
-      description = "Datadog agent monitor";
-      path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps pkgs.gohai ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        ExecStart = "${pkgs.dd-agent}/bin/dd-agent foreground";
-        User = "datadog";
-        Group = "datadog";
-        Restart = "always";
-        RestartSec = 2;
+    systemd.services = let
+      makeService = attrs: recursiveUpdate {
+        path = [ pkgs.dd-agent pkgs.python pkgs.sysstat pkgs.procps pkgs.gohai ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          User = "datadog";
+          Group = "datadog";
+          Restart = "always";
+          RestartSec = 2;
+          PrivateTmp = true;
+        };
+        restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ];
+      } attrs;
+    in {
+      dd-agent = makeService {
+        description = "Datadog agent monitor";
+        serviceConfig.ExecStart = "${pkgs.dd-agent}/bin/dd-agent foreground";
       };
-      restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ];
-    };
 
-    systemd.services.dogstatsd = {
-      description = "Datadog statsd";
-      path = [ pkgs."dd-agent" pkgs.python pkgs.procps ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        ExecStart = "${pkgs.dd-agent}/bin/dogstatsd start";
-        User = "datadog";
-        Group = "datadog";
-        Type = "forking";
-        PIDFile = "/tmp/dogstatsd.pid";
-        Restart = "always";
-        RestartSec = 2;
+      dogstatsd = makeService {
+        description = "Datadog statsd";
+        environment.TMPDIR = "/run/dogstatsd";
+        serviceConfig = {
+          ExecStart = "${pkgs.dd-agent}/bin/dogstatsd start";
+          Type = "forking";
+          PIDFile = "/run/dogstatsd/dogstatsd.pid";
+          RuntimeDirectory = "dogstatsd";
+        };
       };
-      restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ];
-    };
 
-    systemd.services.dd-jmxfetch = lib.mkIf (cfg.jmxConfig != null) {
-      description = "Datadog JMX Fetcher";
-      path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        ExecStart = "${pkgs.dd-agent}/bin/dd-jmxfetch";
-        User = "datadog";
-        Group = "datadog";
-        Restart = "always";
-        RestartSec = 2;
+      dd-jmxfetch = lib.mkIf (cfg.jmxConfig != null) {
+        description = "Datadog JMX Fetcher";
+        path = [ pkgs.dd-agent pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ];
+        serviceConfig.ExecStart = "${pkgs.dd-agent}/bin/dd-jmxfetch";
       };
-      restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig ];
     };
 
     environment.etc = etcfiles;
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index b23266e8d43a..10dc58311212 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -214,12 +214,10 @@ in
             }
           ];
         # Always provide a smb.conf to shut up programs like smbclient and smbspool.
-        environment.etc = singleton
-          { source =
-              if cfg.enable then configFile
-              else pkgs.writeText "smb-dummy.conf" "# Samba is disabled.";
-            target = "samba/smb.conf";
-          };
+        environment.etc."samba/smb.conf".source = mkOptionDefault (
+          if cfg.enable then configFile
+          else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."
+        );
       }
 
       (mkIf cfg.enable {
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index de0aa1a2c2c3..efdbca5d52e8 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -161,8 +161,9 @@ in
       { description = "DHCP Client";
 
         wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target";
-        after = [ "network.target" ];
-        wants = [ "network.target" ];
+        wants = [ "network.target" "systemd-udev-settle.service" ];
+        before = [ "network.target" ];
+        after = [ "systemd-udev-settle.service" ];
 
         # Stopping dhcpcd during a reconfiguration is undesirable
         # because it brings down the network interfaces configured by
diff --git a/nixos/modules/services/networking/iwd.nix b/nixos/modules/services/networking/iwd.nix
index cfc536fc5b5f..eb03d2e1d632 100644
--- a/nixos/modules/services/networking/iwd.nix
+++ b/nixos/modules/services/networking/iwd.nix
@@ -20,14 +20,7 @@ in {
 
     services.dbus.packages = [ pkgs.iwd ];
 
-    systemd.services.iwd = {
-      description = "Wireless daemon";
-      before = [ "network.target" ];
-      wants = [ "network.target" ];
-      wantedBy = [ "multi-user.target" ];
-
-      serviceConfig.ExecStart = "${pkgs.iwd}/libexec/iwd";
-    };
+    systemd.packages = [ pkgs.iwd ];
 
     systemd.tmpfiles.rules = [
       "d /var/lib/iwd 0700 root root -"
diff --git a/nixos/modules/services/search/elasticsearch-curator.nix b/nixos/modules/services/search/elasticsearch-curator.nix
new file mode 100644
index 000000000000..43785c392fee
--- /dev/null
+++ b/nixos/modules/services/search/elasticsearch-curator.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+    cfg = config.services.elasticsearch-curator;
+    curatorConfig = pkgs.writeTextFile {
+      name = "config.yaml";
+      text = ''
+        ---
+        # Remember, leave a key empty if there is no value.  None will be a string,
+        # not a Python "NoneType"
+        client:
+          hosts: ${builtins.toJSON cfg.hosts}
+          port: ${toString cfg.port}
+          url_prefix:
+          use_ssl: False
+          certificate:
+          client_cert:
+          client_key:
+          ssl_no_validate: False
+          http_auth:
+          timeout: 30
+          master_only: False
+        logging:
+          loglevel: INFO
+          logfile:
+          logformat: default
+          blacklist: ['elasticsearch', 'urllib3']
+        '';
+    };
+    curatorAction = pkgs.writeTextFile {
+      name = "action.yaml";
+      text = cfg.actionYAML;
+    };
+in {
+
+  options.services.elasticsearch-curator = {
+
+    enable = mkEnableOption "elasticsearch curator";
+    interval = mkOption {
+      description = "The frequency to run curator, a systemd.time such as 'hourly'";
+      default = "hourly";
+      type = types.str;
+    };
+    hosts = mkOption {
+      description = "a list of elasticsearch hosts to connect to";
+      type = types.listOf types.str;
+      default = ["localhost"];
+    };
+    port = mkOption {
+      description = "the port that elasticsearch is listening on";
+      type = types.int;
+      default = 9200;
+    };
+    actionYAML = mkOption {
+      description = "curator action.yaml file contents, alternatively use curator-cli which takes a simple action command";
+      example = ''
+        ---
+        actions:
+          1:
+            action: delete_indices
+            description: >-
+              Delete indices older than 45 days (based on index name), for logstash-
+              prefixed indices. Ignore the error if the filter does not result in an
+              actionable list of indices (ignore_empty_list) and exit cleanly.
+            options:
+              ignore_empty_list: True
+              disable_action: False
+            filters:
+            - filtertype: pattern
+              kind: prefix
+              value: logstash-
+            - filtertype: age
+              source: name
+              direction: older
+              timestring: '%Y.%m.%d'
+              unit: days
+              unit_count: 45
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.elasticsearch-curator = {
+      startAt = cfg.interval;
+      serviceConfig = {
+        ExecStart = ''${pkgs.python36Packages.elasticsearch-curator}/bin/curator --config ${curatorConfig} ${curatorAction}'';
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index b0831dcd1ca8..6b688c640d59 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -5,22 +5,14 @@ with lib;
 let
   cfg = config.services.elasticsearch;
 
-  es5 = builtins.compareVersions (builtins.parseDrvName cfg.package.name).version "5" >= 0;
-  es6 = builtins.compareVersions (builtins.parseDrvName cfg.package.name).version "6" >= 0;
+  es6 = builtins.compareVersions cfg.package.version "6" >= 0;
 
   esConfig = ''
     network.host: ${cfg.listenAddress}
     cluster.name: ${cfg.cluster_name}
 
-    ${if es5 then ''
-      http.port: ${toString cfg.port}
-      transport.tcp.port: ${toString cfg.tcp_port}
-    '' else ''
-      network.port: ${toString cfg.port}
-      network.tcp.port: ${toString cfg.tcp_port}
-      # TODO: find a way to enable security manager
-      security.manager.enabled: false
-    ''}
+    http.port: ${toString cfg.port}
+    transport.tcp.port: ${toString cfg.tcp_port}
 
     ${cfg.extraConf}
   '';
@@ -32,7 +24,7 @@ let
     text = esConfig;
   };
 
-  loggingConfigFilename = if es5 then "log4j2.properties" else "logging.yml";
+  loggingConfigFilename = "log4j2.properties";
   loggingConfigFile = pkgs.writeTextFile {
     name = loggingConfigFilename;
     text = cfg.logging;
@@ -41,8 +33,7 @@ let
   esPlugins = pkgs.buildEnv {
     name = "elasticsearch-plugins";
     paths = cfg.plugins;
-    # Elasticsearch 5.x won't start when the plugins directory does not exist
-    postBuild = if es5 then "${pkgs.coreutils}/bin/mkdir -p $out/plugins" else "";
+    postBuild = "${pkgs.coreutils}/bin/mkdir -p $out/plugins";
   };
 
 in {
@@ -58,8 +49,8 @@ in {
 
     package = mkOption {
       description = "Elasticsearch package to use.";
-      default = pkgs.elasticsearch2;
-      defaultText = "pkgs.elasticsearch2";
+      default = pkgs.elasticsearch;
+      defaultText = "pkgs.elasticsearch";
       type = types.package;
     };
 
@@ -100,30 +91,18 @@ in {
 
     logging = mkOption {
       description = "Elasticsearch logging configuration.";
-      default =
-        if es5 then ''
-          logger.action.name = org.elasticsearch.action
-          logger.action.level = info
-
-          appender.console.type = Console
-          appender.console.name = console
-          appender.console.layout.type = PatternLayout
-          appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
-
-          rootLogger.level = info
-          rootLogger.appenderRef.console.ref = console
-        '' else ''
-          rootLogger: INFO, console
-          logger:
-            action: INFO
-            com.amazonaws: WARN
-          appender:
-            console:
-              type: console
-              layout:
-                type: consolePattern
-                conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
-        '';
+      default = ''
+        logger.action.name = org.elasticsearch.action
+        logger.action.level = info
+
+        appender.console.type = Console
+        appender.console.name = console
+        appender.console.layout.type = PatternLayout
+        appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
+
+        rootLogger.level = info
+        rootLogger.appenderRef.console.ref = console
+      '';
       type = types.str;
     };
 
@@ -204,9 +183,9 @@ in {
 
         cp ${elasticsearchYml} ${configDir}/elasticsearch.yml
         # Make sure the logging configuration for old elasticsearch versions is removed:
-        rm -f ${if es5 then "${configDir}/logging.yml" else "${configDir}/log4j2.properties"}
+        rm -f "${configDir}/logging.yml"
         cp ${loggingConfigFile} ${configDir}/${loggingConfigFilename}
-        ${optionalString es5 "mkdir -p ${configDir}/scripts"}
+        mkdir -p ${configDir}/scripts
         ${optionalString es6 "cp ${cfg.package}/config/jvm.options ${configDir}/jvm.options"}
 
         if [ "$(id -u)" = 0 ]; then chown -R elasticsearch:elasticsearch ${cfg.dataDir}; fi
diff --git a/nixos/modules/services/search/kibana.nix b/nixos/modules/services/search/kibana.nix
index 5885a72c6628..ca36bba58c02 100644
--- a/nixos/modules/services/search/kibana.nix
+++ b/nixos/modules/services/search/kibana.nix
@@ -5,43 +5,7 @@ with lib;
 let
   cfg = config.services.kibana;
 
-  atLeast54 = versionAtLeast (builtins.parseDrvName cfg.package.name).version "5.4";
-
-  cfgFile = if atLeast54 then cfgFile5 else cfgFile4;
-
-  cfgFile4 = pkgs.writeText "kibana.json" (builtins.toJSON (
-    (filterAttrsRecursive (n: v: v != null) ({
-      host = cfg.listenAddress;
-      port = cfg.port;
-      ssl_cert_file = cfg.cert;
-      ssl_key_file = cfg.key;
-
-      kibana_index = cfg.index;
-      default_app_id = cfg.defaultAppId;
-
-      elasticsearch_url = cfg.elasticsearch.url;
-      kibana_elasticsearch_username = cfg.elasticsearch.username;
-      kibana_elasticsearch_password = cfg.elasticsearch.password;
-      kibana_elasticsearch_cert = cfg.elasticsearch.cert;
-      kibana_elasticsearch_key = cfg.elasticsearch.key;
-      ca = cfg.elasticsearch.ca;
-
-      bundled_plugin_ids = [
-        "plugins/dashboard/index"
-        "plugins/discover/index"
-        "plugins/doc/index"
-        "plugins/kibana/index"
-        "plugins/markdown_vis/index"
-        "plugins/metric_vis/index"
-        "plugins/settings/index"
-        "plugins/table_vis/index"
-        "plugins/vis_types/index"
-        "plugins/visualize/index"
-      ];
-    } // cfg.extraConf)
-  )));
-
-  cfgFile5 = pkgs.writeText "kibana.json" (builtins.toJSON (
+  cfgFile = pkgs.writeText "kibana.json" (builtins.toJSON (
     (filterAttrsRecursive (n: v: v != null) ({
       server.host = cfg.listenAddress;
       server.port = cfg.port;
diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix
index 1eb2f65ba602..ee6d5d91fe15 100644
--- a/nixos/modules/services/security/cfssl.nix
+++ b/nixos/modules/services/security/cfssl.nix
@@ -146,7 +146,7 @@ in {
     };
   };
 
-  config = {
+  config = mkIf cfg.enable {
     users.extraGroups.cfssl = {
       gid = config.ids.gids.cfssl;
     };
@@ -159,7 +159,7 @@ in {
       uid = config.ids.uids.cfssl;
     };
 
-    systemd.services.cfssl = mkIf cfg.enable {
+    systemd.services.cfssl = {
       description = "CFSSL CA API server";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix
index b9355bbb9441..c7e897c96448 100644
--- a/nixos/modules/services/system/localtime.nix
+++ b/nixos/modules/services/system/localtime.nix
@@ -22,14 +22,8 @@ in {
   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;
-       }
-     });
-    '';
+    # so polkit will pick up the rules
+    environment.systemPackages = [ pkgs.localtime ];
 
     users.users = [{
       name = "localtimed";
diff --git a/nixos/modules/services/web-servers/hydron.nix b/nixos/modules/services/web-servers/hydron.nix
index c49efaede160..ed63230bc784 100644
--- a/nixos/modules/services/web-servers/hydron.nix
+++ b/nixos/modules/services/web-servers/hydron.nix
@@ -16,10 +16,10 @@ in with lib; {
 
     interval = mkOption {
       type = types.str;
-      default = "hourly";
+      default = "weekly";
       example = "06:00";
       description = ''
-        How often we run hydron import and possibly fetch tags. Runs by default every hour.
+        How often we run hydron import and possibly fetch tags. Runs by default every week.
 
         The format is described in
         <citerefentry><refentrytitle>systemd.time</refentrytitle>
@@ -137,9 +137,13 @@ in with lib; {
 
     systemd.timers.hydron-fetch = {
       description = "Automatically import paths into hydron and possibly fetch tags";
-      after = [ "network.target" ];
+      after = [ "network.target" "hydron.service" ];
       wantedBy = [ "timers.target" ];
-      timerConfig.OnCalendar = cfg.interval;
+      
+      timerConfig = {
+        Persistent = true;
+        OnCalendar = cfg.interval;
+      };
     };
 
     users = {
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index ee9b11928ae1..c339d24b098a 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -97,6 +97,8 @@ in {
     services.udisks2.enable = true;
     services.accounts-daemon.enable = true;
     services.geoclue2.enable = mkDefault true;
+    # GNOME should have its own geoclue agent
+    services.geoclue2.enableDemoAgent = false;
     services.dleyna-renderer.enable = mkDefault true;
     services.dleyna-server.enable = mkDefault true;
     services.gnome3.at-spi2-core.enable = true;
diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix
index 6be15d8cdf46..dc82f7086c82 100644
--- a/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -15,7 +15,7 @@ let
 
   inherit (pkgs) lightdm writeScript writeText;
 
-  # lightdm runs with clearenv(), but we need a few things in the enviornment for X to startup
+  # lightdm runs with clearenv(), but we need a few things in the environment for X to startup
   xserverWrapper = writeScript "xserver-wrapper"
     ''
       #! ${pkgs.bash}/bin/bash
@@ -209,9 +209,12 @@ in
     services.dbus.enable = true;
     services.dbus.packages = [ lightdm ];
 
-    # lightdm uses the accounts daemon to rember language/window-manager per user
+    # lightdm uses the accounts daemon to remember language/window-manager per user
     services.accounts-daemon.enable = true;
 
+    # Enable the accounts daemon to find lightdm's dbus interface
+    environment.systemPackages = [ lightdm ];
+
     security.pam.services.lightdm = {
       allowNullPassword = true;
       startSession = true;
diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix
index 30d853841ea4..b7dd7debcb63 100644
--- a/nixos/modules/services/x11/redshift.nix
+++ b/nixos/modules/services/x11/redshift.nix
@@ -116,6 +116,9 @@ in {
       }
     ];
 
+    # needed so that .desktop files are installed, which geoclue cares about
+    environment.systemPackages = [ cfg.package ];
+
     services.geoclue2.enable = mkIf (cfg.provider == "geoclue2") true;
 
     systemd.user.services.redshift = 
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index da29e08b3691..9d410a8b9ca4 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -46,7 +46,7 @@ let
 
         ln -s ${kernelPath} $out/kernel
         ln -s ${config.system.modulesTree} $out/kernel-modules
-        ${optionalString (pkgs.stdenv.platform.kernelDTB or false) ''
+        ${optionalString (pkgs.stdenv.hostPlatform.platform.kernelDTB or false) ''
           ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs
         ''}
 
@@ -74,7 +74,7 @@ let
       echo -n "$configurationName" > $out/configuration-name
       echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version
       echo -n "$nixosLabel" > $out/nixos-version
-      echo -n "$system" > $out/system
+      echo -n "${pkgs.stdenv.hostPlatform.system}" > $out/system
 
       mkdir $out/fine-tune
       childCount=0
@@ -175,7 +175,7 @@ in
 
     system.boot.loader.kernelFile = mkOption {
       internal = true;
-      default = pkgs.stdenv.platform.kernelTarget;
+      default = pkgs.stdenv.hostPlatform.platform.kernelTarget;
       type = types.str;
       description = ''
         Name of the kernel file to be passed to the bootloader.
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
index f8a00784034a..2d27611946e2 100644
--- a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
+++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
@@ -13,7 +13,7 @@ let
   };
 
   # Temporary check, for nixos to cope both with nixpkgs stdenv-updates and trunk
-  platform = pkgs.stdenv.platform;
+  inherit (pkgs.stdenv.hostPlatform) platform;
 
 in
 
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
index f974d07da9e5..9bec24c53f5b 100644
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
@@ -15,7 +15,7 @@ let
     inherit configTxt;
   };
 
-  platform = pkgs.stdenv.platform;
+  inherit (pkgs.stdenv.hostPlatform) platform;
 
   builderUboot = import ./builder_uboot.nix { inherit config; inherit pkgs; inherit configTxt; };
 
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index ce770d067608..c11aaeaeb6dc 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -11,17 +11,29 @@ let
   checkLink = checkUnitConfig "Link" [
     (assertOnlyFields [
       "Description" "Alias" "MACAddressPolicy" "MACAddress" "NamePolicy" "Name"
-      "MTUBytes" "BitsPerSecond" "Duplex" "WakeOnLan"
+      "MTUBytes" "BitsPerSecond" "Duplex" "AutoNegotiation" "WakeOnLan" "Port"
+      "TCPSegmentationOffload" "TCP6SegmentationOffload" "GenericSegmentationOffload"
+      "GenericReceiveOffload" "LargeReceiveOffload" "RxChannels" "TxChannels"
+      "OtherChannels" "CombinedChannels"
     ])
-    (assertValueOneOf "MACAddressPolicy" ["persistent" "random"])
+    (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
     (assertMacAddress "MACAddress")
-    (assertValueOneOf "NamePolicy" [
-      "kernel" "database" "onboard" "slot" "path" "mac"
-    ])
     (assertByteFormat "MTUBytes")
     (assertByteFormat "BitsPerSecond")
     (assertValueOneOf "Duplex" ["half" "full"])
-    (assertValueOneOf "WakeOnLan" ["phy" "magic" "off"])
+    (assertValueOneOf "AutoNegotiation" boolValues)
+    (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
+    (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
+    (assertValueOneOf "TCPSegmentationOffload" boolValues)
+    (assertValueOneOf "TCP6SegmentationOffload" boolValues)
+    (assertValueOneOf "GenericSegmentationOffload" boolValues)
+    (assertValueOneOf "UDPSegmentationOffload" boolValues)
+    (assertValueOneOf "GenericReceiveOffload" boolValues)
+    (assertValueOneOf "LargeReceiveOffload" boolValues)
+    (assertRange "RxChannels" 1 4294967295)
+    (assertRange "TxChannels" 1 4294967295)
+    (assertRange "OtherChannels" 1 4294967295)
+    (assertRange "CombinedChannels" 1 4294967295)
   ];
 
   checkNetdev = checkUnitConfig "Netdev" [
@@ -31,16 +43,21 @@ let
     (assertHasField "Name")
     (assertHasField "Kind")
     (assertValueOneOf "Kind" [
-      "bridge" "bond" "vlan" "macvlan" "vxlan" "ipip"
-      "gre" "sit" "vti" "veth" "tun" "tap" "dummy"
+      "bond" "bridge" "dummy" "gre" "gretap" "ip6gre" "ip6tnl" "ip6gretap" "ipip"
+      "ipvlan" "macvlan" "macvtap" "sit" "tap" "tun" "veth" "vlan" "vti" "vti6"
+      "vxlan" "geneve" "vrf" "vcan" "vxcan" "wireguard" "netdevsim"
     ])
     (assertByteFormat "MTUBytes")
     (assertMacAddress "MACAddress")
   ];
 
   checkVlan = checkUnitConfig "VLAN" [
-    (assertOnlyFields ["Id"])
+    (assertOnlyFields ["Id" "GVRP" "MVRP" "LooseBinding" "ReorderHeader"])
     (assertRange "Id" 0 4094)
+    (assertValueOneOf "GVRP" boolValues)
+    (assertValueOneOf "MVRP" boolValues)
+    (assertValueOneOf "LooseBinding" boolValues)
+    (assertValueOneOf "ReorderHeader" boolValues)
   ];
 
   checkMacvlan = checkUnitConfig "MACVLAN" [
@@ -49,15 +66,41 @@ let
   ];
 
   checkVxlan = checkUnitConfig "VXLAN" [
-    (assertOnlyFields ["Id" "Group" "TOS" "TTL" "MacLearning"])
+    (assertOnlyFields [
+      "Id" "Remote" "Local" "TOS" "TTL" "MacLearning" "FDBAgeingSec"
+      "MaximumFDBEntries" "ReduceARPProxy" "L2MissNotification"
+      "L3MissNotification" "RouteShortCircuit" "UDPChecksum"
+      "UDP6ZeroChecksumTx" "UDP6ZeroChecksumRx" "RemoteChecksumTx"
+      "RemoteChecksumRx" "GroupPolicyExtension" "DestinationPort" "PortRange"
+      "FlowLabel"
+    ])
     (assertRange "TTL" 0 255)
     (assertValueOneOf "MacLearning" boolValues)
+    (assertValueOneOf "ReduceARPProxy" boolValues)
+    (assertValueOneOf "L2MissNotification" boolValues)
+    (assertValueOneOf "L3MissNotification" boolValues)
+    (assertValueOneOf "RouteShortCircuit" boolValues)
+    (assertValueOneOf "UDPChecksum" boolValues)
+    (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
+    (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
+    (assertValueOneOf "RemoteChecksumTx" boolValues)
+    (assertValueOneOf "RemoteChecksumRx" boolValues)
+    (assertValueOneOf "GroupPolicyExtension" boolValues)
+    (assertRange "FlowLabel" 0 1048575)
   ];
 
   checkTunnel = checkUnitConfig "Tunnel" [
-    (assertOnlyFields ["Local" "Remote" "TOS" "TTL" "DiscoverPathMTU"])
+    (assertOnlyFields [
+      "Local" "Remote" "TOS" "TTL" "DiscoverPathMTU" "IPv6FlowLabel" "CopyDSCP"
+      "EncapsulationLimit" "Key" "InputKey" "OutputKey" "Mode" "Independent"
+      "AllowLocalRemote"
+    ])
     (assertRange "TTL" 0 255)
     (assertValueOneOf "DiscoverPathMTU" boolValues)
+    (assertValueOneOf "CopyDSCP" boolValues)
+    (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
+    (assertValueOneOf "Independent" boolValues)
+    (assertValueOneOf "AllowLocalRemote" boolValues)
   ];
 
   checkPeer = checkUnitConfig "Peer" [
@@ -66,10 +109,11 @@ let
   ];
 
   tunTapChecks = [
-    (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "User" "Group"])
+    (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "VNetHeader" "User" "Group"])
     (assertValueOneOf "OneQueue" boolValues)
     (assertValueOneOf "MultiQueue" boolValues)
     (assertValueOneOf "PacketInfo" boolValues)
+    (assertValueOneOf "VNetHeader" boolValues)
   ];
 
   checkTun = checkUnitConfig "Tun" tunTapChecks;
@@ -79,67 +123,121 @@ let
   checkBond = checkUnitConfig "Bond" [
     (assertOnlyFields [
       "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec"
-      "UpDelaySec" "DownDelaySec" "GratuitousARP"
+      "UpDelaySec" "DownDelaySec" "LearnPacketIntervalSec" "AdSelect"
+      "FailOverMACPolicy" "ARPValidate" "ARPIntervalSec" "ARPIPTargets"
+      "ARPAllTargets" "PrimaryReselectPolicy" "ResendIGMP" "PacketsPerSlave"
+      "GratuitousARP" "AllSlavesActive" "MinLinks"
     ])
     (assertValueOneOf "Mode" [
       "balance-rr" "active-backup" "balance-xor"
       "broadcast" "802.3ad" "balance-tlb" "balance-alb"
     ])
     (assertValueOneOf "TransmitHashPolicy" [
-      "layer2" "layer3+4" "layer2+3" "encap2+3" "802.3ad" "encap3+4"
+      "layer2" "layer3+4" "layer2+3" "encap2+3" "encap3+4"
     ])
     (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
+    (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
+    (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
+    (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
+    (assertValueOneOf "ARPAllTargets" ["any" "all"])
+    (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
+    (assertRange "ResendIGMP" 0 255)
+    (assertRange "PacketsPerSlave" 0 65535)
+    (assertRange "GratuitousARP" 0 255)
+    (assertValueOneOf "AllSlavesActive" boolValues)
   ];
 
   checkNetwork = checkUnitConfig "Network" [
     (assertOnlyFields [
-      "Description" "DHCP" "DHCPServer" "IPForward" "IPMasquerade" "IPv4LL" "IPv4LLRoute"
-      "LLMNR" "MulticastDNS" "Domains" "Bridge" "Bond" "IPv6PrivacyExtensions"
+      "Description" "DHCP" "DHCPServer" "LinkLocalAddressing" "IPv4LLRoute"
+      "IPv6Token" "LLMNR" "MulticastDNS" "DNSOverTLS" "DNSSEC"
+      "DNSSECNegativeTrustAnchors" "LLDP" "EmitLLDP" "BindCarrier" "Address"
+      "Gateway" "DNS" "Domains" "NTP" "IPForward" "IPMasquerade"
+      "IPv6PrivacyExtensions" "IPv6AcceptRA" "IPv6DuplicateAddressDetection"
+      "IPv6HopLimit" "IPv4ProxyARP" "IPv6ProxyNDP" "IPv6ProxyNDPAddress"
+      "IPv6PrefixDelegation" "IPv6MTUBytes" "Bridge" "Bond" "VRF" "VLAN"
+      "IPVLAN" "MACVLAN" "VXLAN" "Tunnel" "ActiveSlave" "PrimarySlave"
+      "ConfigureWithoutCarrier"
     ])
-    (assertValueOneOf "DHCP" ["both" "none" "v4" "v6"])
+    # Note: For DHCP the values both, none, v4, v6 are deprecated
+    (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6" "both" "none" "v4" "v6"])
     (assertValueOneOf "DHCPServer" boolValues)
+    (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6"])
+    (assertValueOneOf "IPv4LLRoute" boolValues)
+    (assertValueOneOf "LLMNR" ["yes" "resolve" "no"])
+    (assertValueOneOf "MulticastDNS" ["yes" "resolve" "no"])
+    (assertValueOneOf "DNSOverTLS" ["opportunistic" "no"])
+    (assertValueOneOf "DNSSEC" ["yes" "allow-downgrade" "no"])
+    (assertValueOneOf "LLDP" ["yes" "routers-only" "no"])
+    (assertValueOneOf "EmitLLDP" ["yes" "no" "nearest-bridge" "non-tpmr-bridge" "customer-bridge"])
     (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"])
     (assertValueOneOf "IPMasquerade" boolValues)
-    (assertValueOneOf "IPv4LL" boolValues)
-    (assertValueOneOf "IPv4LLRoute" boolValues)
-    (assertValueOneOf "LLMNR" boolValues)
-    (assertValueOneOf "MulticastDNS" boolValues)
     (assertValueOneOf "IPv6PrivacyExtensions" ["yes" "no" "prefer-public" "kernel"])
+    (assertValueOneOf "IPv6AcceptRA" boolValues)
+    (assertValueOneOf "IPv4ProxyARP" boolValues)
+    (assertValueOneOf "IPv6ProxyNDP" boolValues)
+    (assertValueOneOf "IPv6PrefixDelegation" boolValues)
+    (assertValueOneOf "ActiveSlave" boolValues)
+    (assertValueOneOf "PrimarySlave" boolValues)
+    (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
   ];
 
   checkAddress = checkUnitConfig "Address" [
-    (assertOnlyFields ["Address" "Peer" "Broadcast" "Label"])
+    (assertOnlyFields [
+      "Address" "Peer" "Broadcast" "Label" "PreferredLifetime" "Scope"
+      "HomeAddress" "DuplicateAddressDetection" "ManageTemporaryAddress"
+      "PrefixRoute" "AutoJoin"
+    ])
     (assertHasField "Address")
+    (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
+    (assertValueOneOf "HomeAddress" boolValues)
+    (assertValueOneOf "DuplicateAddressDetection" boolValues)
+    (assertValueOneOf "ManageTemporaryAddress" boolValues)
+    (assertValueOneOf "PrefixRoute" boolValues)
+    (assertValueOneOf "AutoJoin" boolValues)
   ];
 
   checkRoute = checkUnitConfig "Route" [
-    (assertOnlyFields ["Gateway" "Destination" "Metric"])
+    (assertOnlyFields [
+      "Gateway" "GatewayOnlink" "Destination" "Source" "Metric"
+      "IPv6Preference" "Scope" "PreferredSource" "Table" "Protocol" "Type"
+      "InitialCongestionWindow" "InitialAdvertisedReceiveWindow" "QuickAck"
+      "MTUBytes"
+    ])
     (assertHasField "Gateway")
   ];
 
   checkDhcp = checkUnitConfig "DHCP" [
     (assertOnlyFields [
-      "UseDNS" "UseMTU" "SendHostname" "UseHostname" "UseDomains" "UseRoutes"
-      "CriticalConnections" "VendorClassIdentifier" "RequestBroadcast"
-      "RouteMetric"
+      "UseDNS" "UseNTP" "UseMTU" "Anonymize" "SendHostname" "UseHostname"
+      "Hostname" "UseDomains" "UseRoutes" "UseTimezone" "CriticalConnection"
+      "ClientIdentifier" "VendorClassIdentifier" "UserClass" "DUIDType"
+      "DUIDRawData" "IAID" "RequestBroadcast" "RouteMetric" "RouteTable"
+      "ListenPort" "RapidCommit"
     ])
     (assertValueOneOf "UseDNS" boolValues)
+    (assertValueOneOf "UseNTP" boolValues)
     (assertValueOneOf "UseMTU" boolValues)
+    (assertValueOneOf "Anonymize" boolValues)
     (assertValueOneOf "SendHostname" boolValues)
     (assertValueOneOf "UseHostname" boolValues)
-    (assertValueOneOf "UseDomains" boolValues)
+    (assertValueOneOf "UseDomains" ["yes" "no" "route"])
     (assertValueOneOf "UseRoutes" boolValues)
-    (assertValueOneOf "CriticalConnections" boolValues)
+    (assertValueOneOf "UseTimezone" boolValues)
+    (assertValueOneOf "CriticalConnection" boolValues)
     (assertValueOneOf "RequestBroadcast" boolValues)
+    (assertRange "RouteTable" 0 4294967295)
+    (assertValueOneOf "RapidCommit" boolValues)
   ];
 
   checkDhcpServer = checkUnitConfig "DHCPServer" [
     (assertOnlyFields [
       "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec"
-      "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitTimezone" "Timezone"
+      "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitRouter" "EmitTimezone" "Timezone"
     ])
     (assertValueOneOf "EmitDNS" boolValues)
     (assertValueOneOf "EmitNTP" boolValues)
+    (assertValueOneOf "EmitRouter" boolValues)
     (assertValueOneOf "EmitTimezone" boolValues)
   ];
 
@@ -461,6 +559,36 @@ let
       '';
     };
 
+    bridge = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of bridge interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    bond = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of bond interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
+    vrf = mkOption {
+      default = [ ];
+      type = types.listOf types.str;
+      description = ''
+        A list of vrf interfaces to be added to the network section of the
+        unit.  See <citerefentry><refentrytitle>systemd.network</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> for details.
+      '';
+    };
+
     vlan = mkOption {
       default = [ ];
       type = types.listOf types.str;
@@ -619,6 +747,9 @@ let
           ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
           ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
           ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
+          ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
+          ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
+          ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
           ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
           ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
           ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index 2caab69cbb95..f58b68cb3353 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -179,7 +179,7 @@ let
         fi
       done
 
-      if [ -z "${toString pkgs.stdenv.isCross}" ]; then
+      if [ -z "${toString (pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform)}" ]; then
       # Make sure that the patchelf'ed binaries still work.
       echo "testing patched programs..."
       $out/bin/ash -c 'echo hello world' | grep "hello world"
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 2d3d80a91bc6..12e029ae57f8 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -65,6 +65,7 @@ let
       "systemd-user-sessions.service"
       "dbus-org.freedesktop.machine1.service"
       "user@.service"
+      "user-runtime-dir@.service"
 
       # Journal.
       "systemd-journald.socket"
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 7120856387ef..2b3b09d725c7 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -23,12 +23,8 @@ let
 
   kernel = config.boot.kernelPackages;
 
-  packages = if config.boot.zfs.enableLegacyCrypto then {
-    spl = kernel.splLegacyCrypto;
-    zfs = kernel.zfsLegacyCrypto;
-    zfsUser = pkgs.zfsLegacyCrypto;
-  } else if config.boot.zfs.enableUnstable then {
-    spl = kernel.splUnstable;
+  packages = if config.boot.zfs.enableUnstable then {
+    spl = null;
     zfs = kernel.zfsUnstable;
     zfsUser = pkgs.zfsUnstable;
   } else {
@@ -117,27 +113,6 @@ in
           '';
       };
 
-      enableLegacyCrypto = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enabling this option will allow you to continue to use the old format for
-          encrypted datasets. With the inclusion of stability patches the format of
-          encrypted datasets has changed. They can still be accessed and mounted but
-          in read-only mode mounted. It is highly recommended to convert them to
-          the new format.
-
-          This option is only for convenience to people that cannot convert their
-          datasets to the new format yet and it will be removed in due time.
-
-          For migration strategies from old format to this new one, check the Wiki:
-          https://nixos.wiki/wiki/NixOS_on_ZFS#Encrypted_Dataset_Format_Change
-
-          See https://github.com/zfsonlinux/zfs/pull/6864 for more details about
-          the stability patches.
-          '';
-      };
-
       extraPools = mkOption {
         type = types.listOf types.str;
         default = [];
@@ -350,12 +325,12 @@ in
       virtualisation.lxd.zfsSupport = true;
 
       boot = {
-        kernelModules = [ "spl" "zfs" ] ;
-        extraModulePackages = with packages; [ spl zfs ];
+        kernelModules = [ "zfs" ] ++ optional (!cfgZfs.enableUnstable) "spl";
+        extraModulePackages = with packages; [ zfs ] ++ optional (!cfgZfs.enableUnstable) spl;
       };
 
       boot.initrd = mkIf inInitrd {
-        kernelModules = [ "spl" "zfs" ];
+        kernelModules = [ "zfs" ] ++ optional (!cfgZfs.enableUnstable) "spl";
         extraUtilsCommands =
           ''
             copy_bin_and_libs ${packages.zfsUser}/sbin/zfs
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 0abf7b11703c..4e9c87222d0a 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -156,9 +156,6 @@ let
             --partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \
             --hybrid 2 \
             --recompute-chs /dev/vda
-          . /sys/class/block/vda2/uevent
-          mknod /dev/vda2 b $MAJOR $MINOR
-          . /sys/class/block/vda/uevent
           ${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2
           export MTOOLS_SKIP_CHECK=1
           ${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot
diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix
index b69860a199a2..60779579402c 100644
--- a/nixos/modules/virtualisation/virtualbox-host.nix
+++ b/nixos/modules/virtualisation/virtualbox-host.nix
@@ -6,7 +6,8 @@ let
   cfg = config.virtualisation.virtualbox.host;
 
   virtualbox = cfg.package.override {
-    inherit (cfg) enableExtensionPack enableHardening headless;
+    inherit (cfg) enableHardening headless;
+    extensionPack = if cfg.enableExtensionPack then pkgs.virtualboxExtpack else null;
   };
 
   kernelModules = config.boot.kernelPackages.virtualbox.override {
@@ -28,6 +29,17 @@ in
       '';
     };
 
+    enableExtensionPack = mkEnableOption "VirtualBox extension pack" // {
+      description = ''
+        Whether to install the Oracle Extension Pack for VirtualBox.
+
+        <important><para>
+          You must set <literal>nixpkgs.config.allowUnfree = true</literal> in
+          order to use this.  This requires you accept the VirtualBox PUEL.
+        </para></important>
+      '';
+    };
+
     package = mkOption {
       type = types.package;
       default = pkgs.virtualbox;
@@ -45,8 +57,6 @@ in
       '';
     };
 
-    enableExtensionPack = mkEnableOption "VirtualBox extension pack";
-
     enableHardening = mkOption {
       type = types.bool;
       default = true;
diff --git a/nixos/release.nix b/nixos/release.nix
index 1d1f8009f27c..b25c684ff47a 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -83,7 +83,7 @@ let
     in
       tarball //
         { meta = {
-            description = "NixOS system tarball for ${system} - ${stdenv.platform.name}";
+            description = "NixOS system tarball for ${system} - ${stdenv.hostPlatform.platform.name}";
             maintainers = map (x: lib.maintainers.${x}) maintainers;
           };
           inherit config;
@@ -106,7 +106,7 @@ let
     let
       configEvaled = import lib/eval-config.nix config;
       build = configEvaled.config.system.build;
-      kernelTarget = configEvaled.pkgs.stdenv.platform.kernelTarget;
+      kernelTarget = configEvaled.pkgs.stdenv.hostPlatform.platform.kernelTarget;
     in
       pkgs.symlinkJoin {
         name = "netboot";
diff --git a/nixos/tests/ec2.nix b/nixos/tests/ec2.nix
index f585fa2ec237..8271747ccc63 100644
--- a/nixos/tests/ec2.nix
+++ b/nixos/tests/ec2.nix
@@ -68,7 +68,9 @@ let
           # again when it deletes link-local addresses.) Ideally we'd
           # turn off the DHCP server, but qemu does not have an option
           # to do that.
-          my $startCommand = "qemu-kvm -m 768 -net nic,vlan=0,model=virtio -net 'user,vlan=0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'";
+          my $startCommand = "qemu-kvm -m 768";
+          $startCommand .= " -device virtio-net-pci,netdev=vlan0";
+          $startCommand .= " -netdev 'user,id=vlan0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'";
           $startCommand .= " -drive file=$diskImage,if=virtio,werror=report";
           $startCommand .= " \$QEMU_OPTS";
 
diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix
index 4c5c441ca265..15be72b80bba 100644
--- a/nixos/tests/elk.nix
+++ b/nixos/tests/elk.nix
@@ -63,6 +63,33 @@ let
                 package = elk.kibana;
                 elasticsearch.url = esUrl;
               };
+
+              elasticsearch-curator = {
+                enable = true;
+                actionYAML = ''
+                ---
+                actions:
+                  1:
+                    action: delete_indices
+                    description: >-
+                      Delete indices older than 1 second (based on index name), for logstash-
+                      prefixed indices. Ignore the error if the filter does not result in an
+                      actionable list of indices (ignore_empty_list) and exit cleanly.
+                    options:
+                      ignore_empty_list: True
+                      disable_action: False
+                    filters:
+                    - filtertype: pattern
+                      kind: prefix
+                      value: logstash-
+                    - filtertype: age
+                      source: name
+                      direction: older
+                      timestring: '%Y.%m.%d'
+                      unit: seconds
+                      unit_count: 1
+                '';
+              };
             };
           };
       };
@@ -91,6 +118,11 @@ let
       # See if logstash messages arive in elasticsearch.
       $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"flowers\"}}}' | jq .hits.total | grep -v 0");
       $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"dragons\"}}}' | jq .hits.total | grep 0");
+
+      # Test elasticsearch-curator.
+      $one->systemctl("stop logstash");
+      $one->systemctl("start elasticsearch-curator");
+      $one->waitUntilSucceeds("! curl --silent --show-error '${esUrl}/_cat/indices' | grep logstash | grep -q ^$1");
     '';
   };
 in mapAttrs mkElkTest {
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 0c027eaca619..2d74b59bca46 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -2,7 +2,8 @@ import ./make-test.nix ({ pkgs, ... }:
 
 let
   configDir = "/var/lib/foobar";
-  apiPassword = "secret";
+  apiPassword = "some_secret";
+  mqttPassword = "another_secret";
 
 in {
   name = "home-assistant";
@@ -33,7 +34,9 @@ in {
             };
             frontend = { };
             http.api_password = apiPassword;
-            mqtt = { }; # Use hbmqtt as broker
+            mqtt = { # Use hbmqtt as broker
+              password = mqttPassword;
+            };
             binary_sensor = [
               {
                 platform = "mqtt";
@@ -62,7 +65,7 @@ in {
 
     # Toggle a binary sensor using MQTT
     $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"off\"'");
-    $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${apiPassword}' -m let_there_be_light");
+    $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${mqttPassword}' -m let_there_be_light");
     $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"on\"'");
 
     # Print log to ease debugging
diff --git a/nixos/tests/hydra/default.nix b/nixos/tests/hydra/default.nix
index 98d99811f3c0..db4e97e0039b 100644
--- a/nixos/tests/hydra/default.nix
+++ b/nixos/tests/hydra/default.nix
@@ -2,14 +2,11 @@ import ../make-test.nix ({ pkgs, ...} :
 
 let
    trivialJob = pkgs.writeTextDir "trivial.nix" ''
-     with import <nix/config.nix>;
-
      { trivial = builtins.derivation {
          name = "trivial";
          system = "x86_64-linux";
-         PATH = coreutils;
-         builder = shell;
-         args = ["-c" "touch $out; exit 0"];
+         builder = "/bin/sh";
+         args = ["-c" "echo success > $out; exit 0"];
        };
      }
    '';
@@ -27,7 +24,7 @@ let
 in {
   name = "hydra-init-localdb";
   meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ pstn lewo ];
+    maintainers = [ pstn lewo ma27 ];
   };
 
   machine =
@@ -50,6 +47,8 @@ in {
           hostName = "localhost";
           systems = [ "x86_64-linux" ];
         }];
+
+        binaryCaches = [];
       };
     };
 
@@ -74,5 +73,5 @@ in {
       $machine->succeed("create-trivial-project.sh");
 
       $machine->waitUntilSucceeds('curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" |  jq .buildstatus | xargs test 0 -eq');
-     '';
+    '';
 })
diff --git a/nixos/tests/matrix-synapse.nix b/nixos/tests/matrix-synapse.nix
index 113fb622588b..8504a7c0d057 100644
--- a/nixos/tests/matrix-synapse.nix
+++ b/nixos/tests/matrix-synapse.nix
@@ -6,12 +6,13 @@ import ./make-test.nix ({ pkgs, ... } : {
   };
 
   nodes = {
-    server_postgres = args: {
+    # Since 0.33.0, matrix-synapse doesn't allow underscores in server names
+    serverpostgres = args: {
       services.matrix-synapse.enable = true;
       services.matrix-synapse.database_type = "psycopg2";
     };
 
-    server_sqlite = args: {
+    serversqlite = args: {
       services.matrix-synapse.enable = true;
       services.matrix-synapse.database_type = "sqlite3";
     };
@@ -19,12 +20,12 @@ import ./make-test.nix ({ pkgs, ... } : {
 
   testScript = ''
     startAll;
-    $server_postgres->waitForUnit("matrix-synapse.service");
-    $server_postgres->waitUntilSucceeds("curl -Lk https://localhost:8448/");
-    $server_postgres->requireActiveUnit("postgresql.service");
-    $server_sqlite->waitForUnit("matrix-synapse.service");
-    $server_sqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/");
-    $server_sqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]");
+    $serverpostgres->waitForUnit("matrix-synapse.service");
+    $serverpostgres->waitUntilSucceeds("curl -Lk https://localhost:8448/");
+    $serverpostgres->requireActiveUnit("postgresql.service");
+    $serversqlite->waitForUnit("matrix-synapse.service");
+    $serversqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/");
+    $serversqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]");
   '';
 
 })
diff --git a/nixos/tests/munin.nix b/nixos/tests/munin.nix
index eb91d4d630bc..9f66005292ab 100644
--- a/nixos/tests/munin.nix
+++ b/nixos/tests/munin.nix
@@ -12,16 +12,23 @@ import ./make-test.nix ({ pkgs, ...} : {
       { config, ... }:
         {
           services = {
-           munin-node.enable = true;
-           munin-cron = {
+           munin-node = {
              enable = true;
-             hosts = ''
-               [${config.networking.hostName}]
-               address localhost
+             # disable a failing plugin to prevent irrelevant error message, see #23049
+             extraConfig = ''
+               ignore_file ^apc_nis$
              '';
            };
+           munin-cron = {
+            enable = true;
+            hosts = ''
+              [${config.networking.hostName}]
+              address localhost
+            '';
+           };
           };
-          systemd.services.munin-node.serviceConfig.TimeoutStartSec = "3min";
+          # long timeout to prevent hydra failure on high load
+          systemd.services.munin-node.serviceConfig.TimeoutStartSec = "10min";
         };
     };
 
@@ -29,7 +36,10 @@ import ./make-test.nix ({ pkgs, ...} : {
     startAll;
 
     $one->waitForUnit("munin-node.service");
+    # make sure the node is actually listening
+    $one->waitForOpenPort(4949);
     $one->succeed('systemctl start munin-cron');
+    # wait for munin-cron output
     $one->waitForFile("/var/lib/munin/one/one-uptime-uptime-g.rrd");
     $one->waitForFile("/var/www/munin/one/index.html");
   '';
diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix
index eb45db6f04c3..9bd147968e4b 100644
--- a/nixos/tests/netdata.nix
+++ b/nixos/tests/netdata.nix
@@ -20,6 +20,9 @@ import ./make-test.nix ({ pkgs, ...} : {
 
     $netdata->waitForUnit("netdata.service");
 
+    # wait for the service to listen before sending a request
+    $netdata->waitForOpenPort(19999);
+
     # check if the netdata main page loads.
     $netdata->succeed("curl --fail http://localhost:19999/");
 
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index cd5d537a3be7..ff088ad2621b 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -448,8 +448,8 @@ let
 
       testScript = ''
         my $targetList = <<'END';
-        tap0: tap UNKNOWN_FLAGS:800 user 0
-        tun0: tun UNKNOWN_FLAGS:800 user 0
+        tap0: tap persist user 0
+        tun0: tun persist user 0
         END
 
         # Wait for networking to come up
@@ -552,15 +552,15 @@ let
 
       testScript = ''
         my $targetIPv4Table = <<'END';
-        10.0.0.0/16 scope link mtu 1500 
+        10.0.0.0/16 proto static scope link mtu 1500 
         192.168.1.0/24 proto kernel scope link src 192.168.1.2 
-        192.168.2.0/24 via 192.168.1.1 
+        192.168.2.0/24 via 192.168.1.1 proto static 
         END
 
         my $targetIPv6Table = <<'END';
         2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium
-        2001:1470:fffd:2098::/64 via fdfd:b3f0::1 metric 1024 pref medium
-        fdfd:b3f0::/48 metric 1024 pref medium
+        2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium
+        fdfd:b3f0::/48 proto static metric 1024 pref medium
         END
 
         $machine->start;
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index 008dab8459c8..4207112cf16a 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -293,6 +293,11 @@ let
     "--hostonlyadapter2 vboxnet0"
   ];
 
+  # The VirtualBox Oracle Extension Pack lets you use USB 3.0 (xHCI).
+  enableExtensionPackVMFlags = [
+    "--usbxhci on"
+  ];
+
   dhcpScript = pkgs: ''
     ${pkgs.dhcp}/bin/dhclient \
       -lf /run/dhcp.leases \
@@ -323,13 +328,17 @@ let
     headless.services.xserver.enable = false;
   };
 
-  mkVBoxTest = name: testScript: makeTest {
+  vboxVMsWithExtpack = mapAttrs createVM {
+    testExtensionPack.vmFlags = enableExtensionPackVMFlags;
+  };
+
+  mkVBoxTest = useExtensionPack: vms: name: testScript: makeTest {
     name = "virtualbox-${name}";
 
     machine = { lib, config, ... }: {
       imports = let
         mkVMConf = name: val: val.machine // { key = "${name}-config"; };
-        vmConfigs = mapAttrsToList mkVMConf vboxVMs;
+        vmConfigs = mapAttrsToList mkVMConf vms;
       in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs;
       virtualisation.memorySize = 2048;
       virtualisation.virtualbox.host.enable = true;
@@ -337,6 +346,8 @@ let
       users.users.alice.extraGroups = let
         inherit (config.virtualisation.virtualbox.host) enableHardening;
       in lib.mkIf enableHardening (lib.singleton "vboxusers");
+      virtualisation.virtualbox.host.enableExtensionPack = useExtensionPack;
+      nixpkgs.config.allowUnfree = useExtensionPack;
     };
 
     testScript = ''
@@ -353,7 +364,7 @@ let
         return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n";
       }
 
-      ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)}
+      ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vms)}
 
       $machine->waitForX;
 
@@ -363,11 +374,11 @@ let
     '';
 
     meta = with pkgs.stdenv.lib.maintainers; {
-      maintainers = [ aszlig wkennington ];
+      maintainers = [ aszlig wkennington cdepillabout ];
     };
   };
 
-in mapAttrs mkVBoxTest {
+in mapAttrs (mkVBoxTest false vboxVMs) {
   simple-gui = ''
     createVM_simple;
     $machine->succeed(ru "VirtualBox &");
@@ -473,4 +484,22 @@ in mapAttrs mkVBoxTest {
     destroyVM_test1;
     destroyVM_test2;
   '';
+} // mapAttrs (mkVBoxTest true vboxVMsWithExtpack) {
+  enable-extension-pack = ''
+    createVM_testExtensionPack;
+    vbm("startvm testExtensionPack");
+    waitForStartup_testExtensionPack;
+    $machine->screenshot("cli_started");
+    waitForVMBoot_testExtensionPack;
+    $machine->screenshot("cli_booted");
+
+    $machine->nest("Checking for privilege escalation", sub {
+      $machine->fail("test -e '/root/VirtualBox VMs'");
+      $machine->fail("test -e '/root/.config/VirtualBox'");
+      $machine->succeed("test -e '/home/alice/VirtualBox VMs'");
+    });
+
+    shutdownVM_testExtensionPack;
+    destroyVM_testExtensionPack;
+  '';
 }
diff --git a/nixos/tests/wordpress.nix b/nixos/tests/wordpress.nix
index 2c0bbbfd7161..5003e25a7d5b 100644
--- a/nixos/tests/wordpress.nix
+++ b/nixos/tests/wordpress.nix
@@ -18,9 +18,6 @@ import ./make-test.nix ({ pkgs, ... }:
             enable = true;
             logPerVirtualHost = true;
             adminAddr="js@lastlog.de";
-            extraModules = [
-              { name = "php7"; path = "${pkgs.php}/modules/libphp7.so"; }
-            ];
 
             virtualHosts = [
               {
@@ -30,7 +27,7 @@ import ./make-test.nix ({ pkgs, ... }:
                     {
                       serviceType = "wordpress";
                       dbPassword = "wordpress";
-                      wordpressUploads = "/data/uploads";
+                      dbHost = "127.0.0.1";
                       languages = [ "de_DE" "en_GB" ];
                     }
                   ];