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/configuration/linux-kernel.xml4
-rw-r--r--nixos/doc/manual/development/option-types.xml9
-rwxr-xr-xnixos/doc/manual/development/releases.xml2
-rw-r--r--nixos/doc/manual/installation/installing-from-other-distro.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1509.xml4
-rw-r--r--nixos/doc/manual/release-notes/rl-1809.xml14
-rw-r--r--nixos/maintainers/scripts/ec2/amazon-image.nix5
-rw-r--r--nixos/modules/config/iproute2.nix23
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl2
-rw-r--r--nixos/modules/installer/tools/tools.nix2
-rw-r--r--nixos/modules/installer/virtualbox-demo.nix1
-rw-r--r--nixos/modules/misc/ids.nix8
-rw-r--r--nixos/modules/misc/version.nix17
-rw-r--r--nixos/modules/module-list.nix8
-rw-r--r--nixos/modules/profiles/base.nix1
-rw-r--r--nixos/modules/programs/sedutil.nix18
-rw-r--r--nixos/modules/programs/shell.nix2
-rw-r--r--nixos/modules/programs/xss-lock.nix26
-rw-r--r--nixos/modules/rename.nix2
-rw-r--r--nixos/modules/security/pam.nix4
-rw-r--r--nixos/modules/services/audio/slimserver.nix3
-rw-r--r--nixos/modules/services/cluster/kubernetes/dashboard.nix2
-rw-r--r--nixos/modules/services/databases/mysql.nix2
-rw-r--r--nixos/modules/services/databases/postgresql.nix10
-rw-r--r--nixos/modules/services/desktops/flatpak.nix52
-rw-r--r--nixos/modules/services/desktops/flatpak.xml53
-rw-r--r--nixos/modules/services/mail/dovecot.nix6
-rw-r--r--nixos/modules/services/misc/gitea.nix69
-rw-r--r--nixos/modules/services/misc/home-assistant.nix8
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix2
-rw-r--r--nixos/modules/services/misc/mesos-slave.nix2
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/misc/sysprof.nix19
-rw-r--r--nixos/modules/services/network-filesystems/beegfs.nix2
-rw-r--r--nixos/modules/services/network-filesystems/ipfs.nix2
-rw-r--r--nixos/modules/services/networking/cjdns.nix3
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix4
-rw-r--r--nixos/modules/services/networking/gnunet.nix14
-rw-r--r--nixos/modules/services/networking/hostapd.nix5
-rw-r--r--nixos/modules/services/networking/keepalived/default.nix62
-rw-r--r--nixos/modules/services/networking/keepalived/vrrp-instance-options.nix (renamed from nixos/modules/services/networking/keepalived/vrrp-options.nix)14
-rw-r--r--nixos/modules/services/networking/keepalived/vrrp-script-options.nix64
-rw-r--r--nixos/modules/services/networking/radicale.nix4
-rw-r--r--nixos/modules/services/networking/stubby.nix214
-rw-r--r--nixos/modules/services/networking/wireguard.nix4
-rw-r--r--nixos/modules/services/web-apps/nexus.nix40
-rw-r--r--nixos/modules/services/web-servers/caddy.nix2
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/desktop-managers/xterm.nix1
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix3
-rw-r--r--nixos/modules/services/x11/window-managers/stumpwm.nix4
-rw-r--r--nixos/modules/system/boot/coredump.nix7
-rw-r--r--nixos/modules/system/boot/grow-partition.nix2
-rw-r--r--nixos/modules/system/boot/luksroot.nix1
-rw-r--r--nixos/modules/system/boot/plymouth.nix3
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh59
-rw-r--r--nixos/modules/system/boot/systemd-lib.nix17
-rw-r--r--nixos/modules/system/boot/systemd-unit-options.nix2
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix2
-rw-r--r--nixos/modules/tasks/scsi-link-power-management.nix26
-rw-r--r--nixos/modules/testing/test-instrumentation.nix6
-rw-r--r--nixos/modules/virtualisation/amazon-image.nix7
-rw-r--r--nixos/modules/virtualisation/amazon-options.nix2
-rw-r--r--nixos/modules/virtualisation/containers.nix4
-rw-r--r--nixos/modules/virtualisation/qemu-guest-agent.nix36
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix35
-rw-r--r--nixos/release-combined.nix7
-rw-r--r--nixos/release.nix10
-rw-r--r--nixos/tests/acme.nix4
-rw-r--r--nixos/tests/common/letsencrypt.nix4
-rw-r--r--nixos/tests/containers-imperative.nix4
-rw-r--r--nixos/tests/containers-ipv4.nix1
-rw-r--r--nixos/tests/dnscrypt-proxy.nix3
-rw-r--r--nixos/tests/flatpak.nix23
-rw-r--r--nixos/tests/graphite.nix20
-rw-r--r--nixos/tests/hardened.nix8
-rw-r--r--nixos/tests/home-assistant.nix7
-rw-r--r--nixos/tests/installer.nix1
-rw-r--r--nixos/tests/kafka.nix69
-rw-r--r--nixos/tests/kafka_0_10.nix48
-rw-r--r--nixos/tests/kafka_0_11.nix48
-rw-r--r--nixos/tests/kafka_0_9.nix48
-rw-r--r--nixos/tests/kafka_1_0.nix48
-rw-r--r--nixos/tests/mesos.nix4
-rw-r--r--nixos/tests/mysql-backup.nix16
-rw-r--r--nixos/tests/mysql-replication.nix11
-rw-r--r--nixos/tests/nexus.nix18
-rw-r--r--nixos/tests/plotinus.nix10
-rw-r--r--nixos/tests/radicale.nix4
-rw-r--r--nixos/tests/statsd.nix19
-rw-r--r--nixos/tests/xdg-desktop-portal.nix17
-rw-r--r--nixos/tests/xss-lock.nix25
94 files changed, 1149 insertions, 367 deletions
diff --git a/nixos/doc/manual/configuration/linux-kernel.xml b/nixos/doc/manual/configuration/linux-kernel.xml
index 0990e9d932ba..6502aaec83e5 100644
--- a/nixos/doc/manual/configuration/linux-kernel.xml
+++ b/nixos/doc/manual/configuration/linux-kernel.xml
@@ -50,9 +50,9 @@ nixpkgs.config.packageOverrides = pkgs:
 <xref linkend="opt-boot.kernelModules"/> = [ "fuse" "kvm-intel" "coretemp" ];
 </programlisting>
   If the module is required early during the boot (e.g. to mount the root file
-  system), you can use <xref linkend="opt-boot.initrd.extraKernelModules"/>:
+  system), you can use <xref linkend="opt-boot.initrd.kernelModules"/>:
 <programlisting>
-<xref linkend="opt-boot.initrd.extraKernelModules"/> = [ "cifs" ];
+<xref linkend="opt-boot.initrd.kernelModules"/> = [ "cifs" ];
 </programlisting>
   This causes the specified modules and their dependencies to be added to the
   initial ramdisk.
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
index 7969d8124738..5cb747e6d9f1 100644
--- a/nixos/doc/manual/development/option-types.xml
+++ b/nixos/doc/manual/development/option-types.xml
@@ -22,6 +22,15 @@
 
   <variablelist>
    <varlistentry>
+    <term><varname>types.attrs</varname>
+    </term>
+    <listitem>
+     <para>
+      A free-form attribute set.
+     </para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
     <term><varname>types.bool</varname>
     </term>
     <listitem>
diff --git a/nixos/doc/manual/development/releases.xml b/nixos/doc/manual/development/releases.xml
index d4e5ff3f4312..863110a1c7ca 100755
--- a/nixos/doc/manual/development/releases.xml
+++ b/nixos/doc/manual/development/releases.xml
@@ -70,7 +70,7 @@
     <listitem>
      <para>
       <link xlink:href="https://github.com/NixOS/nixpkgs/compare/bdf161ed8d21...6b63c4616790">
-      Bump the <literal>system.defaultChannel</literal> attribute in
+      Bump the <literal>system.nixos.defaultChannel</literal> attribute in
       <literal>nixos/modules/misc/version.nix</literal> </link>
      </para>
     </listitem>
diff --git a/nixos/doc/manual/installation/installing-from-other-distro.xml b/nixos/doc/manual/installation/installing-from-other-distro.xml
index 8b0c350b064d..c55aa90267fb 100644
--- a/nixos/doc/manual/installation/installing-from-other-distro.xml
+++ b/nixos/doc/manual/installation/installing-from-other-distro.xml
@@ -47,7 +47,7 @@
     Short version:
    </para>
 <screen>
-$ bash &lt;(curl https://nixos.org/nix/install)
+$ curl https://nixos.org/nix/install | sh
 $ . $HOME/.nix-profile/etc/profile.d/nix.sh # …or open a fresh shell</screen>
    <para>
     More details in the
diff --git a/nixos/doc/manual/release-notes/rl-1509.xml b/nixos/doc/manual/release-notes/rl-1509.xml
index e500c9d63422..734bc076b852 100644
--- a/nixos/doc/manual/release-notes/rl-1509.xml
+++ b/nixos/doc/manual/release-notes/rl-1509.xml
@@ -433,9 +433,9 @@ system.autoUpgrade.enable = true;
      default. If you have existing systems with such host keys and want to
      continue to use them, please set
 <programlisting>
-system.stateVersion = "14.12";
+system.nixos.stateVersion = "14.12";
 </programlisting>
-     The new option <option>system.stateVersion</option> ensures that certain
+     The new option <option>system.nixos.stateVersion</option> ensures that certain
      configuration changes that could break existing systems (such as the
      <command>sshd</command> host key setting) will maintain compatibility with
      the specified NixOS release. NixOps sets the state version of existing
diff --git a/nixos/doc/manual/release-notes/rl-1809.xml b/nixos/doc/manual/release-notes/rl-1809.xml
index 01b5e9d77460..0ae630945db2 100644
--- a/nixos/doc/manual/release-notes/rl-1809.xml
+++ b/nixos/doc/manual/release-notes/rl-1809.xml
@@ -53,7 +53,10 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
 
   <itemizedlist>
    <listitem>
-    <para></para>
+     <para>When enabled the <literal>iproute2</literal> will copy the files
+       expected by ip route (e.g., <filename>rt_tables</filename>) in
+       <filename>/run/iproute2</filename>. This allows to write aliases for
+       routing tables for instance.</para>
    </listitem>
   </itemizedlist>
  </section>
@@ -103,8 +106,13 @@ $ nix-instantiate -E '(import &lt;nixpkgsunstable&gt; {}).gitFull'
    </listitem>
    <listitem>
     <para>
-     <literal>googleearth</literal> has been removed from Nixpkgs. Google does not provide
-     a stable URL for Nixpkgs to use to package this proprietary software.
+     <literal>gnucash</literal> has changed from version 2.4 to 3.x.
+     If you've been using <literal>gnucash</literal> (version 2.4) instead of
+     <literal>gnucash26</literal> (version 2.6) you must open your Gnucash 
+     data file(s) with <literal>gnucash26</literal> and then save them to
+     upgrade the file format. Then you may use your data file(s) with
+     Gnucash 3.x. See the upgrade <link xlink:href="https://wiki.gnucash.org/wiki/FAQ#Using_Different_Versions.2C_Up_And_Downgrade">documentation</link>.
+     Gnucash 2.4 is still available under the attribute <literal>gnucash24</literal>.
     </para>
    </listitem>
   </itemizedlist>
diff --git a/nixos/maintainers/scripts/ec2/amazon-image.nix b/nixos/maintainers/scripts/ec2/amazon-image.nix
index 972c04453aef..eeae27ede0f8 100644
--- a/nixos/maintainers/scripts/ec2/amazon-image.nix
+++ b/nixos/maintainers/scripts/ec2/amazon-image.nix
@@ -8,6 +8,11 @@ in {
 
   imports = [ ../../../modules/virtualisation/amazon-image.nix ];
 
+  # Required to provide good EBS experience,
+  # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html#timeout-nvme-ebs-volumes
+  # TODO change value to 4294967295 when kernel is updated to 4.15 or later
+  config.boot.kernelParams = [ "nvme_core.io_timeout=255" ];
+
   options.amazonImage = {
     name = mkOption {
       type = types.str;
diff --git a/nixos/modules/config/iproute2.nix b/nixos/modules/config/iproute2.nix
new file mode 100644
index 000000000000..881ad671a627
--- /dev/null
+++ b/nixos/modules/config/iproute2.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.networking.iproute2;
+  confDir = "/run/iproute2";
+in
+{
+  options.networking.iproute2.enable = mkEnableOption "copy IP route configuration files";
+
+  config = mkMerge [
+    ({ nixpkgs.config.iproute2.confDir = confDir; })
+
+    (mkIf cfg.enable {
+      system.activationScripts.iproute2 = ''
+        cp -R ${pkgs.iproute}/etc/iproute2 ${confDir}
+        chmod -R 664 ${confDir}
+        chmod +x ${confDir}
+      '';
+    })
+  ];
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
index 756c8751d00e..1ed56386e6e7 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -31,4 +31,6 @@ with lib;
 
   # Allow the user to log in as root without a password.
   users.extraUsers.root.initialHashedPassword = "";
+
+  system.nixos.stateVersion = mkDefault "18.03";
 }
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 74b61a64667e..a198c2d49b53 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -628,7 +628,7 @@ $bootLoaderConfig
   # compatible, in order to avoid breaking some software such as database
   # servers. You should change this only after NixOS release notes say you
   # should.
-  system.stateVersion = "${\(qw(@release@))}"; # Did you read the comment?
+  system.nixos.stateVersion = "${\(qw(@release@))}"; # Did you read the comment?
 
 }
 EOF
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index beac9e29d59c..42b00b2025d8 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -76,7 +76,7 @@ in
       ];
 
     system.build = {
-      inherit nixos-install nixos-prepare-root nixos-generate-config nixos-option nixos-rebuild nixos-enter;
+      inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter;
     };
 
   };
diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix
index 13a0d7f4f6ee..c40e30354206 100644
--- a/nixos/modules/installer/virtualbox-demo.nix
+++ b/nixos/modules/installer/virtualbox-demo.nix
@@ -21,4 +21,5 @@ with lib;
   services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" "modesetting" ];
 
   powerManagement.enable = false;
+  system.nixos.stateVersion = mkDefault "18.03";
 }
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index cc7d86849824..bb97c707bf65 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -1,6 +1,14 @@
 # This module defines the global list of uids and gids.  We keep a
 # central list to prevent id collisions.
 
+# IMPORTANT!
+# We only add static uids and gids for services where it is not feasible
+# to change uids/gids on service start, in example a service with a lot of
+# files. Please also check if the service is applicable for systemd's
+# DynamicUser option and does not need a uid/gid allocation at all.
+# Systemd can also change ownership of service directories using the
+# RuntimeDirectory/StateDirectory options.
+
 { config, pkgs, lib, ... }:
 
 {
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index 74c86443ab90..33d8a7861693 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ options, config, lib, pkgs, ... }:
 
 with lib;
 
@@ -12,29 +12,29 @@ in
 
 {
 
-  options.system = {
+  options.system.nixos = {
 
-    nixos.version = mkOption {
+    version = mkOption {
       internal = true;
       type = types.str;
       description = "The full NixOS version (e.g. <literal>16.03.1160.f2d4ee1</literal>).";
     };
 
-    nixos.release = mkOption {
+    release = mkOption {
       readOnly = true;
       type = types.str;
       default = trivial.release;
       description = "The NixOS release (e.g. <literal>16.03</literal>).";
     };
 
-    nixos.versionSuffix = mkOption {
+    versionSuffix = mkOption {
       internal = true;
       type = types.str;
       default = trivial.versionSuffix;
       description = "The NixOS version suffix (e.g. <literal>1160.f2d4ee1</literal>).";
     };
 
-    nixos.revision = mkOption {
+    revision = mkOption {
       internal = true;
       type = types.str;
       default = if pathIsDirectory gitRepo then commitIdFromGitRepo gitRepo
@@ -43,7 +43,7 @@ in
       description = "The Git revision from which this NixOS configuration was built.";
     };
 
-    nixos.codeName = mkOption {
+    codeName = mkOption {
       readOnly = true;
       type = types.str;
       description = "The NixOS release code name (e.g. <literal>Emu</literal>).";
@@ -76,6 +76,9 @@ in
 
   config = {
 
+    warnings = lib.optional (options.system.nixos.stateVersion.highestPrio > 1000)
+      "You don't have `system.nixos.stateVersion` explicitly set. Expect things to break.";
+
     system.nixos = {
       # These defaults are set here rather than up there so that
       # changing them would not rebuild the manual
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 6c4326046ef8..d5cfd87520c5 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -9,6 +9,7 @@
   ./config/fonts/ghostscript.nix
   ./config/gnu.nix
   ./config/i18n.nix
+  ./config/iproute2.nix
   ./config/krb5/default.nix
   ./config/ldap.nix
   ./config/networking.nix
@@ -101,6 +102,7 @@
   ./programs/qt5ct.nix
   ./programs/rootston.nix
   ./programs/screen.nix
+  ./programs/sedutil.nix
   ./programs/slock.nix
   ./programs/shadow.nix
   ./programs/shell.nix
@@ -120,6 +122,7 @@
   ./programs/wireshark.nix
   ./programs/xfs_quota.nix
   ./programs/xonsh.nix
+  ./programs/xss-lock.nix
   ./programs/yabar.nix
   ./programs/zsh/oh-my-zsh.nix
   ./programs/zsh/zsh.nix
@@ -214,6 +217,7 @@
   ./services/desktops/accountsservice.nix
   ./services/desktops/dleyna-renderer.nix
   ./services/desktops/dleyna-server.nix
+  ./services/desktops/flatpak.nix
   ./services/desktops/geoclue2.nix
   ./services/desktops/pipewire.nix
   ./services/desktops/gnome3/at-spi2-core.nix
@@ -380,6 +384,7 @@
   ./services/misc/sundtek.nix
   ./services/misc/svnserve.nix
   ./services/misc/synergy.nix
+  ./services/misc/sysprof.nix
   ./services/misc/taskserver
   ./services/misc/tzupdate.nix
   ./services/misc/uhub.nix
@@ -566,6 +571,7 @@
   ./services/networking/strongswan.nix
   ./services/networking/strongswan-swanctl/module.nix
   ./services/networking/stunnel.nix
+  ./services/networking/stubby.nix
   ./services/networking/supplicant.nix
   ./services/networking/supybot.nix
   ./services/networking/syncthing.nix
@@ -649,6 +655,7 @@
   ./services/web-apps/tt-rss.nix
   ./services/web-apps/selfoss.nix
   ./services/web-apps/quassel-webserver.nix
+  ./services/web-apps/youtrack.nix
   ./services/web-servers/apache-httpd/default.nix
   ./services/web-servers/caddy.nix
   ./services/web-servers/fcgiwrap.nix
@@ -780,6 +787,7 @@
   ./virtualisation/hyperv-guest.nix
   ./virtualisation/openvswitch.nix
   ./virtualisation/parallels-guest.nix
+  ./virtualisation/qemu-guest-agent.nix
   ./virtualisation/rkt.nix
   ./virtualisation/virtualbox-guest.nix
   ./virtualisation/virtualbox-host.nix
diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix
index 3bf06a951193..52481d90eab9 100644
--- a/nixos/modules/profiles/base.nix
+++ b/nixos/modules/profiles/base.nix
@@ -17,6 +17,7 @@
     pkgs.ddrescue
     pkgs.ccrypt
     pkgs.cryptsetup # needed for dm-crypt volumes
+    pkgs.mkpasswd # for generating password files
 
     # Some networking tools.
     pkgs.fuse
diff --git a/nixos/modules/programs/sedutil.nix b/nixos/modules/programs/sedutil.nix
new file mode 100644
index 000000000000..7efc80f4abba
--- /dev/null
+++ b/nixos/modules/programs/sedutil.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.sedutil;
+
+in {
+  options.programs.sedutil.enable = mkEnableOption "sedutil";
+
+  config = mkIf cfg.enable {
+    boot.kernelParams = [
+      "libata.allow_tpm=1"
+    ];
+
+    environment.systemPackages = with pkgs; [ sedutil ];
+  };
+}
diff --git a/nixos/modules/programs/shell.nix b/nixos/modules/programs/shell.nix
index d8845fd8f446..3504a8a924b0 100644
--- a/nixos/modules/programs/shell.nix
+++ b/nixos/modules/programs/shell.nix
@@ -40,7 +40,7 @@ in
 
           # Subscribe the root user to the NixOS channel by default.
           if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
-              echo "${config.system.defaultChannel} nixos" > $HOME/.nix-channels
+              echo "${config.system.nixos.defaultChannel} nixos" > $HOME/.nix-channels
           fi
 
           # Create the per-user garbage collector roots directory.
diff --git a/nixos/modules/programs/xss-lock.nix b/nixos/modules/programs/xss-lock.nix
new file mode 100644
index 000000000000..49d522c604f5
--- /dev/null
+++ b/nixos/modules/programs/xss-lock.nix
@@ -0,0 +1,26 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.xss-lock;
+in
+{
+  options.programs.xss-lock = {
+    enable = mkEnableOption "xss-lock";
+    lockerCommand = mkOption {
+      example = "xlock";
+      type = types.string;
+      description = "Locker to be used with xsslock";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.user.services.xss-lock = {
+      description = "XSS Lock Daemon";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      serviceConfig.ExecStart = "${pkgs.xss-lock}/bin/xss-lock ${cfg.lockerCommand}";
+    };
+  };
+}
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 56b7bf00448c..8820a6da8c0b 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -204,6 +204,8 @@ with lib;
     (mkRenamedOptionModule [ "system" "nixosVersionSuffix" ] [ "system" "nixos" "versionSuffix" ])
     (mkRenamedOptionModule [ "system" "nixosRevision" ] [ "system" "nixos" "revision" ])
     (mkRenamedOptionModule [ "system" "nixosLabel" ] [ "system" "nixos" "label" ])
+    (mkRenamedOptionModule [ "system" "stateVersion" ] [ "system" "nixos" "stateVersion" ])
+    (mkRenamedOptionModule [ "system" "defaultChannel" ] [ "system" "nixos" "defaultChannel" ])
 
     # Users
     (mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ])
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 48998285d89d..bef10b4fe614 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -449,6 +449,10 @@ in
           <varname>item</varname>, and <varname>value</varname>
           attribute.  The syntax and semantics of these attributes
           must be that described in the limits.conf(5) man page.
+
+          Note that these limits do not apply to systemd services,
+          whose limits can be changed via <option>systemd.extraConfig</option>
+          instead.
        '';
     };
 
diff --git a/nixos/modules/services/audio/slimserver.nix b/nixos/modules/services/audio/slimserver.nix
index 7d661dd60408..640403d2c97d 100644
--- a/nixos/modules/services/audio/slimserver.nix
+++ b/nixos/modules/services/audio/slimserver.nix
@@ -51,7 +51,8 @@ in {
       serviceConfig = {
         User = "slimserver";
         PermissionsStartOnly = true;
-        ExecStart = "${cfg.package}/slimserver.pl --logdir ${cfg.dataDir}/logs --prefsdir ${cfg.dataDir}/prefs --cachedir ${cfg.dataDir}/cache";
+        # Issue 40589: Disable broken image/video support (audio still works!)
+        ExecStart = "${cfg.package}/slimserver.pl --logdir ${cfg.dataDir}/logs --prefsdir ${cfg.dataDir}/prefs --cachedir ${cfg.dataDir}/cache --noimage --novideo";
       };
     };
 
diff --git a/nixos/modules/services/cluster/kubernetes/dashboard.nix b/nixos/modules/services/cluster/kubernetes/dashboard.nix
index e331889b9dd5..d27389b6a1c7 100644
--- a/nixos/modules/services/cluster/kubernetes/dashboard.nix
+++ b/nixos/modules/services/cluster/kubernetes/dashboard.nix
@@ -70,7 +70,7 @@ in {
                 resources = {
                   limits = {
                     cpu = "100m";
-                    memory = "50Mi";
+                    memory = "250Mi";
                   };
                   requests = {
                     cpu = "100m";
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index 21a131b90a81..66c9330c3550 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -218,7 +218,7 @@ in
   config = mkIf config.services.mysql.enable {
 
     services.mysql.dataDir =
-      mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
+      mkDefault (if versionAtLeast config.system.nixos.stateVersion "17.09" then "/var/lib/mysql"
                  else "/var/mysql");
 
     users.extraUsers.mysql = {
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index f022e0863dfd..4ad4728ccda6 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -147,7 +147,7 @@ in
       };
       superUser = mkOption {
         type = types.str;
-        default= if versionAtLeast config.system.stateVersion "17.09" then "postgres" else "root";
+        default= if versionAtLeast config.system.nixos.stateVersion "17.09" then "postgres" else "root";
         internal = true;
         description = ''
           NixOS traditionally used 'root' as superuser, most other distros use 'postgres'.
@@ -166,14 +166,14 @@ in
 
     services.postgresql.package =
       # Note: when changing the default, make it conditional on
-      # ‘system.stateVersion’ to maintain compatibility with existing
+      # ‘system.nixos.stateVersion’ to maintain compatibility with existing
       # systems!
-      mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql96
-            else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql95
+      mkDefault (if versionAtLeast config.system.nixos.stateVersion "17.09" then pkgs.postgresql96
+            else if versionAtLeast config.system.nixos.stateVersion "16.03" then pkgs.postgresql95
             else pkgs.postgresql94);
 
     services.postgresql.dataDir =
-      mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}"
+      mkDefault (if versionAtLeast config.system.nixos.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}"
                  else "/var/db/postgresql");
 
     services.postgresql.authentication = mkAfter
diff --git a/nixos/modules/services/desktops/flatpak.nix b/nixos/modules/services/desktops/flatpak.nix
new file mode 100644
index 000000000000..cfca1893bd82
--- /dev/null
+++ b/nixos/modules/services/desktops/flatpak.nix
@@ -0,0 +1,52 @@
+# flatpak service.
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.flatpak;
+in {
+  meta = {
+    doc = ./flatpak.xml;
+    maintainers = pkgs.flatpak.meta.maintainers;
+  };
+
+  ###### interface
+  options = {
+    services.flatpak = {
+      enable = mkEnableOption "flatpak";
+
+      extraPortals = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        description = ''
+          List of additional portals to add to path. Portals allow interaction
+          with system, like choosing files or taking screenshots. At minimum,
+          a desktop portal implementation should be listed. GNOME already
+          adds <package>xdg-desktop-portal-gtk</package>; for KDE, there
+          is <package>xdg-desktop-portal-kde</package>. Other desktop
+          environments will probably want to do the same.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.flatpak ];
+
+    services.dbus.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
+
+    systemd.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
+
+    environment.profiles = [
+      "$HOME/.local/share/flatpak/exports"
+      "/var/lib/flatpak/exports"
+    ];
+
+    environment.variables = {
+      XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
+    };
+  };
+}
diff --git a/nixos/modules/services/desktops/flatpak.xml b/nixos/modules/services/desktops/flatpak.xml
new file mode 100644
index 000000000000..d9c8b711c450
--- /dev/null
+++ b/nixos/modules/services/desktops/flatpak.xml
@@ -0,0 +1,53 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-services-flatpak">
+
+<title>Flatpak</title>
+
+<para><emphasis>Source:</emphasis> <filename>modules/services/desktop/flatpak.nix</filename></para>
+
+<para><emphasis>Upstream documentation:</emphasis> <link xlink:href="https://github.com/flatpak/flatpak/wiki"/></para>
+
+<para>Flatpak is a system for building, distributing, and running sandboxed desktop applications on Linux.</para>
+
+<para>
+  To enable Flatpak, add the following to your <filename>configuration.nix</filename>:
+
+  <programlisting>
+  <xref linkend="opt-services.flatpak.enable"/> = true;
+  </programlisting>
+</para>
+
+<para>
+  For the sandboxed apps to work correctly, desktop integration portals need to be installed. If you run GNOME, this will be handled automatically for you; in other cases, you will need to add something like the following to your <filename>configuration.nix</filename>:
+
+  <programlisting>
+  <xref linkend="opt-services.flatpak.extraPortals"/> = [ pkgs.xdg-desktop-portal-gtk ];
+  </programlisting>
+</para>
+
+<para>
+  Then, you will need to add a repository, for example, <link xlink:href="https://github.com/flatpak/flatpak/wiki">Flathub</link>, either using the following commands:
+
+  <programlisting>
+  flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
+  flatpak update
+  </programlisting>
+
+  or by opening the <link xlink:href="https://flathub.org/repo/flathub.flatpakrepo">repository file</link> in GNOME Software.
+</para>
+
+<para>
+  Finally, you can search and install programs:
+
+  <programlisting>
+  flatpak search bustle
+  flatpak install flathub org.freedesktop.Bustle
+  flatpak run org.freedesktop.Bustle
+  </programlisting>
+
+  Again, GNOME Software offers graphical interface for these tasks.
+</para>
+</chapter>
diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix
index 96e60f9c88ea..50477fdd25ba 100644
--- a/nixos/modules/services/mail/dovecot.nix
+++ b/nixos/modules/services/mail/dovecot.nix
@@ -25,7 +25,7 @@ let
       ssl_cert = <${cfg.sslServerCert}
       ssl_key = <${cfg.sslServerKey}
       ${optionalString (!(isNull cfg.sslCACert)) ("ssl_ca = <" + cfg.sslCACert)}
-      ssl_dh = <${config.security.dhparams.path}/dovecot2.pem
+      ssl_dh = <${config.security.dhparams.params.dovecot2.path}
       disable_plaintext_auth = yes
     '')
 
@@ -302,9 +302,7 @@ in
 
     security.dhparams = mkIf (! isNull cfg.sslServerCert) {
       enable = true;
-      params = {
-        dovecot2 = 2048;
-      };
+      params.dovecot2 = {};
     };
    services.dovecot2.protocols =
      optional cfg.enableImap "imap"
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index 63e976ae566c..2d0f66de037d 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -4,6 +4,7 @@ with lib;
 
 let
   cfg = config.services.gitea;
+  gitea = cfg.package;
   pg = config.services.postgresql;
   usePostgresql = cfg.database.type == "postgres";
   configFile = pkgs.writeText "app.ini" ''
@@ -57,6 +58,13 @@ in
         description = "Enable Gitea Service.";
       };
 
+      package = mkOption {
+        default = pkgs.gitea;
+        type = types.package;
+        defaultText = "pkgs.gitea";
+        description = "gitea derivation to use";
+      };
+
       useWizard = mkOption {
         default = false;
         type = types.bool;
@@ -156,6 +164,30 @@ in
         };
       };
 
+      dump = {
+        enable = mkOption {
+          type = types.bool;
+          default = false;
+          description = ''
+            Enable a timer that runs gitea dump to generate backup-files of the
+            current gitea database and repositories.
+          '';
+        };
+
+        interval = mkOption {
+          type = types.str;
+          default = "04:31";
+          example = "hourly";
+          description = ''
+            Run a gitea dump at this interval. Runs by default at 04:31 every day.
+
+            The format is described in
+            <citerefentry><refentrytitle>systemd.time</refentrytitle>
+            <manvolnum>7</manvolnum></citerefentry>.
+          '';
+        };
+      };
+
       appName = mkOption {
         type = types.str;
         default = "gitea: Gitea Service";
@@ -203,7 +235,7 @@ in
 
       staticRootPath = mkOption {
         type = types.str;
-        default = "${pkgs.gitea.data}";
+        default = "${gitea.data}";
         example = "/var/lib/gitea/data";
         description = "Upper level of template and static files path.";
       };
@@ -223,7 +255,7 @@ in
       description = "gitea";
       after = [ "network.target" "postgresql.service" ];
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.gitea.bin ];
+      path = [ gitea.bin ];
 
       preStart = let
         runConfig = "${cfg.stateDir}/custom/conf/app.ini";
@@ -253,7 +285,7 @@ in
         HOOKS=$(find ${cfg.repositoryRoot} -mindepth 4 -maxdepth 4 -type f -wholename "*git/hooks/*")
         if [ "$HOOKS" ]
         then
-          sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gitea,${pkgs.gitea.bin}/bin/gitea,g' $HOOKS
+          sed -ri 's,/nix/store/[a-z0-9.-]+/bin/gitea,${gitea.bin}/bin/gitea,g' $HOOKS
           sed -ri 's,/nix/store/[a-z0-9.-]+/bin/env,${pkgs.coreutils}/bin/env,g' $HOOKS
           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
@@ -261,7 +293,7 @@ in
         if [ ! -d ${cfg.stateDir}/conf/locale ]
         then
           mkdir -p ${cfg.stateDir}/conf
-          cp -r ${pkgs.gitea.out}/locale ${cfg.stateDir}/conf/locale
+          cp -r ${gitea.out}/locale ${cfg.stateDir}/conf/locale
         fi
       '' + optionalString (usePostgresql && cfg.database.createDatabase) ''
         if ! test -e "${cfg.stateDir}/db-created"; then
@@ -288,7 +320,7 @@ in
         User = cfg.user;
         WorkingDirectory = cfg.stateDir;
         PermissionsStartOnly = true;
-        ExecStart = "${pkgs.gitea.bin}/bin/gitea web";
+        ExecStart = "${gitea.bin}/bin/gitea web";
         Restart = "always";
       };
 
@@ -318,5 +350,32 @@ in
         name = "gitea-database-password";
         text = cfg.database.password;
       })));
+
+    systemd.services.gitea-dump = {
+       description = "gitea dump";
+       after = [ "gitea.service" ];
+       wantedBy = [ "default.target" ];
+       path = [ gitea.bin ];
+
+       environment = {
+         USER = cfg.user;
+         HOME = cfg.stateDir;
+         GITEA_WORK_DIR = cfg.stateDir;
+       };
+
+       serviceConfig = {
+         Type = "oneshot";
+         User = cfg.user;
+         ExecStart = "${gitea.bin}/bin/gitea dump";
+         WorkingDirectory = cfg.stateDir;
+       };
+    };
+
+    systemd.timers.gitea-dump = {
+      description = "Update timer for gitea-dump";
+      partOf = [ "gitea-dump.service" ];
+      wantedBy = [ "timers.target" ];
+      timerConfig.OnCalendar = cfg.dump.interval;
+    };
   };
 }
diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix
index 1dc7b44ee37b..05555353f207 100644
--- a/nixos/modules/services/misc/home-assistant.nix
+++ b/nixos/modules/services/misc/home-assistant.nix
@@ -128,9 +128,17 @@ in {
         you might need to specify it in <literal>extraPackages</literal>.
       '';
     };
+
+    openFirewall = mkOption {
+      default = false;
+      type = types.bool;
+      description = "Whether to open the firewall for the specified port.";
+    };
   };
 
   config = mkIf cfg.enable {
+    networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
+
     systemd.services.home-assistant = {
       description = "Home Assistant";
       after = [ "network.target" ];
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 10901e102225..f7441988b272 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -342,7 +342,7 @@ in {
       };
       database_type = mkOption {
         type = types.enum [ "sqlite3" "psycopg2" ];
-        default = if versionAtLeast config.system.stateVersion "18.03"
+        default = if versionAtLeast config.system.nixos.stateVersion "18.03"
           then "psycopg2"
           else "sqlite3";
         description = ''
diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix
index effa29b64f63..468c7f36ecc5 100644
--- a/nixos/modules/services/misc/mesos-slave.nix
+++ b/nixos/modules/services/misc/mesos-slave.nix
@@ -187,7 +187,7 @@ in {
     systemd.services.mesos-slave = {
       description = "Mesos Slave";
       wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
+      after = [ "network.target" ] ++ optionals cfg.withDocker [ "docker.service" ] ;
       path = [ pkgs.runtimeShellPackage ];
       serviceConfig = {
         ExecStart = ''
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 277ae9e292ce..8b940d71ebee 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -340,7 +340,7 @@ in
         default =
           [
             "$HOME/.nix-defexpr/channels"
-            "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs"
+            "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos"
             "nixos-config=/etc/nixos/configuration.nix"
             "/nix/var/nix/profiles/per-user/root/channels"
           ];
diff --git a/nixos/modules/services/misc/sysprof.nix b/nixos/modules/services/misc/sysprof.nix
new file mode 100644
index 000000000000..ab91a8b586a2
--- /dev/null
+++ b/nixos/modules/services/misc/sysprof.nix
@@ -0,0 +1,19 @@
+{ config, lib, pkgs, ... }:
+
+{
+  options = {
+    services.sysprof = {
+      enable = lib.mkEnableOption "sysprof profiling daemon";
+    };
+  };
+
+  config = lib.mkIf config.services.sysprof.enable {
+    environment.systemPackages = [ pkgs.sysprof ];
+
+    services.dbus.packages = [ pkgs.sysprof ];
+
+    systemd.packages = [ pkgs.sysprof ];
+  };
+
+  meta.maintainers = pkgs.sysprof.meta.maintainers;
+}
diff --git a/nixos/modules/services/network-filesystems/beegfs.nix b/nixos/modules/services/network-filesystems/beegfs.nix
index a6a2ec6cbc36..182fabf6405f 100644
--- a/nixos/modules/services/network-filesystems/beegfs.nix
+++ b/nixos/modules/services/network-filesystems/beegfs.nix
@@ -31,7 +31,7 @@ let
     connPortShift = ${toString cfg.connPortShift}
     storeAllowFirstRunInit = false
 
-    ${cfg.mgmtd.extraConfig}
+    ${cfg.meta.extraConfig}
   '';
 
   configStorage = name: cfg: pkgs.writeText "storage-${name}.conf" ''
diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix
index 39a4fd6beff8..e2122ddb8ede 100644
--- a/nixos/modules/services/network-filesystems/ipfs.nix
+++ b/nixos/modules/services/network-filesystems/ipfs.nix
@@ -14,7 +14,7 @@ let
     (optionalString (cfg.defaultMode == "norouting") "--routing=none")
   ] ++ cfg.extraFlags);
 
-  defaultDataDir = if versionAtLeast config.system.stateVersion "17.09" then
+  defaultDataDir = if versionAtLeast config.system.nixos.stateVersion "17.09" then
     "/var/lib/ipfs" else
     "/var/lib/ipfs/.ipfs";
 
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 12c2677c3368..39b62bdc7094 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -260,7 +260,8 @@ in
         RestartSec = 1;
         CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW CAP_SETUID";
         ProtectSystem = true;
-        MemoryDenyWriteExecute = true;
+        # Doesn't work on i686, causing service to fail
+        MemoryDenyWriteExecute = !pkgs.stdenv.isi686;
         ProtectHome = true;
         PrivateTmp = true;
       };
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 857657eea4db..6f5e7d8d456e 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -192,6 +192,7 @@ in
     security.apparmor.profiles = singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
       ${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy {
         /dev/null rw,
+        /dev/random r,
         /dev/urandom r,
 
         /etc/passwd r,
@@ -211,6 +212,9 @@ in
         ${getLib pkgs.gcc.cc}/lib/libssp.so.* mr,
         ${getLib pkgs.libsodium}/lib/libsodium.so.* mr,
         ${getLib pkgs.systemd}/lib/libsystemd.so.* mr,
+        ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
+        ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
+        ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
         ${getLib pkgs.xz}/lib/liblzma.so.* mr,
         ${getLib pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
         ${getLib pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
diff --git a/nixos/modules/services/networking/gnunet.nix b/nixos/modules/services/networking/gnunet.nix
index 02cd53c6fa38..008b09e81a57 100644
--- a/nixos/modules/services/networking/gnunet.nix
+++ b/nixos/modules/services/networking/gnunet.nix
@@ -102,6 +102,14 @@ in
         };
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.gnunet;
+        defaultText = "pkgs.gnunet";
+        description = "Overridable attribute of the gnunet package to use.";
+        example = literalExample "pkgs.gnunet_git";
+      };
+
       extraOptions = mkOption {
         default = "";
         description = ''
@@ -130,16 +138,16 @@ in
 
     # The user tools that talk to `gnunetd' should come from the same source,
     # so install them globally.
-    environment.systemPackages = [ pkgs.gnunet ];
+    environment.systemPackages = [ cfg.package ];
 
     systemd.services.gnunet = {
       description = "GNUnet";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.gnunet pkgs.miniupnpc ];
+      path = [ cfg.package pkgs.miniupnpc ];
       environment.TMPDIR = "/tmp";
       serviceConfig.PrivateTemp = true;
-      serviceConfig.ExecStart = "${pkgs.gnunet}/lib/gnunet/libexec/gnunet-service-arm -c ${configFile}";
+      serviceConfig.ExecStart = "${cfg.package}/lib/gnunet/libexec/gnunet-service-arm -c ${configFile}";
       serviceConfig.User = "gnunet";
       serviceConfig.UMask = "0007";
       serviceConfig.WorkingDirectory = homeDir;
diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix
index bf2d0916fa36..63f56437d1c8 100644
--- a/nixos/modules/services/networking/hostapd.nix
+++ b/nixos/modules/services/networking/hostapd.nix
@@ -151,11 +151,6 @@ in
 
   config = mkIf cfg.enable {
 
-    assertions = [
-      { assertion = (cfg.channel >= 1 && cfg.channel <= 13);
-        message = "channel must be between 1 and 13";
-      }];
-
     environment.systemPackages =  [ pkgs.hostapd ];
 
     systemd.services.hostapd =
diff --git a/nixos/modules/services/networking/keepalived/default.nix b/nixos/modules/services/networking/keepalived/default.nix
index 378cd9365848..c9ac2ee25990 100644
--- a/nixos/modules/services/networking/keepalived/default.nix
+++ b/nixos/modules/services/networking/keepalived/default.nix
@@ -8,10 +8,12 @@ let
 
   keepalivedConf = pkgs.writeText "keepalived.conf" ''
     global_defs {
+      ${optionalString cfg.enableScriptSecurity "enable_script_security"}
       ${snmpGlobalDefs}
       ${cfg.extraGlobalDefs}
     }
 
+    ${vrrpScriptStr}
     ${vrrpInstancesStr}
     ${cfg.extraConfig}
   '';
@@ -26,6 +28,22 @@ let
     + optionalString enableTraps "enable_traps"
   );
 
+  vrrpScriptStr = concatStringsSep "\n" (map (s:
+    ''
+      vrrp_script ${s.name} {
+        script "${s.script}"
+        interval ${toString s.interval}
+        fall ${toString s.fall}
+        rise ${toString s.rise}
+        timeout ${toString s.timeout}
+        weight ${toString s.weight}
+        user ${s.user} ${optionalString (s.group != null) s.group}
+
+        ${s.extraConfig}
+      }
+    ''
+  ) vrrpScripts);
+
   vrrpInstancesStr = concatStringsSep "\n" (map (i:
     ''
       vrrp_instance ${i.name} {
@@ -49,6 +67,18 @@ let
           ${concatMapStringsSep "\n" virtualIpLine i.virtualIps}
         }
 
+        ${optionalString (builtins.length i.trackScripts > 0) ''
+          track_script {
+            ${concatStringsSep "\n" i.trackScripts}
+          }
+        ''}
+
+        ${optionalString (builtins.length i.trackInterfaces > 0) ''
+          track_interface {
+            ${concatStringsSep "\n" i.trackInterfaces}
+          }
+        ''}
+
         ${i.extraConfig}
       }
     ''
@@ -64,6 +94,12 @@ let
 
   notNullOrEmpty = s: !(s == null || s == "");
 
+  vrrpScripts = mapAttrsToList (name: config:
+    {
+      inherit name;
+    } // config
+  ) cfg.vrrpScripts;
+
   vrrpInstances = mapAttrsToList (iName: iConfig:
     {
       name = iName;
@@ -86,7 +122,8 @@ let
     { assertion = !i.vmacXmitBase || i.useVmac;
       message = "services.keepalived.vrrpInstances.${i.name}.vmacXmitBase has no effect when services.keepalived.vrrpInstances.${i.name}.useVmac is not set.";
     }
-  ] ++ flatten (map (virtualIpAssertions i.name) i.virtualIps);
+  ] ++ flatten (map (virtualIpAssertions i.name) i.virtualIps)
+    ++ flatten (map (vrrpScriptAssertion i.name) i.trackScripts);
 
   virtualIpAssertions = vrrpName: ip: [
     { assertion = ip.addr != "";
@@ -94,6 +131,11 @@ let
     }
   ];
 
+  vrrpScriptAssertion = vrrpName: scriptName: {
+    assertion = builtins.hasAttr scriptName cfg.vrrpScripts;
+    message = "services.keepalived.vrrpInstances.${vrrpName} trackscript ${scriptName} is not defined in services.keepalived.vrrpScripts.";
+  };
+
   pidFile = "/run/keepalived.pid";
 
 in
@@ -110,6 +152,14 @@ in
         '';
       };
 
+      enableScriptSecurity = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Don't run scripts configured to be run as root if any part of the path is writable by a non-root user.
+        '';
+      };
+
       snmp = {
 
         enable = mkOption {
@@ -181,8 +231,16 @@ in
 
       };
 
+      vrrpScripts = mkOption {
+        type = types.attrsOf (types.submodule (import ./vrrp-script-options.nix {
+          inherit lib;
+        }));
+        default = {};
+        description = "Declarative vrrp script config";
+      };
+
       vrrpInstances = mkOption {
-        type = types.attrsOf (types.submodule (import ./vrrp-options.nix {
+        type = types.attrsOf (types.submodule (import ./vrrp-instance-options.nix {
           inherit lib;
         }));
         default = {};
diff --git a/nixos/modules/services/networking/keepalived/vrrp-options.nix b/nixos/modules/services/networking/keepalived/vrrp-instance-options.nix
index 79eff3ae5419..85b9bc337726 100644
--- a/nixos/modules/services/networking/keepalived/vrrp-options.nix
+++ b/nixos/modules/services/networking/keepalived/vrrp-instance-options.nix
@@ -108,6 +108,20 @@ with lib;
       description = "Declarative vhost config";
     };
 
+    trackScripts = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "chk_cmd1" "chk_cmd2" ];
+      description = "List of script names to invoke for health tracking.";
+    };
+
+    trackInterfaces = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = [ "eth0" "eth1" ];
+      description = "List of network interfaces to monitor for health tracking.";
+    };
+
     extraConfig = mkOption {
       type = types.lines;
       default = "";
diff --git a/nixos/modules/services/networking/keepalived/vrrp-script-options.nix b/nixos/modules/services/networking/keepalived/vrrp-script-options.nix
new file mode 100644
index 000000000000..a3f794c40a89
--- /dev/null
+++ b/nixos/modules/services/networking/keepalived/vrrp-script-options.nix
@@ -0,0 +1,64 @@
+{ lib } :
+
+with lib;
+with lib.types;
+{
+  options = {
+
+    script = mkOption {
+      type = str;
+      example = "\${pkgs.curl} -f http://localhost:80";
+      description = "(Path of) Script command to execute followed by args, i.e. cmd [args]...";
+    };
+
+    interval = mkOption {
+      type = int;
+      default = 1;
+      description = "Seconds between script invocations.";
+    };
+
+    timeout = mkOption {
+      type = int;
+      default = 5;
+      description = "Seconds after which script is considered to have failed.";
+    };
+
+    weight = mkOption {
+      type = int;
+      default = 0;
+      description = "Following a failure, adjust the priority by this weight.";
+    };
+
+    rise = mkOption {
+      type = int;
+      default = 5;
+      description = "Required number of successes for OK transition.";
+    };
+
+    fall = mkOption {
+      type = int;
+      default = 3;
+      description = "Required number of failures for KO transition.";
+    };
+
+    user = mkOption {
+      type = str;
+      default = "keepalived_script";
+      description = "Name of user to run the script under.";
+    };
+
+    group = mkOption {
+      type = nullOr str;
+      default = null;
+      description = "Name of group to run the script under. Defaults to user group.";
+    };
+
+    extraConfig = mkOption {
+      type = lines;
+      default = "";
+      description = "Extra lines to be added verbatim to the vrrp_script section.";
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix
index 391f4bdebbab..97ee05046ff0 100644
--- a/nixos/modules/services/networking/radicale.nix
+++ b/nixos/modules/services/networking/radicale.nix
@@ -9,7 +9,7 @@ let
   confFile = pkgs.writeText "radicale.conf" cfg.config;
 
   # This enables us to default to version 2 while still not breaking configurations of people with version 1
-  defaultPackage = if versionAtLeast config.system.stateVersion "17.09" then {
+  defaultPackage = if versionAtLeast config.system.nixos.stateVersion "17.09" then {
     pkg = pkgs.radicale2;
     text = "pkgs.radicale2";
   } else {
@@ -35,7 +35,7 @@ in
       defaultText = defaultPackage.text;
       description = ''
         Radicale package to use. This defaults to version 1.x if
-        <literal>system.stateVersion &lt; 17.09</literal> and version 2.x
+        <literal>system.nixos.stateVersion &lt; 17.09</literal> and version 2.x
         otherwise.
       '';
     };
diff --git a/nixos/modules/services/networking/stubby.nix b/nixos/modules/services/networking/stubby.nix
new file mode 100644
index 000000000000..3fbf6eb60e9d
--- /dev/null
+++ b/nixos/modules/services/networking/stubby.nix
@@ -0,0 +1,214 @@
+{ config, lib, pkgs, ...}:
+
+with lib;
+
+let
+  cfg = config.services.stubby;
+
+  fallbacks = concatMapStringsSep "\n  " (x: "- ${x}") cfg.fallbackProtocols;
+  listeners = concatMapStringsSep "\n  " (x: "- ${x}") cfg.listenAddresses;
+
+  # By default, the recursive resolvers maintained by the getdns
+  # project itself are enabled. More information about both getdns's servers,
+  # as well as third party options for upstream resolvers, can be found here:
+  # https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers
+  #
+  # You can override these values by supplying a yaml-formatted array of your
+  # preferred upstream resolvers in the following format:
+  #
+  # 106 # - address_data: IPv4 or IPv6 address of the upstream
+  #   port: Port for UDP/TCP (default is 53)
+  #   tls_auth_name: Authentication domain name checked against the server
+  #                  certificate
+  #   tls_pubkey_pinset: An SPKI pinset verified against the keys in the server
+  #                      certificate
+  #     - digest: Only "sha256" is currently supported
+  #       value: Base64 encoded value of the sha256 fingerprint of the public
+  #              key
+  #   tls_port: Port for TLS (default is 853)
+
+  defaultUpstream = ''
+    - address_data: 145.100.185.15
+      tls_auth_name: "dnsovertls.sinodun.com"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
+    - address_data: 145.100.185.16
+      tls_auth_name: "dnsovertls1.sinodun.com"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
+    - address_data: 185.49.141.37
+      tls_auth_name: "getdnsapi.net"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
+    - address_data: 2001:610:1:40ba:145:100:185:15
+      tls_auth_name: "dnsovertls.sinodun.com"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
+    - address_data: 2001:610:1:40ba:145:100:185:16
+      tls_auth_name: "dnsovertls1.sinodun.com"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
+    - address_data: 2a04:b900:0:100::38
+      tls_auth_name: "getdnsapi.net"
+      tls_pubkey_pinset:
+        - digest: "sha256"
+          value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
+  '';
+
+  # Resolution type is not changeable here because it is required per the
+  # stubby documentation:
+  #
+  # "resolution_type: Work in stub mode only (not recursive mode) - required for Stubby
+  # operation."
+  #
+  # https://dnsprivacy.org/wiki/display/DP/Configuring+Stubby
+
+  confFile = pkgs.writeText "stubby.yml" ''
+    resolution_type: GETDNS_RESOLUTION_STUB
+    dns_transport_list:
+      ${fallbacks}
+    tls_authentication: ${cfg.authenticationMode}
+    tls_query_padding_blocksize: ${toString cfg.queryPaddingBlocksize}
+    edns_client_subnet_private: ${if cfg.subnetPrivate then "1" else "0"}
+    idle_timeout: ${toString cfg.idleTimeout}
+    listen_addresses:
+      ${listeners}
+    round_robin_upstreams: ${if cfg.roundRobinUpstreams then "1" else "0"}
+    ${cfg.extraConfig}
+    upstream_recursive_servers:
+    ${cfg.upstreamServers}
+  '';
+in
+
+{
+  options = {
+    services.stubby = {
+
+      enable = mkEnableOption "Stubby DNS resolver";
+
+      fallbackProtocols = mkOption {
+        default = [ "GETDNS_TRANSPORT_TLS" ];
+        type = with types; listOf (enum [
+          "GETDNS_TRANSPORT_TLS"
+          "GETDNS_TRANSPORT_TCP"
+          "GETDNS_TRANSPORT_UDP"
+        ]);
+        description = ''
+          Ordered list composed of one or more transport protocols.
+          Strict mode should only use <literal>GETDNS_TRANSPORT_TLS</literal>.
+          Other options are <literal>GETDNS_TRANSPORT_UDP</literal> and
+          <literal>GETDNS_TRANSPORT_TCP</literal>.
+        '';
+      };
+
+      authenticationMode = mkOption {
+        default = "GETDNS_AUTHENTICATION_REQUIRED";
+        type = types.enum [
+          "GETDNS_AUTHENTICATION_REQUIRED"
+          "GETDNS_AUTHENTICATION_NONE"
+        ];
+        description = ''
+          Selects the Strict or Opportunistic usage profile.
+          For strict, set to <literal>GETDNS_AUTHENTICATION_REQUIRED</literal>.
+          for opportunistic, use <literal>GETDNS_AUTHENTICATION_NONE</literal>.
+        '';
+      };
+
+      queryPaddingBlocksize = mkOption {
+        default = 128;
+        type = types.int;
+        description = ''
+          EDNS0 option to pad the size of the DNS query to the given blocksize.
+        '';
+      };
+
+      subnetPrivate = mkOption {
+        default = true;
+        type = types.bool;
+        description = ''
+          EDNS0 option for ECS client privacy. Default is
+          <literal>true</literal>. If set, this option prevents the client
+          subnet from being sent to authoritative nameservers.
+        '';
+      };
+
+      idleTimeout = mkOption {
+        default = 10000;
+        type = types.int;
+        description = "EDNS0 option for keepalive idle timeout expressed in
+        milliseconds.";
+      };
+
+      listenAddresses = mkOption {
+        default = [ "127.0.0.1" "0::1" ];
+        type = with types; listOf str;
+        description = ''
+          Sets the listen address for the stubby daemon.
+          Uses port 53 by default.
+          Ise IP@port to specify a different port.
+        '';
+      };
+
+      roundRobinUpstreams = mkOption {
+        default = true;
+        type = types.bool;
+        description = ''
+          Instructs stubby to distribute queries across all available name
+          servers. Default is <literal>true</literal>. Set to
+          <literal>false</literal> in order to use the first available.
+        '';
+      };
+
+      upstreamServers = mkOption {
+        default = defaultUpstream;
+        type = types.lines;
+        description = ''
+          Add additional upstreams. See <citerefentry><refentrytitle>stubby
+          </refentrytitle><manvolnum>1</manvolnum></citerefentry> for an
+          example of the entry formatting. In Strict mode, at least one of the
+          following settings must be supplied for each nameserver:
+          <literal>tls_auth_name</literal> or
+          <literal>tls_pubkey_pinset</literal>.
+        '';
+      };
+
+      debugLogging = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Enable or disable debug level logging.";
+      };
+
+      extraConfig = mkOption {
+        default = "";
+        type = types.lines;
+        description = ''
+          Add additional configuration options. see <citerefentry>
+          <refentrytitle>stubby</refentrytitle><manvolnum>1</manvolnum>
+          </citerefentry>for more options.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.stubby ];
+    systemd.services.stubby = {
+      description = "Stubby local DNS resolver";
+      after = [ "network.target" ];
+      before = [ "nss-lookup.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+        CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
+        ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}";
+        DynamicUser = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
index 0591917c7423..acb4778d8485 100644
--- a/nixos/modules/services/networking/wireguard.nix
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -193,7 +193,7 @@ let
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
         environment.DEVICE = name;
-        path = with pkgs; [ kmod iproute wireguard ];
+        path = with pkgs; [ kmod iproute wireguard-tools ];
 
         serviceConfig = {
           Type = "oneshot";
@@ -279,7 +279,7 @@ in
   config = mkIf (cfg.interfaces != {}) {
 
     boot.extraModulePackages = [ kernel.wireguard ];
-    environment.systemPackages = [ pkgs.wireguard ];
+    environment.systemPackages = [ pkgs.wireguard-tools ];
 
     systemd.services = mapAttrs' generateUnit cfg.interfaces;
 
diff --git a/nixos/modules/services/web-apps/nexus.nix b/nixos/modules/services/web-apps/nexus.nix
index f6a5ce73a12b..d5bd0f12febb 100644
--- a/nixos/modules/services/web-apps/nexus.nix
+++ b/nixos/modules/services/web-apps/nexus.nix
@@ -42,6 +42,34 @@ in
         default = 8081;
         description = "Port to listen on.";
       };
+
+      jvmOpts = mkOption {
+        type = types.lines;
+        default = ''
+          -Xms1200M
+          -Xmx1200M
+          -XX:MaxDirectMemorySize=2G
+          -XX:+UnlockDiagnosticVMOptions
+          -XX:+UnsyncloadClass
+          -XX:+LogVMOutput
+          -XX:LogFile=${cfg.home}/nexus3/log/jvm.log
+          -XX:-OmitStackTraceInFastThrow
+          -Djava.net.preferIPv4Stack=true
+          -Dkaraf.home=${pkgs.nexus}
+          -Dkaraf.base=${pkgs.nexus}
+          -Dkaraf.etc=${pkgs.nexus}/etc/karaf
+          -Djava.util.logging.config.file=${pkgs.nexus}/etc/karaf/java.util.logging.properties
+          -Dkaraf.data=${cfg.home}/nexus3
+          -Djava.io.tmpdir=${cfg.home}/nexus3/tmp
+          -Dkaraf.startLocalConsole=false
+        '';
+
+        description = ''
+          Options for the JVM written to `nexus.jvmopts`.
+          Please refer to the docs (https://help.sonatype.com/repomanager3/installation/configuring-the-runtime-environment)
+          for further information.
+        '';
+      };
     };
   };
 
@@ -63,13 +91,13 @@ in
       environment = {
         NEXUS_USER = cfg.user;
         NEXUS_HOME = cfg.home;
+
+        VM_OPTS_FILE = pkgs.writeText "nexus.vmoptions" cfg.jvmOpts;
       };
 
       preStart = ''
         mkdir -p ${cfg.home}/nexus3/etc
 
-        ln -sf ${cfg.home} /run/sonatype-work
-
         chown -R ${cfg.user}:${cfg.group} ${cfg.home}
 
         if [ ! -f ${cfg.home}/nexus3/etc/nexus.properties ]; then
@@ -77,10 +105,10 @@ in
           echo "application-port=${toString cfg.listenPort}" >> ${cfg.home}/nexus3/etc/nexus.properties
           echo "application-host=${toString cfg.listenAddress}" >> ${cfg.home}/nexus3/etc/nexus.properties
         else
-          sed 's/^application-port=.*/application-port=${toString cfg.listenPort}/' -i ${cfg.home}/nexus3/etc/nexus.properties 
-          sed 's/^# application-port=.*/application-port=${toString cfg.listenPort}/' -i ${cfg.home}/nexus3/etc/nexus.properties 
-          sed 's/^application-host=.*/application-host=${toString cfg.listenAddress}/' -i ${cfg.home}/nexus3/etc/nexus.properties 
-          sed 's/^# application-host=.*/application-host=${toString cfg.listenAddress}/' -i ${cfg.home}/nexus3/etc/nexus.properties 
+          sed 's/^application-port=.*/application-port=${toString cfg.listenPort}/' -i ${cfg.home}/nexus3/etc/nexus.properties
+          sed 's/^# application-port=.*/application-port=${toString cfg.listenPort}/' -i ${cfg.home}/nexus3/etc/nexus.properties
+          sed 's/^application-host=.*/application-host=${toString cfg.listenAddress}/' -i ${cfg.home}/nexus3/etc/nexus.properties
+          sed 's/^# application-host=.*/application-host=${toString cfg.listenAddress}/' -i ${cfg.home}/nexus3/etc/nexus.properties
         fi
       '';
 
diff --git a/nixos/modules/services/web-servers/caddy.nix b/nixos/modules/services/web-servers/caddy.nix
index 2124a42f01a1..fe65fba42a46 100644
--- a/nixos/modules/services/web-servers/caddy.nix
+++ b/nixos/modules/services/web-servers/caddy.nix
@@ -66,7 +66,7 @@ in {
       description = "Caddy web server";
       after = [ "network-online.target" ];
       wantedBy = [ "multi-user.target" ];
-      environment = mkIf (versionAtLeast config.system.stateVersion "17.09")
+      environment = mkIf (versionAtLeast config.system.nixos.stateVersion "17.09")
         { CADDYPATH = cfg.dataDir; };
       serviceConfig = {
         ExecStart = ''
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index f014d817e80e..e4494dff37da 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -62,6 +62,7 @@ with lib;
         This is useful if you have many subdomains and want to avoid hitting the
         <link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>.
         Alternately, you can generate a certificate through <option>enableACME</option>.
+        <emphasis>Note that this option does not create any certificates, nor it does add subdomains to existing ones – you will need to create them manually using  <xref linkend="opt-security.acme.certs"/>.</emphasis>
       '';
     };
 
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 10e8ef0ed381..27b62df7097c 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -120,6 +120,7 @@ in {
     services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
     services.udev.packages = [ pkgs.gnome3.gnome-settings-daemon ];
     systemd.packages = [ pkgs.gnome3.vino ];
+    services.flatpak.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
 
     # If gnome3 is installed, build vim for gtk3 too.
     nixpkgs.config.vim.gui = "gtk3";
diff --git a/nixos/modules/services/x11/desktop-managers/xterm.nix b/nixos/modules/services/x11/desktop-managers/xterm.nix
index 29752ff405e2..6ff1ef0e4c9a 100644
--- a/nixos/modules/services/x11/desktop-managers/xterm.nix
+++ b/nixos/modules/services/x11/desktop-managers/xterm.nix
@@ -12,6 +12,7 @@ in
   options = {
 
     services.xserver.desktopManager.xterm.enable = mkOption {
+      type = types.bool;
       default = true;
       description = "Enable a xterm terminal as a desktop manager.";
     };
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 70fc7388c2ac..a6a38a21b617 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -135,6 +135,9 @@ in
 
     systemd.services.display-manager.path = [ pkgs.gnome3.gnome-session ];
 
+    # Allow choosing an user account
+    services.accounts-daemon.enable = true;
+
     services.dbus.packages = [ gdm ];
 
     systemd.user.services.dbus.wantedBy = [ "default.target" ];
diff --git a/nixos/modules/services/x11/window-managers/stumpwm.nix b/nixos/modules/services/x11/window-managers/stumpwm.nix
index 3d3f2e0028c0..27a17178476a 100644
--- a/nixos/modules/services/x11/window-managers/stumpwm.nix
+++ b/nixos/modules/services/x11/window-managers/stumpwm.nix
@@ -15,10 +15,10 @@ in
     services.xserver.windowManager.session = singleton {
       name = "stumpwm";
       start = ''
-        ${pkgs.stumpwm}/bin/stumpwm &
+        ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
         waitPID=$!
       '';
     };
-    environment.systemPackages = [ pkgs.stumpwm ];
+    environment.systemPackages = [ pkgs.lispPackages.stumpwm ];
   };
 }
diff --git a/nixos/modules/system/boot/coredump.nix b/nixos/modules/system/boot/coredump.nix
index b27a35b6257d..30f367da7666 100644
--- a/nixos/modules/system/boot/coredump.nix
+++ b/nixos/modules/system/boot/coredump.nix
@@ -15,8 +15,11 @@ with lib;
           Enables storing core dumps in systemd.
           Note that this alone is not enough to enable core dumps. The maximum
           file size for core dumps must be specified in limits.conf as well. See
-          <option>security.pam.loginLimits</option> as well as the limits.conf(5)
-          man page.
+          <option>security.pam.loginLimits</option> and the limits.conf(5)
+          man page (these specify the core dump limits for user login sessions)
+          and <option>systemd.extraConfig</option> (where e.g.
+          <literal>DefaultLimitCORE=1000000</literal> can be specified to set
+          the core dump limit for systemd system-level services).
         '';
       };
 
diff --git a/nixos/modules/system/boot/grow-partition.nix b/nixos/modules/system/boot/grow-partition.nix
index 1e6f9e442b67..8c9b1502558a 100644
--- a/nixos/modules/system/boot/grow-partition.nix
+++ b/nixos/modules/system/boot/grow-partition.nix
@@ -30,7 +30,7 @@ with lib;
 
     boot.initrd.postDeviceCommands = ''
       rootDevice="${config.fileSystems."/".device}"
-      if [ -e "$rootDevice" ]; then
+      if waitDevice "$rootDevice"; then
         rootDevice="$(readlink -f "$rootDevice")"
         parentDevice="$rootDevice"
         while [ "''${parentDevice%[0-9]}" != "''${parentDevice}" ]; do
diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix
index 54dfb53fd30f..7ebfdb134d7d 100644
--- a/nixos/modules/system/boot/luksroot.nix
+++ b/nixos/modules/system/boot/luksroot.nix
@@ -454,7 +454,6 @@ in
       ["firewire_ohci" "firewire_core" "firewire_sbp2"];
 
     # Some modules that may be needed for mounting anything ciphered
-    # Also load input_leds to get caps lock light working (#12456)
     boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" "input_leds" ]
       ++ luks.cryptoModules
       # workaround until https://marc.info/?l=linux-crypto-vger&m=148783562211457&w=4 is merged
diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix
index f8fb8a64cb9b..e4223bae7d32 100644
--- a/nixos/modules/system/boot/plymouth.nix
+++ b/nixos/modules/system/boot/plymouth.nix
@@ -87,9 +87,10 @@ in
 
     systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ];
     systemd.services.plymouth-halt.wantedBy = [ "halt.target" ];
+    systemd.services.plymouth-quit-wait.wantedBy = [ "multi-user.target" ];
     systemd.services.plymouth-quit = {
       wantedBy = [ "multi-user.target" ];
-      after = [ "display-manager.service" "multi-user.target" ];
+      after = [ "display-manager.service" ];
     };
     systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
     systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 964ec68cfe2f..92e68b72664a 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -74,6 +74,32 @@ ln -s /proc/mounts /etc/mtab # to shut up mke2fs
 touch /etc/udev/hwdb.bin # to shut up udev
 touch /etc/initrd-release
 
+# Function for waiting a device to appear.
+waitDevice() {
+    local device="$1"
+
+    # USB storage devices tend to appear with some delay.  It would be
+    # great if we had a way to synchronously wait for them, but
+    # alas...  So just wait for a few seconds for the device to
+    # appear.
+    if test ! -e $device; then
+        echo -n "waiting for device $device to appear..."
+        try=20
+        while [ $try -gt 0 ]; do
+            sleep 1
+            # also re-try lvm activation now that new block devices might have appeared
+            lvm vgchange -ay
+            # and tell udev to create nodes for the new LVs
+            udevadm trigger --action=add
+            if test -e $device; then break; fi
+            echo -n "."
+            try=$((try - 1))
+        done
+        echo
+        [ $try -ne 0 ]
+    fi
+}
+
 # Mount special file systems.
 specialMount() {
   local device="$1"
@@ -377,40 +403,7 @@ lustrateRoot () {
     exec 4>&-
 }
 
-# Function for waiting a device to appear.
-waitDevice() {
-    local device="$1"
-
-    # USB storage devices tend to appear with some delay.  It would be
-    # great if we had a way to synchronously wait for them, but
-    # alas...  So just wait for a few seconds for the device to
-    # appear.
-    if test ! -e $device; then
-        echo -n "waiting for device $device to appear..."
-        try=20
-        while [ $try -gt 0 ]; do
-            sleep 1
-            # also re-try lvm activation now that new block devices might have appeared
-            lvm vgchange -ay
-            # and tell udev to create nodes for the new LVs
-            udevadm trigger --action=add
-            if test -e $device; then break; fi
-            echo -n "."
-            try=$((try - 1))
-        done
-        echo
-        [ $try -ne 0 ]
-    fi
-}
-
 
-# Try to resume - all modules are loaded now.
-if test -e /sys/power/tuxonice/resume; then
-    if test -n "$(cat /sys/power/tuxonice/resume)"; then
-        echo 0 > /sys/power/tuxonice/user_interface/enabled
-        echo 1 > /sys/power/tuxonice/do_resume || echo "failed to resume..."
-    fi
-fi
 
 if test -e /sys/power/resume -a -e /sys/power/disk; then
     if test -n "@resumeDevice@" && waitDevice "@resumeDevice@"; then
diff --git a/nixos/modules/system/boot/systemd-lib.nix b/nixos/modules/system/boot/systemd-lib.nix
index 7c01f8ea9b7f..ae9ee8811f77 100644
--- a/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixos/modules/system/boot/systemd-lib.nix
@@ -2,9 +2,10 @@
 
 with lib;
 
-let cfg = config.systemd; in
-
-rec {
+let
+  cfg = config.systemd;
+  lndir = "${pkgs.xorg.lndir}/bin/lndir";
+in rec {
 
   shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s);
 
@@ -136,7 +137,13 @@ rec {
       for i in ${toString cfg.packages}; do
         for fn in $i/etc/systemd/${type}/* $i/lib/systemd/${type}/*; do
           if ! [[ "$fn" =~ .wants$ ]]; then
-            ln -s $fn $out/
+            if [[ -d "$fn" ]]; then
+              targetDir="$out/$(basename "$fn")"
+              mkdir -p "$targetDir"
+              ${lndir} "$fn" "$targetDir"
+            else
+              ln -s $fn $out/
+            fi
           fi
         done
       done
@@ -151,7 +158,7 @@ rec {
           if [ "$(readlink -f $i/$fn)" = /dev/null ]; then
             ln -sfn /dev/null $out/$fn
           else
-            mkdir $out/$fn.d
+            mkdir -p $out/$fn.d
             ln -s $i/$fn $out/$fn.d/overrides.conf
           fi
        else
diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix
index 5255f1a1b97a..2cff25a8c854 100644
--- a/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixos/modules/system/boot/systemd-unit-options.nix
@@ -217,7 +217,7 @@ in rec {
 
     environment = mkOption {
       default = {};
-      type = with types; attrsOf (nullOr (either str package));
+      type = with types; attrsOf (nullOr (either str (either path package)));
       example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
       description = "Environment variables passed to the service's processes.";
     };
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index e754a1e8718d..c4a2bd1f75fd 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -209,7 +209,7 @@ let
                   ''
                      echo "${cidr}" >> $state
                      echo -n "adding route ${cidr}... "
-                     if out=$(ip route add "${cidr}" ${options} ${via} dev "${i.name}" 2>&1); then
+                     if out=$(ip route add "${cidr}" ${options} ${via} dev "${i.name}" proto static 2>&1); then
                        echo "done"
                      elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then
                        echo "'ip route add "${cidr}" ${options} ${via} dev "${i.name}"' failed: $out"
diff --git a/nixos/modules/tasks/scsi-link-power-management.nix b/nixos/modules/tasks/scsi-link-power-management.nix
index 484c0a0186d7..69599bda6d32 100644
--- a/nixos/modules/tasks/scsi-link-power-management.nix
+++ b/nixos/modules/tasks/scsi-link-power-management.nix
@@ -2,7 +2,20 @@
 
 with lib;
 
-let cfg = config.powerManagement.scsiLinkPolicy; in
+let
+
+  cfg = config.powerManagement.scsiLinkPolicy;
+
+  kernel = config.boot.kernelPackages.kernel;
+
+  allowedValues = [
+    "min_power"
+    "max_performance"
+    "medium_power"
+    "med_power_with_dipm"
+  ];
+
+in
 
 {
   ###### interface
@@ -11,10 +24,13 @@ let cfg = config.powerManagement.scsiLinkPolicy; in
 
     powerManagement.scsiLinkPolicy = mkOption {
       default = null;
-      type = types.nullOr (types.enum [ "min_power" "max_performance" "medium_power" ]);
+      type = types.nullOr (types.enum allowedValues);
       description = ''
         SCSI link power management policy. The kernel default is
         "max_performance".
+        </para><para>
+        "med_power_with_dipm" is supported by kernel versions
+        4.15 and newer.
       '';
     };
 
@@ -24,6 +40,12 @@ let cfg = config.powerManagement.scsiLinkPolicy; in
   ###### implementation
 
   config = mkIf (cfg != null) {
+
+    assertions = singleton {
+      assertion = (cfg == "med_power_with_dipm") -> versionAtLeast kernel.version "4.15";
+      message = "med_power_with_dipm is not supported for kernels older than 4.15";
+    };
+
     services.udev.extraRules = ''
       SUBSYSTEM=="scsi_host", ACTION=="add", KERNEL=="host*", ATTR{link_power_management_policy}="${cfg}"
     '';
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 41dec2af9ed4..3d46ba72493c 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -58,6 +58,9 @@ in
     systemd.services."serial-getty@${qemuSerialDevice}".enable = false;
     systemd.services."serial-getty@hvc0".enable = false;
 
+    # Only use a serial console, no TTY.
+    virtualisation.qemu.consoles = [ qemuSerialDevice ];
+
     boot.initrd.preDeviceCommands =
       ''
         echo 600 > /proc/sys/kernel/hung_task_timeout_secs
@@ -126,6 +129,9 @@ in
     users.extraUsers.root.initialHashedPassword = mkOverride 150 "";
 
     services.xserver.displayManager.job.logToJournal = true;
+
+    # set default stateVersion to avoid warnings during eval
+    system.nixos.stateVersion = mkDefault "18.03";
   };
 
 }
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index f74c42a777f5..e9e935e90202 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -48,13 +48,6 @@ let cfg = config.ec2; in
     boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)";
     boot.loader.timeout = 0;
 
-    boot.initrd.postDeviceCommands =
-      ''
-        # Force udev to exit to prevent random "Device or resource busy
-        # while trying to open /dev/xvda" errors from fsck.
-        udevadm control --exit || true
-      '';
-
     boot.initrd.network.enable = true;
 
     # Mount all formatted ephemeral disks and activate all swap devices.
diff --git a/nixos/modules/virtualisation/amazon-options.nix b/nixos/modules/virtualisation/amazon-options.nix
index 349fd3adfc96..9ecdcf23e5fb 100644
--- a/nixos/modules/virtualisation/amazon-options.nix
+++ b/nixos/modules/virtualisation/amazon-options.nix
@@ -3,7 +3,7 @@
   options = {
     ec2 = {
       hvm = lib.mkOption {
-        default = lib.versionAtLeast config.system.stateVersion "17.03";
+        default = lib.versionAtLeast config.system.nixos.stateVersion "17.03";
         internal = true;
         description = ''
           Whether the EC2 instance is a HVM instance.
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 248c2fc1fb23..c3044ea124cf 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -606,8 +606,8 @@ in
                   { config, pkgs, ... }:
                   { services.postgresql.enable = true;
                     services.postgresql.package = pkgs.postgresql96;
-                    
-                    system.stateVersion = "17.03";
+
+                    system.nixos.stateVersion = "17.03";
                   };
               };
           }
diff --git a/nixos/modules/virtualisation/qemu-guest-agent.nix b/nixos/modules/virtualisation/qemu-guest-agent.nix
new file mode 100644
index 000000000000..e0d2b3dc509d
--- /dev/null
+++ b/nixos/modules/virtualisation/qemu-guest-agent.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.qemuGuest;
+in {
+
+  options.services.qemuGuest = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the qemu guest agent.";
+      };
+  };
+
+  config = mkIf cfg.enable (
+      mkMerge [
+    {
+
+      services.udev.extraRules = ''
+        SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"
+      '';
+
+      systemd.services.qemu-guest-agent = {
+        description = "Run the QEMU Guest Agent";
+        serviceConfig = {
+          ExecStart = "${pkgs.kvm.ga}/bin/qemu-ga";
+          Restart = "always";
+          RestartSec = 0;
+        };
+      };
+    }
+  ]
+  );
+}
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index f7ec5b088c1b..0abf7b11703c 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -25,10 +25,7 @@ let
 
   qemuGraphics = lib.optionalString (!cfg.graphics) "-nographic";
 
-  # enable both serial console and tty0. select preferred console (last one) based on cfg.graphics
-  kernelConsoles = let
-    consoles = [ "console=${qemuSerialDevice},115200n8" "console=tty0" ];
-    in lib.concatStringsSep " " (if cfg.graphics then consoles else reverseList consoles);
+  consoles = lib.concatMapStringsSep " " (c: "console=${c}") cfg.qemu.consoles;
 
   # XXX: This is very ugly and in the future we really should use attribute
   # sets to build ALL of the QEMU flags instead of this mixed mess of Nix
@@ -111,7 +108,7 @@ let
             ${mkDiskIfaceDriveFlag "0" "file=$NIX_DISK_IMAGE,cache=writeback,werror=report"} \
             -kernel ${config.system.build.toplevel}/kernel \
             -initrd ${config.system.build.toplevel}/initrd \
-            -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${kernelConsoles} $QEMU_KERNEL_PARAMS" \
+            -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS" \
           ''} \
           $extraDisks \
           ${qemuGraphics} \
@@ -336,6 +333,23 @@ in
           description = "Options passed to QEMU.";
         };
 
+      consoles = mkOption {
+        type = types.listOf types.str;
+        default = let
+          consoles = [ "${qemuSerialDevice},115200n8" "tty0" ];
+        in if cfg.graphics then consoles else reverseList consoles;
+        example = [ "console=tty1" ];
+        description = ''
+          The output console devices to pass to the kernel command line via the
+          <literal>console</literal> parameter, the primary console is the last
+          item of this list.
+
+          By default it enables both serial console and
+          <literal>tty0</literal>. The preferred console (last one) is based on
+          the value of <option>virtualisation.graphics</option>.
+        '';
+      };
+
       networkingOptions =
         mkOption {
           default = [
@@ -360,6 +374,15 @@ in
           type = types.enum [ "virtio" "scsi" "ide" ];
           description = "The interface used for the virtual hard disks.";
         };
+
+      guestAgent.enable =
+        mkOption {
+          default = true;
+          type = types.bool;
+          description = ''
+            Enable the Qemu guest agent.
+          '';
+        };
     };
 
     virtualisation.useBootLoader =
@@ -511,6 +534,8 @@ in
     # Don't run ntpd in the guest.  It should get the correct time from KVM.
     services.timesyncd.enable = false;
 
+    services.qemuGuest.enable = cfg.qemu.guestAgent.enable;
+
     system.build.vm = pkgs.runCommand "nixos-vm" { preferLocalBuild = true; }
       ''
         mkdir -p $out/bin
diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix
index e010b532a688..989764874c48 100644
--- a/nixos/release-combined.nix
+++ b/nixos/release-combined.nix
@@ -58,6 +58,8 @@ in rec {
         nixos.ova.x86_64-linux or []
 
         #(all nixos.tests.containers)
+        (all nixos.tests.containers-imperative)
+        (all nixos.tests.containers-ipv4)
         nixos.tests.chromium.x86_64-linux or []
         (all nixos.tests.firefox)
         (all nixos.tests.firewall)
@@ -98,6 +100,7 @@ in rec {
         (all nixos.tests.misc)
         (all nixos.tests.mutableUsers)
         (all nixos.tests.nat.firewall)
+        (all nixos.tests.nat.firewall-conntrack)
         (all nixos.tests.nat.standalone)
         (all nixos.tests.networking.scripted.loopback)
         (all nixos.tests.networking.scripted.static)
@@ -112,6 +115,10 @@ in rec {
         (all nixos.tests.nfs4)
         (all nixos.tests.openssh)
         (all nixos.tests.php-pcre)
+        (all nixos.tests.predictable-interface-names.predictable)
+        (all nixos.tests.predictable-interface-names.unpredictable)
+        (all nixos.tests.predictable-interface-names.predictableNetworkd)
+        (all nixos.tests.predictable-interface-names.unpredictableNetworkd)
         (all nixos.tests.printing)
         (all nixos.tests.proxy)
         (all nixos.tests.sddm.default)
diff --git a/nixos/release.nix b/nixos/release.nix
index ae70b535a5e2..f7c2943b96fa 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -198,6 +198,7 @@ in rec {
         modules = singleton ({ config, pkgs, ... }:
           { fileSystems."/".device  = mkDefault "/dev/sda1";
             boot.loader.grub.device = mkDefault "/dev/sda";
+            system.nixos.stateVersion = mkDefault "18.03";
           });
       }).config.system.build.toplevel;
       preferLocalBuild = true;
@@ -284,6 +285,7 @@ in rec {
   tests.env = callTest tests/env.nix {};
   tests.ferm = callTest tests/ferm.nix {};
   tests.firefox = callTest tests/firefox.nix {};
+  tests.flatpak = callTest tests/flatpak.nix {};
   tests.firewall = callTest tests/firewall.nix {};
   tests.fwupd = callTest tests/fwupd.nix {};
   #tests.gitlab = callTest tests/gitlab.nix {};
@@ -313,10 +315,7 @@ in rec {
   tests.plotinus = callTest tests/plotinus.nix {};
   tests.keymap = callSubTests tests/keymap.nix {};
   tests.initrdNetwork = callTest tests/initrd-network.nix {};
-  tests.kafka_0_9 = callTest tests/kafka_0_9.nix {};
-  tests.kafka_0_10 = callTest tests/kafka_0_10.nix {};
-  tests.kafka_0_11 = callTest tests/kafka_0_11.nix {};
-  tests.kafka_1_0 = callTest tests/kafka_1_0.nix {};
+  tests.kafka = callSubTests tests/kafka.nix {};
   tests.kernel-copperhead = callTest tests/kernel-copperhead.nix {};
   tests.kernel-latest = callTest tests/kernel-latest.nix {};
   tests.kernel-lts = callTest tests/kernel-lts.nix {};
@@ -348,6 +347,7 @@ in rec {
   tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; };
   # TODO: put in networking.nix after the test becomes more complete
   tests.networkingProxy = callTest tests/networking-proxy.nix {};
+  tests.nexus = callTest tests/nexus.nix { };
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
   tests.nfs4 = callTest tests/nfs.nix { version = 4; };
   tests.nginx = callTest tests/nginx.nix { };
@@ -398,9 +398,11 @@ in rec {
   tests.virtualbox = callSubTestsOnMatchingSystems ["x86_64-linux"] tests/virtualbox.nix {};
   tests.wordpress = callTest tests/wordpress.nix {};
   tests.xautolock = callTest tests/xautolock.nix {};
+  tests.xdg-desktop-portal = callTest tests/xdg-desktop-portal.nix {};
   tests.xfce = callTest tests/xfce.nix {};
   tests.xmonad = callTest tests/xmonad.nix {};
   tests.xrdp = callTest tests/xrdp.nix {};
+  tests.xss-lock = callTest tests/xss-lock.nix {};
   tests.yabar = callTest tests/yabar.nix {};
   tests.zookeeper = callTest tests/zookeeper.nix {};
 
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index d7452744e17b..21b0fedcfefe 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -54,9 +54,11 @@ in import ./make-test.nix {
   };
 
   testScript = ''
+    $letsencrypt->waitForUnit("default.target");
     $letsencrypt->waitForUnit("boulder.service");
-    startAll;
+    $webserver->waitForUnit("default.target");
     $webserver->waitForUnit("acme-certificates.target");
+    $client->waitForUnit("default.target");
     $client->succeed('curl https://example.com/ | grep -qF "hello world"');
   '';
 }
diff --git a/nixos/tests/common/letsencrypt.nix b/nixos/tests/common/letsencrypt.nix
index 10cde45d18a8..7c6b3b29e36d 100644
--- a/nixos/tests/common/letsencrypt.nix
+++ b/nixos/tests/common/letsencrypt.nix
@@ -386,6 +386,10 @@ in {
 
     services.nginx.enable = true;
     services.nginx.recommendedProxySettings = true;
+    # This fixes the test on i686
+    services.nginx.commonHttpConfig = ''
+      server_names_hash_bucket_size 64;
+    '';
     services.nginx.virtualHosts.${wfeDomain} = {
       onlySSL = true;
       enableACME = false;
diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix
index 015b79b1cee6..a548b17b1ff1 100644
--- a/nixos/tests/containers-imperative.nix
+++ b/nixos/tests/containers-imperative.nix
@@ -17,7 +17,9 @@ import ./make-test.nix ({ pkgs, ...} : {
         emptyContainer = import ../lib/eval-config.nix {
           inherit (config.nixpkgs.localSystem) system;
           modules = lib.singleton {
-            containers.foo.config = {};
+            containers.foo.config = {
+              system.nixos.stateVersion = "18.03";
+            };
           };
         };
       in [ pkgs.stdenv emptyContainer.config.containers.foo.path pkgs.libxslt ];
diff --git a/nixos/tests/containers-ipv4.nix b/nixos/tests/containers-ipv4.nix
index 31d05990a679..821ce1cd07d2 100644
--- a/nixos/tests/containers-ipv4.nix
+++ b/nixos/tests/containers-ipv4.nix
@@ -21,6 +21,7 @@ import ./make-test.nix ({ pkgs, ...} : {
               services.httpd.adminAddr = "foo@example.org";
               networking.firewall.allowedTCPPorts = [ 80 ];
               networking.firewall.allowPing = true;
+              system.nixos.stateVersion = "18.03";
             };
         };
 
diff --git a/nixos/tests/dnscrypt-proxy.nix b/nixos/tests/dnscrypt-proxy.nix
index 845623368250..1fcf3903b13e 100644
--- a/nixos/tests/dnscrypt-proxy.nix
+++ b/nixos/tests/dnscrypt-proxy.nix
@@ -26,7 +26,8 @@ import ./make-test.nix ({ pkgs, ... }: {
     $client->waitForUnit("dnsmasq");
 
     # The daemon is socket activated; sending a single ping should activate it.
+    $client->fail("systemctl is-active dnscrypt-proxy");
     $client->execute("${pkgs.iputils}/bin/ping -c1 example.com");
-    $client->succeed("systemctl is-active dnscrypt-proxy");
+    $client->waitUntilSucceeds("systemctl is-active dnscrypt-proxy");
   '';
 })
diff --git a/nixos/tests/flatpak.nix b/nixos/tests/flatpak.nix
new file mode 100644
index 000000000000..d1c7cf843147
--- /dev/null
+++ b/nixos/tests/flatpak.nix
@@ -0,0 +1,23 @@
+# run installed tests
+import ./make-test.nix ({ pkgs, ... }:
+
+{
+  name = "flatpak";
+  meta = {
+    maintainers = pkgs.flatpak.meta.maintainers;
+  };
+
+  machine = { config, pkgs, ... }: {
+    imports = [ ./common/x11.nix ];
+    services.xserver.desktopManager.gnome3.enable = true; # TODO: figure out minimal environment where the tests work
+    services.flatpak.enable = true;
+    environment.systemPackages = with pkgs; [ gnupg gnome-desktop-testing ostree python2 ];
+    virtualisation.memorySize = 2047;
+    virtualisation.diskSize = 1024;
+  };
+
+  testScript = ''
+    $machine->waitForX();
+    $machine->succeed("gnome-desktop-testing-runner -d '${pkgs.flatpak.installedTests}/share' --timeout 3600");
+  '';
+})
diff --git a/nixos/tests/graphite.nix b/nixos/tests/graphite.nix
index a22ef224580a..5a1f50bd29b1 100644
--- a/nixos/tests/graphite.nix
+++ b/nixos/tests/graphite.nix
@@ -4,6 +4,7 @@ import ./make-test.nix ({ pkgs, ...} :
   nodes = {
     one =
       { config, pkgs, ... }: {
+        virtualisation.memorySize = 1024;
         time.timeZone = "UTC";
         services.graphite = {
           web.enable = true;
@@ -21,12 +22,17 @@ import ./make-test.nix ({ pkgs, ...} :
   testScript = ''
     startAll;
     $one->waitForUnit("default.target");
-    $one->requireActiveUnit("graphiteWeb.service");
-    $one->requireActiveUnit("graphiteApi.service");
-    $one->requireActiveUnit("graphitePager.service");
-    $one->requireActiveUnit("carbonCache.service");
-    $one->requireActiveUnit("seyren.service");
-    $one->succeed("echo \"foo 1 `date +%s`\" | nc -q0 localhost 2003");
-    $one->waitUntilSucceeds("curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo")
+    $one->waitForUnit("graphiteWeb.service");
+    $one->waitForUnit("graphiteApi.service");
+    $one->waitForUnit("graphitePager.service");
+    $one->waitForUnit("carbonCache.service");
+    $one->waitForUnit("seyren.service");
+    # The services above are of type "simple". systemd considers them active immediately
+    # even if they're still in preStart (which takes quite long for graphiteWeb).
+    # Wait for ports to open so we're sure the services are up and listening.
+    $one->waitForOpenPort(8080);
+    $one->waitForOpenPort(2003);
+    $one->succeed("echo \"foo 1 `date +%s`\" | nc -N localhost 2003");
+    $one->waitUntilSucceeds("curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo >&2");
   '';
 })
diff --git a/nixos/tests/hardened.nix b/nixos/tests/hardened.nix
index cb33b69e7199..0a0639d62796 100644
--- a/nixos/tests/hardened.nix
+++ b/nixos/tests/hardened.nix
@@ -25,16 +25,18 @@ import ./make-test.nix ({ pkgs, ...} : {
 
   testScript =
     ''
+      $machine->waitForUnit("multi-user.target");
+
       # Test hidepid
       subtest "hidepid", sub {
           $machine->succeed("grep -Fq hidepid=2 /proc/mounts");
-          $machine->succeed("[ `su - sybil -c 'pgrep -c -u root'` = 0 ]");
-          $machine->succeed("[ `su - alice -c 'pgrep -c -u root'` != 0 ]");
+          # cannot use pgrep -u here, it segfaults when access to process info is denied
+          $machine->succeed("[ `su - sybil -c 'ps --no-headers --user root | wc -l'` = 0 ]");
+          $machine->succeed("[ `su - alice -c 'ps --no-headers --user root | wc -l'` != 0 ]");
       };
 
       # Test kernel module hardening
       subtest "lock-modules", sub {
-          $machine->waitForUnit("multi-user.target");
           # note: this better a be module we normally wouldn't load ...
           $machine->fail("modprobe dccp");
       };
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 4ebccb7ab868..797706a062ca 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -65,12 +65,13 @@ in {
     $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${apiPassword}' -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\"'");
 
-    # Check that no errors were logged
-    $hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR");
-
     # Print log to ease debugging
     my $log = $hass->succeed("cat ${configDir}/home-assistant.log");
     print "\n### home-assistant.log ###\n";
     print "$log\n";
+
+    # Check that no errors were logged
+    # The timer can get out of sync due to Hydra's load, so this error is ignored
+    $hass->fail("cat ${configDir}/home-assistant.log | grep -vF 'Timer got out of sync' | grep -qF ERROR");
   '';
 })
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index acf248d0a5a6..7da02d9c204a 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -241,6 +241,7 @@ let
                 nixos-artwork.wallpapers.gnome-dark
                 perlPackages.XMLLibXML
                 perlPackages.ListCompare
+                xorg.lndir
 
                 # add curl so that rather than seeing the test attempt to download
                 # curl's tarball, we see what it's trying to download
diff --git a/nixos/tests/kafka.nix b/nixos/tests/kafka.nix
new file mode 100644
index 000000000000..e48b25d67df3
--- /dev/null
+++ b/nixos/tests/kafka.nix
@@ -0,0 +1,69 @@
+{ system ? builtins.currentSystem }:
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+
+let
+  makeKafkaTest = name: kafkaPackage: (makeTest {
+    inherit name;
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ nequissimus ];
+    };
+
+    nodes = {
+      zookeeper1 = { config, ... }: {
+        services.zookeeper = {
+          enable = true;
+        };
+
+        networking.firewall.allowedTCPPorts = [ 2181 ];
+        virtualisation.memorySize = 1024;
+      };
+      kafka = { config, ... }: {
+        services.apache-kafka = {
+          enable = true;
+          extraProperties = ''
+            offsets.topic.replication.factor = 1
+            zookeeper.session.timeout.ms = 600000
+          '';
+          package = kafkaPackage;
+          zookeeper = "zookeeper1:2181";
+          # These are the default options, but UseCompressedOops doesn't work with 32bit JVM
+          jvmOptions = [
+            "-server" "-Xmx1G" "-Xms1G" "-XX:+UseParNewGC" "-XX:+UseConcMarkSweepGC" "-XX:+CMSClassUnloadingEnabled"
+            "-XX:+CMSScavengeBeforeRemark" "-XX:+DisableExplicitGC" "-Djava.awt.headless=true" "-Djava.net.preferIPv4Stack=true"
+          ] ++ optionals (! pkgs.stdenv.isi686 ) [ "-XX:+UseCompressedOops" ];
+        };
+
+        networking.firewall.allowedTCPPorts = [ 9092 ];
+        # i686 tests: qemu-system-i386 can simulate max 2047MB RAM (not 2048)
+        virtualisation.memorySize = 2047; 
+      };
+    };
+
+    testScript = ''
+      startAll;
+
+      $zookeeper1->waitForUnit("default.target");
+      $zookeeper1->waitForUnit("zookeeper.service");
+      $zookeeper1->waitForOpenPort(2181);
+
+      $kafka->waitForUnit("default.target");
+      $kafka->waitForUnit("apache-kafka.service");
+      $kafka->waitForOpenPort(9092);
+
+      $kafka->waitUntilSucceeds("${kafkaPackage}/bin/kafka-topics.sh --create --zookeeper zookeeper1:2181 --partitions 1 --replication-factor 1 --topic testtopic");
+      $kafka->mustSucceed("echo 'test 1' | ${kafkaPackage}/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testtopic");
+    '' + (if name == "kafka_0_9" then ''
+      $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --zookeeper zookeeper1:2181 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
+    '' else ''
+      $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
+    '');
+  });
+
+in with pkgs; {
+  kafka_0_9  = makeKafkaTest "kafka_0_9"  apacheKafka_0_9;
+  kafka_0_10 = makeKafkaTest "kafka_0_10" apacheKafka_0_10;
+  kafka_0_11 = makeKafkaTest "kafka_0_11" apacheKafka_0_11;
+  kafka_1_0  = makeKafkaTest "kafka_1_0"  apacheKafka_1_0;
+  kafka_1_1  = makeKafkaTest "kafka_1_1"  apacheKafka_1_1;
+}
diff --git a/nixos/tests/kafka_0_10.nix b/nixos/tests/kafka_0_10.nix
deleted file mode 100644
index 6e7820f64bc4..000000000000
--- a/nixos/tests/kafka_0_10.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-import ./make-test.nix ({ pkgs, lib, ... } :
-let
-  kafkaPackage = pkgs.apacheKafka_0_10;
-in {
-  name = "kafka_0_10";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ nequissimus ];
-  };
-
-  nodes = {
-    zookeeper1 = { config, ... }: {
-      services.zookeeper = {
-        enable = true;
-      };
-
-      networking.firewall.allowedTCPPorts = [ 2181 ];
-    };
-    kafka = { config, ... }: {
-      services.apache-kafka = {
-        enable = true;
-        extraProperties = ''
-          offsets.topic.replication.factor = 1
-        '';
-        package = kafkaPackage;
-        zookeeper = "zookeeper1:2181";
-      };
-
-      networking.firewall.allowedTCPPorts = [ 9092 ];
-      virtualisation.memorySize = 2048;
-    };
-  };
-
-  testScript = ''
-    startAll;
-
-    $zookeeper1->waitForUnit("zookeeper");
-    $zookeeper1->waitForUnit("network.target");
-    $zookeeper1->waitForOpenPort(2181);
-
-    $kafka->waitForUnit("apache-kafka");
-    $kafka->waitForUnit("network.target");
-    $kafka->waitForOpenPort(9092);
-
-    $kafka->waitUntilSucceeds("${kafkaPackage}/bin/kafka-topics.sh --create --zookeeper zookeeper1:2181 --partitions 1 --replication-factor 1 --topic testtopic");
-    $kafka->mustSucceed("echo 'test 1' | ${kafkaPackage}/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testtopic");
-    $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
-  '';
-})
diff --git a/nixos/tests/kafka_0_11.nix b/nixos/tests/kafka_0_11.nix
deleted file mode 100644
index 39f9c36bb229..000000000000
--- a/nixos/tests/kafka_0_11.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-import ./make-test.nix ({ pkgs, lib, ... } :
-let
-  kafkaPackage = pkgs.apacheKafka_0_11;
-in {
-  name = "kafka_0_11";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ nequissimus ];
-  };
-
-  nodes = {
-    zookeeper1 = { config, ... }: {
-      services.zookeeper = {
-        enable = true;
-      };
-
-      networking.firewall.allowedTCPPorts = [ 2181 ];
-    };
-    kafka = { config, ... }: {
-      services.apache-kafka = {
-        enable = true;
-        extraProperties = ''
-          offsets.topic.replication.factor = 1
-        '';
-        package = kafkaPackage;
-        zookeeper = "zookeeper1:2181";
-      };
-
-      networking.firewall.allowedTCPPorts = [ 9092 ];
-      virtualisation.memorySize = 2048;
-    };
-  };
-
-  testScript = ''
-    startAll;
-
-    $zookeeper1->waitForUnit("zookeeper");
-    $zookeeper1->waitForUnit("network.target");
-    $zookeeper1->waitForOpenPort(2181);
-
-    $kafka->waitForUnit("apache-kafka");
-    $kafka->waitForUnit("network.target");
-    $kafka->waitForOpenPort(9092);
-
-    $kafka->waitUntilSucceeds("${kafkaPackage}/bin/kafka-topics.sh --create --zookeeper zookeeper1:2181 --partitions 1 --replication-factor 1 --topic testtopic");
-    $kafka->mustSucceed("echo 'test 1' | ${kafkaPackage}/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testtopic");
-    $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
-  '';
-})
diff --git a/nixos/tests/kafka_0_9.nix b/nixos/tests/kafka_0_9.nix
deleted file mode 100644
index fee82aba2bda..000000000000
--- a/nixos/tests/kafka_0_9.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-import ./make-test.nix ({ pkgs, lib, ... } :
-let
-  kafkaPackage = pkgs.apacheKafka_0_9;
-in {
-  name = "kafka_0_9";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ nequissimus ];
-  };
-
-  nodes = {
-    zookeeper1 = { config, ... }: {
-      services.zookeeper = {
-        enable = true;
-      };
-
-      networking.firewall.allowedTCPPorts = [ 2181 ];
-    };
-    kafka = { config, ... }: {
-      services.apache-kafka = {
-        enable = true;
-        extraProperties = ''
-          offsets.topic.replication.factor = 1
-        '';
-        package = kafkaPackage;
-        zookeeper = "zookeeper1:2181";
-      };
-
-      networking.firewall.allowedTCPPorts = [ 9092 ];
-      virtualisation.memorySize = 2048;
-    };
-  };
-
-  testScript = ''
-    startAll;
-
-    $zookeeper1->waitForUnit("zookeeper");
-    $zookeeper1->waitForUnit("network.target");
-    $zookeeper1->waitForOpenPort(2181);
-
-    $kafka->waitForUnit("apache-kafka");
-    $kafka->waitForUnit("network.target");
-    $kafka->waitForOpenPort(9092);
-
-    $kafka->waitUntilSucceeds("${kafkaPackage}/bin/kafka-topics.sh --create --zookeeper zookeeper1:2181 --partitions 1 --replication-factor 1 --topic testtopic");
-    $kafka->mustSucceed("echo 'test 1' | ${kafkaPackage}/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testtopic");
-    $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --zookeeper zookeeper1:2181 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
-  '';
-})
diff --git a/nixos/tests/kafka_1_0.nix b/nixos/tests/kafka_1_0.nix
deleted file mode 100644
index 936840dbcfdc..000000000000
--- a/nixos/tests/kafka_1_0.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-import ./make-test.nix ({ pkgs, lib, ... } :
-let
-  kafkaPackage = pkgs.apacheKafka_1_0;
-in {
-  name = "kafka_1_0";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ nequissimus ];
-  };
-
-  nodes = {
-    zookeeper1 = { config, ... }: {
-      services.zookeeper = {
-        enable = true;
-      };
-
-      networking.firewall.allowedTCPPorts = [ 2181 ];
-    };
-    kafka = { config, ... }: {
-      services.apache-kafka = {
-        enable = true;
-        extraProperties = ''
-          offsets.topic.replication.factor = 1
-        '';
-        package = kafkaPackage;
-        zookeeper = "zookeeper1:2181";
-      };
-
-      networking.firewall.allowedTCPPorts = [ 9092 ];
-      virtualisation.memorySize = 2048;
-    };
-  };
-
-  testScript = ''
-    startAll;
-
-    $zookeeper1->waitForUnit("zookeeper");
-    $zookeeper1->waitForUnit("network.target");
-    $zookeeper1->waitForOpenPort(2181);
-
-    $kafka->waitForUnit("apache-kafka");
-    $kafka->waitForUnit("network.target");
-    $kafka->waitForOpenPort(9092);
-
-    $kafka->waitUntilSucceeds("${kafkaPackage}/bin/kafka-topics.sh --create --zookeeper zookeeper1:2181 --partitions 1 --replication-factor 1 --topic testtopic");
-    $kafka->mustSucceed("echo 'test 1' | ${kafkaPackage}/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic testtopic");
-    $kafka->mustSucceed("${kafkaPackage}/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic testtopic --from-beginning --max-messages 1 | grep 'test 1'");
-  '';
-})
diff --git a/nixos/tests/mesos.nix b/nixos/tests/mesos.nix
index 34671df047c8..007d7ac21603 100644
--- a/nixos/tests/mesos.nix
+++ b/nixos/tests/mesos.nix
@@ -66,9 +66,11 @@ import ./make-test.nix ({ pkgs, ...} : rec {
   testScript =
     ''
       startAll;
+      $master->waitForUnit("zookeeper.service");
       $master->waitForUnit("mesos-master.service");
+      $slave->waitForUnit("docker.service");
       $slave->waitForUnit("mesos-slave.service");
-
+      $master->waitForOpenPort(2181);
       $master->waitForOpenPort(5050);
       $slave->waitForOpenPort(5051);
 
diff --git a/nixos/tests/mysql-backup.nix b/nixos/tests/mysql-backup.nix
index f5bcc460cba7..ff3650988836 100644
--- a/nixos/tests/mysql-backup.nix
+++ b/nixos/tests/mysql-backup.nix
@@ -23,17 +23,25 @@ import ./make-test.nix ({ pkgs, ... } : {
   testScript =
     '' startAll;
 
+       # Delete backup file that may be left over from a previous test run.
+       # This is not needed on Hydra but useful for repeated local test runs.
+       $master->execute("rm -f /var/backup/mysql/testdb.gz");
+
        # Need to have mysql started so that it can be populated with data.
        $master->waitForUnit("mysql.service");
 
-       # Wait for testdb to be populated.
-       $master->sleep(10);
+       # Wait for testdb to be fully populated (5 rows).
+       $master->waitUntilSucceeds("mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5");
 
-       # Do a backup and wait for it to finish.
+       # Do a backup and wait for it to start
        $master->startJob("mysql-backup.service");
        $master->waitForJob("mysql-backup.service");
 
-       # Check that data appears in backup
+       # wait for backup to fail, because of database 'doesnotexist'
+       $master->waitUntilFails("systemctl is-active -q mysql-backup.service");
+
+       # wait for backup file and check that data appears in backup
+       $master->waitForFile("/var/backup/mysql/testdb.gz");
        $master->succeed("${pkgs.gzip}/bin/zcat /var/backup/mysql/testdb.gz | grep hello");
 
        # Check that a failed backup is logged
diff --git a/nixos/tests/mysql-replication.nix b/nixos/tests/mysql-replication.nix
index 75c6d793febc..ed09ac10b75d 100644
--- a/nixos/tests/mysql-replication.nix
+++ b/nixos/tests/mysql-replication.nix
@@ -57,18 +57,25 @@ in
     $master->start;
     $master->waitForUnit("mysql");
     $master->waitForOpenPort(3306);
+    # Wait for testdb to be fully populated (5 rows).
+    $master->waitUntilSucceeds("mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5");
+
     $slave1->start;
     $slave2->start;
     $slave1->waitForUnit("mysql");
     $slave1->waitForOpenPort(3306);
     $slave2->waitForUnit("mysql");
     $slave2->waitForOpenPort(3306);
-    $slave2->succeed("echo 'use testdb; select * from tests' | mysql -u root -N | grep 4");
+
+    # wait for replications to finish
+    $slave1->waitUntilSucceeds("mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5");
+    $slave2->waitUntilSucceeds("mysql -u root -D testdb -N -B -e 'select count(id) from tests' | grep -q 5");
+
     $slave2->succeed("systemctl stop mysql");
     $master->succeed("echo 'insert into testdb.tests values (123, 456);' | mysql -u root -N");
     $slave2->succeed("systemctl start mysql");
     $slave2->waitForUnit("mysql");
     $slave2->waitForOpenPort(3306);
-    $slave2->succeed("echo 'select * from testdb.tests where Id = 123;' | mysql -u root -N | grep 456");
+    $slave2->waitUntilSucceeds("echo 'select * from testdb.tests where Id = 123;' | mysql -u root -N | grep 456");
   '';
 })
diff --git a/nixos/tests/nexus.nix b/nixos/tests/nexus.nix
index 1f19fc0867a4..be8862018777 100644
--- a/nixos/tests/nexus.nix
+++ b/nixos/tests/nexus.nix
@@ -1,34 +1,32 @@
 # verifies:
 #   1. nexus service starts on server
-#   2. nexus user can be extended on server
-#   3. nexus service not can startup on server (creating database and all other initial stuff)
+#   2. nexus service can startup on server (creating database and all other initial stuff)
+#   3. the web application is reachable via HTTP
 
 import ./make-test.nix ({ pkgs, ...} : {
   name = "nexus";
   meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ ironpinguin ];
+    maintainers = [ ironpinguin ma27 ];
   };
 
   nodes = {
 
     server =
       { config, pkgs, ... }:
-      { virtualisation.memorySize = 2048;
+      { virtualisation.memorySize = 2047; # qemu-system-i386 has a 2047M limit
+        virtualisation.diskSize = 2048;
 
         services.nexus.enable = true;
-
-        users.extraUsers.nexus.extraGroups = [ "users" ];
       };
+
   };
 
   testScript = ''
     startAll;
 
     $server->waitForUnit("nexus");
-
-    print $server->execute("sudo -u nexus groups");
-    $server->mustSucceed("sudo -u nexus groups | grep nexus | grep users");
-
     $server->waitForOpenPort(8081);
+
+    $server->succeed("curl -f 127.0.0.1:8081");
   '';
 })
diff --git a/nixos/tests/plotinus.nix b/nixos/tests/plotinus.nix
index 557d65f7960a..9058c59c92de 100644
--- a/nixos/tests/plotinus.nix
+++ b/nixos/tests/plotinus.nix
@@ -15,11 +15,11 @@ import ./make-test.nix ({ pkgs, ... }: {
   testScript =
     ''
       $machine->waitForX;
-      $machine->execute("xterm -e 'gnome-calculator' &");
-      $machine->waitForWindow(qr/Calculator/);
-      $machine->execute("xdotool key ctrl+shift+p");
-      $machine->sleep(1); # wait for the popup
-      $machine->execute("xdotool key p r e f e r e n c e s Return");
+      $machine->succeed("gnome-calculator &");
+      $machine->waitForWindow(qr/gnome-calculator/);
+      $machine->succeed("xdotool search --sync --onlyvisible --class gnome-calculator windowfocus --sync key ctrl+shift+p");
+      $machine->sleep(5); # wait for the popup
+      $machine->succeed("xdotool key --delay 100 p r e f e r e n c e s Return");
       $machine->waitForWindow(qr/Preferences/);
       $machine->screenshot("screen");
     '';
diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix
index 8ac0639c6a8c..e38430385415 100644
--- a/nixos/tests/radicale.nix
+++ b/nixos/tests/radicale.nix
@@ -43,7 +43,7 @@ in
             });
           })
         ];
-        system.stateVersion = "17.03";
+        system.nixos.stateVersion = "17.03";
       };
       radicale1_export = lib.recursiveUpdate radicale1 {
         services.radicale.extraArgs = [
@@ -54,7 +54,7 @@ in
         services.radicale.extraArgs = [ "--verify-storage" ];
       };
       radicale2 = lib.recursiveUpdate (common args) {
-        system.stateVersion = "17.09";
+        system.nixos.stateVersion = "17.09";
       };
     };
 
diff --git a/nixos/tests/statsd.nix b/nixos/tests/statsd.nix
index a9d7dc61cb60..666961249ced 100644
--- a/nixos/tests/statsd.nix
+++ b/nixos/tests/statsd.nix
@@ -8,7 +8,7 @@ with lib;
     maintainers = [ ma27 ];
   };
 
-  nodes.statsd1 = {
+  machine = {
     services.statsd.enable = true;
     services.statsd.backends = [ "statsd-influxdb-backend" "console" ];
     services.statsd.extraConfig = ''
@@ -33,8 +33,19 @@ with lib;
   };
 
   testScript = ''
-    $statsd1->start();
-    $statsd1->waitForUnit("statsd.service");
-    $statsd1->succeed("nc -z 127.0.0.1 8126");
+    $machine->start();
+    $machine->waitForUnit("statsd.service");
+    $machine->waitForOpenPort(8126);
+
+    # check state of the `statsd` server
+    $machine->succeed('[ "health: up" = "$(echo health | nc 127.0.0.1 8126 -w 120 -N)" ];');
+
+    # confirm basic examples for metrics derived from docs:
+    # https://github.com/etsy/statsd/blob/v0.8.0/README.md#usage and
+    # https://github.com/etsy/statsd/blob/v0.8.0/docs/admin_interface.md
+    $machine->succeed("echo 'foo:1|c' | nc -u -w 0  127.0.0.1 8125");
+    $machine->succeed("echo counters | nc -w 120 127.0.0.1 8126 -N | grep foo");
+    $machine->succeed("echo 'delcounters foo' | nc -w 120 127.0.0.1 8126 -N");
+    $machine->fail("echo counters | nc -w 120 127.0.0.1 8126 -N | grep foo");
   '';
 })
diff --git a/nixos/tests/xdg-desktop-portal.nix b/nixos/tests/xdg-desktop-portal.nix
new file mode 100644
index 000000000000..d954b07f73d6
--- /dev/null
+++ b/nixos/tests/xdg-desktop-portal.nix
@@ -0,0 +1,17 @@
+# run installed tests
+import ./make-test.nix ({ pkgs, ... }:
+
+{
+  name = "xdg-desktop-portal";
+  meta = {
+    maintainers = pkgs.xdg-desktop-portal.meta.maintainers;
+  };
+
+  machine = { config, pkgs, ... }: {
+    environment.systemPackages = with pkgs; [ gnome-desktop-testing ];
+  };
+
+  testScript = ''
+    $machine->succeed("gnome-desktop-testing-runner -d '${pkgs.xdg-desktop-portal.installedTests}/share'");
+  '';
+})
diff --git a/nixos/tests/xss-lock.nix b/nixos/tests/xss-lock.nix
new file mode 100644
index 000000000000..045667bdcdec
--- /dev/null
+++ b/nixos/tests/xss-lock.nix
@@ -0,0 +1,25 @@
+import ./make-test.nix ({ pkgs, lib, ... }:
+
+with lib;
+
+{
+  name = "xss-lock";
+  meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ma27 ];
+
+  machine = {
+    imports = [ ./common/x11.nix ./common/user-account.nix ];
+    programs.xss-lock.enable = true;
+    programs.xss-lock.lockerCommand = "${pkgs.xlockmore}/bin/xlock";
+    services.xserver.displayManager.auto.user = "alice";
+  };
+
+  testScript = ''
+    $machine->start;
+    $machine->waitForX;
+    $machine->waitForUnit("xss-lock.service", "alice");
+
+    $machine->fail("pgrep xlock");
+    $machine->succeed("su -l alice -c 'xset dpms force standby'");
+    $machine->waitUntilSucceeds("pgrep xlock");
+  '';
+})