about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-04-27 21:04:56 +0000
committerAlyssa Ross <hi@alyssa.is>2020-04-27 21:04:56 +0000
commita4e6c7d26af697f4346cacb7ab18dcd7fcfc056e (patch)
tree47950e79183035018882419c4eff5047d1537b99 /nixpkgs/nixos/tests
parent5b00523fb58512232b819a301c4309f579c7f09c (diff)
parent22a3bf9fb9edad917fb6cd1066d58b5e426ee975 (diff)
downloadnixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.gz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.bz2
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.lz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.xz
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.tar.zst
nixlib-a4e6c7d26af697f4346cacb7ab18dcd7fcfc056e.zip
Merge commit '22a3bf9fb9edad917fb6cd1066d58b5e426ee975'
Diffstat (limited to 'nixpkgs/nixos/tests')
-rw-r--r--nixpkgs/nixos/tests/acme.nix168
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix23
-rw-r--r--nixpkgs/nixos/tests/caddy.nix44
-rw-r--r--nixpkgs/nixos/tests/ceph-multi-node.nix6
-rw-r--r--nixpkgs/nixos/tests/ceph-single-node.nix6
-rw-r--r--nixpkgs/nixos/tests/cockroachdb.nix28
-rw-r--r--nixpkgs/nixos/tests/common/acme/client/default.nix15
-rw-r--r--nixpkgs/nixos/tests/common/acme/server/default.nix (renamed from nixpkgs/nixos/tests/common/letsencrypt/default.nix)34
-rw-r--r--nixpkgs/nixos/tests/common/acme/server/mkcerts.nix (renamed from nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix)5
-rwxr-xr-xnixpkgs/nixos/tests/common/acme/server/mkcerts.sh (renamed from nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh)0
-rw-r--r--nixpkgs/nixos/tests/common/acme/server/snakeoil-certs.nix171
-rw-r--r--nixpkgs/nixos/tests/common/letsencrypt/common.nix12
-rw-r--r--nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix254
-rw-r--r--nixpkgs/nixos/tests/common/resolver.nix2
-rw-r--r--nixpkgs/nixos/tests/containers-custom-pkgs.nix42
-rw-r--r--nixpkgs/nixos/tests/deluge.nix109
-rw-r--r--nixpkgs/nixos/tests/dokuwiki.nix83
-rw-r--r--nixpkgs/nixos/tests/dovecot.nix4
-rw-r--r--nixpkgs/nixos/tests/flannel.nix37
-rw-r--r--nixpkgs/nixos/tests/gerrit.nix1
-rw-r--r--nixpkgs/nixos/tests/gnome3-xorg.nix6
-rw-r--r--nixpkgs/nixos/tests/gnome3.nix6
-rw-r--r--nixpkgs/nixos/tests/hardened.nix11
-rw-r--r--nixpkgs/nixos/tests/hydra/common.nix47
-rw-r--r--nixpkgs/nixos/tests/hydra/db-migration.nix92
-rw-r--r--nixpkgs/nixos/tests/hydra/default.nix137
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/default.nix22
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/dropbear.privbin1573 -> 0 bytes
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/dropbear.pub1
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/generate-keys.nix8
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/id_ed255197
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519.pub1
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/openssh.priv51
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/openssh.pub1
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key7
-rw-r--r--nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key.pub1
-rw-r--r--nixpkgs/nixos/tests/installed-tests/default.nix1
-rw-r--r--nixpkgs/nixos/tests/installed-tests/libjcat.nix5
-rw-r--r--nixpkgs/nixos/tests/installer.nix20
-rw-r--r--nixpkgs/nixos/tests/iodine.nix5
-rw-r--r--nixpkgs/nixos/tests/k3s.nix78
-rw-r--r--nixpkgs/nixos/tests/kafka.nix2
-rw-r--r--nixpkgs/nixos/tests/magic-wormhole-mailbox-server.nix38
-rw-r--r--nixpkgs/nixos/tests/mongodb.nix4
-rw-r--r--nixpkgs/nixos/tests/mpd.nix2
-rw-r--r--nixpkgs/nixos/tests/mysql.nix33
-rw-r--r--nixpkgs/nixos/tests/nesting.nix44
-rw-r--r--nixpkgs/nixos/tests/networking.nix50
-rw-r--r--nixpkgs/nixos/tests/nextcloud/basic.nix6
-rw-r--r--nixpkgs/nixos/tests/nextcloud/with-mysql-and-memcached.nix8
-rw-r--r--nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix8
-rw-r--r--nixpkgs/nixos/tests/nginx-etag.nix4
-rw-r--r--nixpkgs/nixos/tests/nginx-pubhtml.nix20
-rw-r--r--nixpkgs/nixos/tests/nginx.nix53
-rw-r--r--nixpkgs/nixos/tests/os-prober.nix2
-rw-r--r--nixpkgs/nixos/tests/php/default.nix7
-rw-r--r--nixpkgs/nixos/tests/php/fpm.nix55
-rw-r--r--nixpkgs/nixos/tests/php/pcre.nix (renamed from nixpkgs/nixos/tests/php-pcre.nix)31
-rw-r--r--nixpkgs/nixos/tests/quorum.nix79
-rw-r--r--nixpkgs/nixos/tests/rabbitmq.nix2
-rw-r--r--nixpkgs/nixos/tests/redmine.nix8
-rw-r--r--nixpkgs/nixos/tests/roundcube.nix1
-rw-r--r--nixpkgs/nixos/tests/rxe.nix2
-rw-r--r--nixpkgs/nixos/tests/specialisation.nix43
-rw-r--r--nixpkgs/nixos/tests/switch-test.nix2
-rw-r--r--nixpkgs/nixos/tests/systemd-confinement.nix6
-rw-r--r--nixpkgs/nixos/tests/systemd.nix2
-rw-r--r--nixpkgs/nixos/tests/traefik.nix87
-rw-r--r--nixpkgs/nixos/tests/tuptime.nix29
-rw-r--r--nixpkgs/nixos/tests/udisks2.nix2
-rw-r--r--nixpkgs/nixos/tests/virtualbox.nix4
-rw-r--r--nixpkgs/nixos/tests/wireguard/default.nix142
-rw-r--r--nixpkgs/nixos/tests/wireguard/make-peer.nix23
-rw-r--r--nixpkgs/nixos/tests/wireguard/wg-quick.nix63
74 files changed, 1518 insertions, 895 deletions
diff --git a/nixpkgs/nixos/tests/acme.nix b/nixpkgs/nixos/tests/acme.nix
index e045f3415fa0..693f02962f45 100644
--- a/nixpkgs/nixos/tests/acme.nix
+++ b/nixpkgs/nixos/tests/acme.nix
@@ -1,5 +1,5 @@
 let
-  commonConfig = ./common/letsencrypt/common.nix;
+  commonConfig = ./common/acme/client;
 
   dnsScript = {writeScript, dnsAddress, bash, curl}: writeScript "dns-hook.sh" ''
     #!${bash}/bin/bash
@@ -16,8 +16,8 @@ in import ./make-test-python.nix {
   name = "acme";
 
   nodes = rec {
-    letsencrypt = { nodes, lib, ... }: {
-      imports = [ ./common/letsencrypt ];
+    acme = { nodes, lib, ... }: {
+      imports = [ ./common/acme/server ];
       networking.nameservers = lib.mkForce [
         nodes.dnsserver.config.networking.primaryIPAddress
       ];
@@ -33,8 +33,7 @@ in import ./make-test-python.nix {
         serviceConfig = {
           ExecStart = "${pkgs.pebble}/bin/pebble-challtestsrv -dns01 ':53' -defaultIPv6 '' -defaultIPv4 '${nodes.webserver.config.networking.primaryIPAddress}'";
           # Required to bind on privileged ports.
-          User = "root";
-          Group = "root";
+          AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
         };
       };
     };
@@ -45,19 +44,16 @@ in import ./make-test-python.nix {
         nodes.dnsserver.config.networking.primaryIPAddress
       ];
       networking.firewall.allowedTCPPorts = [ 80 ];
-      security.acme = {
-        server = "https://acme-v02.api.letsencrypt.org/dir";
-        certs."standalone.com" = {
-            webroot = "/var/lib/acme/acme-challenges";
-        };
+      security.acme.certs."standalone.test" = {
+        webroot = "/var/lib/acme/acme-challenges";
       };
-      systemd.targets."acme-finished-standalone.com" = {};
-      systemd.services."acme-standalone.com" = {
-        wants = [ "acme-finished-standalone.com.target" ];
-        before = [ "acme-finished-standalone.com.target" ];
+      systemd.targets."acme-finished-standalone.test" = {};
+      systemd.services."acme-standalone.test" = {
+        wants = [ "acme-finished-standalone.test.target" ];
+        before = [ "acme-finished-standalone.test.target" ];
       };
       services.nginx.enable = true;
-      services.nginx.virtualHosts."standalone.com" = {
+      services.nginx.virtualHosts."standalone.test" = {
         locations."/.well-known/acme-challenge".root = "/var/lib/acme/acme-challenges";
       };
     };
@@ -71,16 +67,16 @@ in import ./make-test-python.nix {
 
       # A target remains active. Use this to probe the fact that
       # a service fired eventhough it is not RemainAfterExit
-      systemd.targets."acme-finished-a.example.com" = {};
-      systemd.services."acme-a.example.com" = {
-        wants = [ "acme-finished-a.example.com.target" ];
-        before = [ "acme-finished-a.example.com.target" ];
+      systemd.targets."acme-finished-a.example.test" = {};
+      systemd.services."acme-a.example.test" = {
+        wants = [ "acme-finished-a.example.test.target" ];
+        before = [ "acme-finished-a.example.test.target" ];
         after = [ "nginx.service" ];
       };
 
       services.nginx.enable = true;
 
-      services.nginx.virtualHosts."a.example.com" = {
+      services.nginx.virtualHosts."a.example.test" = {
         enableACME = true;
         forceSSL = true;
         locations."/".root = pkgs.runCommand "docroot" {} ''
@@ -89,54 +85,52 @@ in import ./make-test-python.nix {
         '';
       };
 
-      security.acme.server = "https://acme-v02.api.letsencrypt.org/dir";
-
-      nesting.clone = [
-        ({pkgs, ...}: {
-          systemd.targets."acme-finished-b.example.com" = {};
-          systemd.services."acme-b.example.com" = {
-            wants = [ "acme-finished-b.example.com.target" ];
-            before = [ "acme-finished-b.example.com.target" ];
-            after = [ "nginx.service" ];
-          };
-          services.nginx.virtualHosts."b.example.com" = {
-            enableACME = true;
-            forceSSL = true;
-            locations."/".root = pkgs.runCommand "docroot" {} ''
-              mkdir -p "$out"
-              echo hello world > "$out/index.html"
-            '';
-          };
-        })
-        ({pkgs, config, nodes, lib, ...}: {
-          security.acme.certs."example.com" = {
-            domain = "*.example.com";
-            dnsProvider = "exec";
-            dnsPropagationCheck = false;
-            credentialsFile = with pkgs; writeText "wildcard.env" ''
-              EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }}
-            '';
-            user = config.services.nginx.user;
-            group = config.services.nginx.group;
-          };
-          systemd.targets."acme-finished-example.com" = {};
-          systemd.services."acme-example.com" = {
-            wants = [ "acme-finished-example.com.target" ];
-            before = [ "acme-finished-example.com.target" "nginx.service" ];
-            wantedBy = [ "nginx.service" ];
-          };
-          services.nginx.virtualHosts."c.example.com" = {
-            forceSSL = true;
-            sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem";
-            sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem";
-            sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem";
-            locations."/".root = pkgs.runCommand "docroot" {} ''
-              mkdir -p "$out"
-              echo hello world > "$out/index.html"
-            '';
-          };
-        })
-      ];
+      security.acme.server = "https://acme.test/dir";
+
+      specialisation.second-cert.configuration = {pkgs, ...}: {
+        systemd.targets."acme-finished-b.example.test" = {};
+        systemd.services."acme-b.example.test" = {
+          wants = [ "acme-finished-b.example.test.target" ];
+          before = [ "acme-finished-b.example.test.target" ];
+          after = [ "nginx.service" ];
+        };
+        services.nginx.virtualHosts."b.example.test" = {
+          enableACME = true;
+          forceSSL = true;
+          locations."/".root = pkgs.runCommand "docroot" {} ''
+            mkdir -p "$out"
+            echo hello world > "$out/index.html"
+          '';
+        };
+      };
+      specialisation.dns-01.configuration = {pkgs, config, nodes, lib, ...}: {
+        security.acme.certs."example.test" = {
+          domain = "*.example.test";
+          dnsProvider = "exec";
+          dnsPropagationCheck = false;
+          credentialsFile = with pkgs; writeText "wildcard.env" ''
+            EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }}
+          '';
+          user = config.services.nginx.user;
+          group = config.services.nginx.group;
+        };
+        systemd.targets."acme-finished-example.test" = {};
+        systemd.services."acme-example.test" = {
+          wants = [ "acme-finished-example.test.target" ];
+          before = [ "acme-finished-example.test.target" "nginx.service" ];
+          wantedBy = [ "nginx.service" ];
+        };
+        services.nginx.virtualHosts."c.example.test" = {
+          forceSSL = true;
+          sslCertificate = config.security.acme.certs."example.test".directory + "/cert.pem";
+          sslTrustedCertificate = config.security.acme.certs."example.test".directory + "/full.pem";
+          sslCertificateKey = config.security.acme.certs."example.test".directory + "/key.pem";
+          locations."/".root = pkgs.runCommand "docroot" {} ''
+            mkdir -p "$out"
+            echo hello world > "$out/index.html"
+          '';
+        };
+      };
     };
 
     client = {nodes, lib, ...}: {
@@ -161,46 +155,44 @@ in import ./make-test-python.nix {
       client.start()
       dnsserver.start()
 
-      letsencrypt.wait_for_unit("default.target")
+      acme.wait_for_unit("default.target")
       dnsserver.wait_for_unit("pebble-challtestsrv.service")
       client.succeed(
-          'curl --data \'{"host": "acme-v02.api.letsencrypt.org", "addresses": ["${nodes.letsencrypt.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
+          'curl --data \'{"host": "acme.test", "addresses": ["${nodes.acme.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
       )
       client.succeed(
-          'curl --data \'{"host": "standalone.com", "addresses": ["${nodes.acmeStandalone.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
+          'curl --data \'{"host": "standalone.test", "addresses": ["${nodes.acmeStandalone.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
       )
 
-      letsencrypt.start()
+      acme.start()
       acmeStandalone.start()
 
-      letsencrypt.wait_for_unit("default.target")
-      letsencrypt.wait_for_unit("pebble.service")
+      acme.wait_for_unit("default.target")
+      acme.wait_for_unit("pebble.service")
 
       with subtest("can request certificate with HTTPS-01 challenge"):
           acmeStandalone.wait_for_unit("default.target")
-          acmeStandalone.succeed("systemctl start acme-standalone.com.service")
-          acmeStandalone.wait_for_unit("acme-finished-standalone.com.target")
+          acmeStandalone.succeed("systemctl start acme-standalone.test.service")
+          acmeStandalone.wait_for_unit("acme-finished-standalone.test.target")
 
       client.wait_for_unit("default.target")
 
-      client.succeed("curl https://acme-v02.api.letsencrypt.org:15000/roots/0 > /tmp/ca.crt")
-      client.succeed(
-          "curl https://acme-v02.api.letsencrypt.org:15000/intermediate-keys/0 >> /tmp/ca.crt"
-      )
+      client.succeed("curl https://acme.test:15000/roots/0 > /tmp/ca.crt")
+      client.succeed("curl https://acme.test:15000/intermediate-keys/0 >> /tmp/ca.crt")
 
       with subtest("Can request certificate for nginx service"):
-          webserver.wait_for_unit("acme-finished-a.example.com.target")
+          webserver.wait_for_unit("acme-finished-a.example.test.target")
           client.succeed(
-              "curl --cacert /tmp/ca.crt https://a.example.com/ | grep -qF 'hello world'"
+              "curl --cacert /tmp/ca.crt https://a.example.test/ | grep -qF 'hello world'"
           )
 
       with subtest("Can add another certificate for nginx service"):
           webserver.succeed(
-              "/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
+              "/run/current-system/specialisation/second-cert/bin/switch-to-configuration test"
           )
-          webserver.wait_for_unit("acme-finished-b.example.com.target")
+          webserver.wait_for_unit("acme-finished-b.example.test.target")
           client.succeed(
-              "curl --cacert /tmp/ca.crt https://b.example.com/ | grep -qF 'hello world'"
+              "curl --cacert /tmp/ca.crt https://b.example.test/ | grep -qF 'hello world'"
           )
 
       with subtest("Can request wildcard certificates using DNS-01 challenge"):
@@ -208,11 +200,11 @@ in import ./make-test-python.nix {
               "${switchToNewServer}"
           )
           webserver.succeed(
-              "/run/current-system/fine-tune/child-2/bin/switch-to-configuration test"
+              "/run/current-system/specialisation/dns-01/bin/switch-to-configuration test"
           )
-          webserver.wait_for_unit("acme-finished-example.com.target")
+          webserver.wait_for_unit("acme-finished-example.test.target")
           client.succeed(
-              "curl --cacert /tmp/ca.crt https://c.example.com/ | grep -qF 'hello world'"
+              "curl --cacert /tmp/ca.crt https://c.example.test/ | grep -qF 'hello world'"
           )
     '';
 }
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 3501c551625d..30229a3a5b2f 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -22,7 +22,7 @@ let
 in
 {
   _3proxy = handleTest ./3proxy.nix {};
-  acme = handleTestOn ["x86_64-linux"] ./acme.nix {};
+  acme = handleTest ./acme.nix {};
   atd = handleTest ./atd.nix {};
   automysqlbackup = handleTest ./automysqlbackup.nix {};
   avahi = handleTest ./avahi.nix {};
@@ -51,7 +51,9 @@ in
   cloud-init = handleTest ./cloud-init.nix {};
   codimd = handleTest ./codimd.nix {};
   consul = handleTest ./consul.nix {};
+  cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {};
   containers-bridge = handleTest ./containers-bridge.nix {};
+  containers-custom-pkgs.nix = handleTest ./containers-custom-pkgs.nix {};
   containers-ephemeral = handleTest ./containers-ephemeral.nix {};
   containers-extra_veth = handleTest ./containers-extra_veth.nix {};
   containers-hosts = handleTest ./containers-hosts.nix {};
@@ -121,12 +123,16 @@ in
   handbrake = handleTestOn ["x86_64-linux"] ./handbrake.nix {};
   haproxy = handleTest ./haproxy.nix {};
   hardened = handleTest ./hardened.nix {};
-  hibernate = handleTest ./hibernate.nix {};
+  # 9pnet_virtio used to mount /nix partition doesn't support
+  # hibernation. This test happens to work on x86_64-linux but
+  # not on other platforms.
+  hibernate = handleTestOn ["x86_64-linux"] ./hibernate.nix {};
   hitch = handleTest ./hitch {};
   hocker-fetchdocker = handleTest ./hocker-fetchdocker {};
   home-assistant = handleTest ./home-assistant.nix {};
   hound = handleTest ./hound.nix {};
   hydra = handleTest ./hydra {};
+  hydra-db-migration = handleTest ./hydra/db-migration.nix {};
   i3wm = handleTest ./i3wm.nix {};
   icingaweb2 = handleTest ./icingaweb2.nix {};
   iftop = handleTest ./iftop.nix {};
@@ -142,6 +148,7 @@ in
   jellyfin = handleTest ./jellyfin.nix {};
   jenkins = handleTest ./jenkins.nix {};
   jirafeau = handleTest ./jirafeau.nix {};
+  k3s = handleTest ./k3s.nix {};
   kafka = handleTest ./kafka.nix {};
   keepalived = handleTest ./keepalived.nix {};
   kerberos = handleTest ./kerberos/default.nix {};
@@ -155,6 +162,7 @@ in
   # kubernetes.e2e should eventually replace kubernetes.rbac when it works
   #kubernetes.e2e = handleTestOn ["x86_64-linux"] ./kubernetes/e2e.nix {};
   kubernetes.rbac = handleTestOn ["x86_64-linux"] ./kubernetes/rbac.nix {};
+  latestKernel.hardened = handleTest ./hardened.nix { latestKernel = true; };
   latestKernel.login = handleTest ./login.nix { latestKernel = true; };
   ldap = handleTest ./ldap.nix {};
   leaps = handleTest ./leaps.nix {};
@@ -166,6 +174,7 @@ in
   #logstash = handleTest ./logstash.nix {};
   lorri = handleTest ./lorri/default.nix {};
   magnetico = handleTest ./magnetico.nix {};
+  magic-wormhole-mailbox-server = handleTest ./magic-wormhole-mailbox-server.nix {};
   mailcatcher = handleTest ./mailcatcher.nix {};
   mathics = handleTest ./mathics.nix {};
   matomo = handleTest ./matomo.nix {};
@@ -197,7 +206,7 @@ in
   nat.standalone = handleTest ./nat.nix { withFirewall = false; };
   ndppd = handleTest ./ndppd.nix {};
   neo4j = handleTest ./neo4j.nix {};
-  nesting = handleTest ./nesting.nix {};
+  specialisation = handleTest ./specialisation.nix {};
   netdata = handleTest ./netdata.nix {};
   networking.networkd = handleTest ./networking.nix { networkd = true; };
   networking.scripted = handleTest ./networking.nix { networkd = false; };
@@ -211,6 +220,7 @@ in
   nghttpx = handleTest ./nghttpx.nix {};
   nginx = handleTest ./nginx.nix {};
   nginx-etag = handleTest ./nginx-etag.nix {};
+  nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
   nginx-sso = handleTest ./nginx-sso.nix {};
   nix-ssh-serve = handleTest ./nix-ssh-serve.nix {};
   nixos-generate-config = handleTest ./nixos-generate-config.nix {};
@@ -235,7 +245,7 @@ in
   peerflix = handleTest ./peerflix.nix {};
   pgjwt = handleTest ./pgjwt.nix {};
   pgmanage = handleTest ./pgmanage.nix {};
-  php-pcre = handleTest ./php-pcre.nix {};
+  php = handleTest ./php {};
   plasma5 = handleTest ./plasma5.nix {};
   plotinus = handleTest ./plotinus.nix {};
   postgis = handleTest ./postgis.nix {};
@@ -251,6 +261,7 @@ in
   prosodyMysql = handleTest ./xmpp/prosody-mysql.nix {};
   proxy = handleTest ./proxy.nix {};
   quagga = handleTest ./quagga.nix {};
+  quorum = handleTest ./quorum.nix {};
   rabbitmq = handleTest ./rabbitmq.nix {};
   radarr = handleTest ./radarr.nix {};
   radicale = handleTest ./radicale.nix {};
@@ -296,17 +307,21 @@ in
   timezone = handleTest ./timezone.nix {};
   tinydns = handleTest ./tinydns.nix {};
   tor = handleTest ./tor.nix {};
+  # traefik test relies on docker-containers
+  traefik = handleTestOn ["x86_64-linux"] ./traefik.nix {};
   transmission = handleTest ./transmission.nix {};
   trac = handleTest ./trac.nix {};
   trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {};
   trezord = handleTest ./trezord.nix {};
   trickster = handleTest ./trickster.nix {};
+  tuptime = handleTest ./tuptime.nix {};
   udisks2 = handleTest ./udisks2.nix {};
   upnp = handleTest ./upnp.nix {};
   uwsgi = handleTest ./uwsgi.nix {};
   vault = handleTest ./vault.nix {};
   victoriametrics = handleTest ./victoriametrics.nix {};
   virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {};
+  wg-quick = handleTest ./wireguard/wg-quick.nix {};
   wireguard = handleTest ./wireguard {};
   wireguard-generated = handleTest ./wireguard/generated.nix {};
   wireguard-namespaces = handleTest ./wireguard/namespaces.nix {};
diff --git a/nixpkgs/nixos/tests/caddy.nix b/nixpkgs/nixos/tests/caddy.nix
index fc10df0c79b5..144d83179a16 100644
--- a/nixpkgs/nixos/tests/caddy.nix
+++ b/nixpkgs/nixos/tests/caddy.nix
@@ -20,35 +20,33 @@ import ./make-test-python.nix ({ pkgs, ... }: {
         }
       '';
 
-      nesting.clone = [
-        {
-          services.caddy.config = lib.mkForce ''
-            http://localhost {
-              gzip
+      specialisation.etag.configuration = {
+        services.caddy.config = lib.mkForce ''
+          http://localhost {
+            gzip
 
-              root ${
-                pkgs.runCommand "testdir2" {} ''
-                  mkdir "$out"
-                  echo changed > "$out/example.html"
-                ''
-              }
+            root ${
+              pkgs.runCommand "testdir2" {} ''
+                mkdir "$out"
+                echo changed > "$out/example.html"
+              ''
             }
-          '';
-        }
+          }
+        '';
+      };
 
-        {
-          services.caddy.config = ''
-            http://localhost:8080 {
-            }
-          '';
-        }
-      ];
+      specialisation.config-reload.configuration = {
+        services.caddy.config = ''
+          http://localhost:8080 {
+          }
+        '';
+      };
     };
   };
 
   testScript = { nodes, ... }: let
-    etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1";
-    justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2";
+    etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag";
+    justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload";
   in ''
     url = "http://localhost/example.html"
     webserver.wait_for_unit("caddy")
@@ -77,7 +75,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
         assert old_etag != new_etag, "Old ETag {} is the same as {}".format(
             old_etag, new_etag
         )
-    
+
     with subtest("config is reloaded on nixos-rebuild switch"):
         webserver.succeed(
             "${justReloadSystem}/bin/switch-to-configuration test >&2"
diff --git a/nixpkgs/nixos/tests/ceph-multi-node.nix b/nixpkgs/nixos/tests/ceph-multi-node.nix
index 90dd747525de..22fe5cada480 100644
--- a/nixpkgs/nixos/tests/ceph-multi-node.nix
+++ b/nixpkgs/nixos/tests/ceph-multi-node.nix
@@ -183,15 +183,15 @@ let
     monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
 
     monA.succeed(
-        "ceph osd pool create multi-node-test 100 100",
+        "ceph osd pool create multi-node-test 128 128",
         "ceph osd pool ls | grep 'multi-node-test'",
         "ceph osd pool rename multi-node-test multi-node-other-test",
         "ceph osd pool ls | grep 'multi-node-other-test'",
     )
-    monA.wait_until_succeeds("ceph -s | grep '1 pools, 100 pgs'")
+    monA.wait_until_succeeds("ceph -s | grep '1 pools, 128 pgs'")
     monA.succeed("ceph osd pool set multi-node-other-test size 2")
     monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
-    monA.wait_until_succeeds("ceph -s | grep '100 active+clean'")
+    monA.wait_until_succeeds("ceph -s | grep '128 active+clean'")
     monA.fail(
         "ceph osd pool ls | grep 'multi-node-test'",
         "ceph osd pool delete multi-node-other-test multi-node-other-test --yes-i-really-really-mean-it",
diff --git a/nixpkgs/nixos/tests/ceph-single-node.nix b/nixpkgs/nixos/tests/ceph-single-node.nix
index 1a027e178367..01c4b4138451 100644
--- a/nixpkgs/nixos/tests/ceph-single-node.nix
+++ b/nixpkgs/nixos/tests/ceph-single-node.nix
@@ -143,12 +143,12 @@ let
     monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
 
     monA.succeed(
-        "ceph osd pool create single-node-test 100 100",
+        "ceph osd pool create single-node-test 128 128",
         "ceph osd pool ls | grep 'single-node-test'",
         "ceph osd pool rename single-node-test single-node-other-test",
         "ceph osd pool ls | grep 'single-node-other-test'",
     )
-    monA.wait_until_succeeds("ceph -s | grep '1 pools, 100 pgs'")
+    monA.wait_until_succeeds("ceph -s | grep '1 pools, 128 pgs'")
     monA.succeed(
         "ceph osd getcrushmap -o crush",
         "crushtool -d crush -o decrushed",
@@ -158,7 +158,7 @@ let
         "ceph osd pool set single-node-other-test size 2",
     )
     monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
-    monA.wait_until_succeeds("ceph -s | grep '100 active+clean'")
+    monA.wait_until_succeeds("ceph -s | grep '128 active+clean'")
     monA.fail(
         "ceph osd pool ls | grep 'multi-node-test'",
         "ceph osd pool delete single-node-other-test single-node-other-test --yes-i-really-really-mean-it",
diff --git a/nixpkgs/nixos/tests/cockroachdb.nix b/nixpkgs/nixos/tests/cockroachdb.nix
index 496283fddc7b..d0cc5e19837c 100644
--- a/nixpkgs/nixos/tests/cockroachdb.nix
+++ b/nixpkgs/nixos/tests/cockroachdb.nix
@@ -1,7 +1,7 @@
 # This performs a full 'end-to-end' test of a multi-node CockroachDB cluster
 # using the built-in 'cockroach workload' command, to simulate a semi-realistic
 # test load. It generally takes anywhere from 3-5 minutes to run and 1-2GB of
-# RAM (though each of 3 workers gets 1GB allocated)
+# RAM (though each of 3 workers gets 2GB allocated)
 #
 # CockroachDB requires synchronized system clocks within a small error window
 # (~500ms by default) on each node in order to maintain a multi-node cluster.
@@ -55,7 +55,7 @@ let
 
     {
       # Bank/TPC-C benchmarks take some memory to complete
-      virtualisation.memorySize = 1024;
+      virtualisation.memorySize = 2048;
 
       # Install the KVM PTP "Virtualized Clock" driver. This allows a /dev/ptp0
       # device to appear as a reference clock, synchronized to the host clock.
@@ -88,6 +88,8 @@ let
       services.cockroachdb.listen.address = myAddr;
       services.cockroachdb.join = lib.mkIf (joinNode != null) joinNode;
 
+      systemd.services.chronyd.unitConfig.ConditionPathExists = "/dev/ptp0";
+
       # Hold startup until Chrony has performed its first measurement (which
       # will probably result in a full timeskip, thanks to makestep)
       systemd.services.cockroachdb.preStart = ''
@@ -95,7 +97,7 @@ let
       '';
     };
 
-in import ./make-test.nix ({ pkgs, ...} : {
+in import ./make-test-python.nix ({ pkgs, ...} : {
   name = "cockroachdb";
   meta.maintainers = with pkgs.stdenv.lib.maintainers;
     [ thoughtpolice ];
@@ -110,17 +112,13 @@ in import ./make-test.nix ({ pkgs, ...} : {
   # there's otherwise no way to guarantee that node1 will start before the others try
   # to join it.
   testScript = ''
-    $node1->start;
-    $node1->waitForUnit("cockroachdb");
-
-    $node2->start;
-    $node2->waitForUnit("cockroachdb");
-
-    $node3->start;
-    $node3->waitForUnit("cockroachdb");
-
-    $node1->mustSucceed("cockroach sql --host=192.168.1.1 --insecure -e 'SHOW ALL CLUSTER SETTINGS' 2>&1");
-    $node1->mustSucceed("cockroach workload init bank 'postgresql://root\@192.168.1.1:26257?sslmode=disable'");
-    $node1->mustSucceed("cockroach workload run bank --duration=1m 'postgresql://root\@192.168.1.1:26257?sslmode=disable'");
+    for node in node1, node2, node3:
+        node.start()
+        node.wait_for_unit("cockroachdb")
+    node1.succeed(
+        "cockroach sql --host=192.168.1.1 --insecure -e 'SHOW ALL CLUSTER SETTINGS' 2>&1",
+        "cockroach workload init bank 'postgresql://root@192.168.1.1:26257?sslmode=disable'",
+        "cockroach workload run bank --duration=1m 'postgresql://root@192.168.1.1:26257?sslmode=disable'",
+    )
   '';
 })
diff --git a/nixpkgs/nixos/tests/common/acme/client/default.nix b/nixpkgs/nixos/tests/common/acme/client/default.nix
new file mode 100644
index 000000000000..80893da02524
--- /dev/null
+++ b/nixpkgs/nixos/tests/common/acme/client/default.nix
@@ -0,0 +1,15 @@
+{ lib, nodes, pkgs, ... }:
+
+let
+  acme-ca = nodes.acme.config.test-support.acme.caCert;
+in
+
+{
+  security.acme = {
+    server = "https://acme.test/dir";
+    email = "hostmaster@example.test";
+    acceptTerms = true;
+  };
+
+  security.pki.certificateFiles = [ acme-ca ];
+}
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/default.nix b/nixpkgs/nixos/tests/common/acme/server/default.nix
index 110a2520971d..1a0ee882572c 100644
--- a/nixpkgs/nixos/tests/common/letsencrypt/default.nix
+++ b/nixpkgs/nixos/tests/common/acme/server/default.nix
@@ -1,27 +1,27 @@
 # The certificate for the ACME service is exported as:
 #
-#   config.test-support.letsencrypt.caCert
+#   config.test-support.acme.caCert
 #
 # This value can be used inside the configuration of other test nodes to inject
 # the snakeoil certificate into security.pki.certificateFiles or into package
 # overlays.
 #
 # Another value that's needed if you don't use a custom resolver (see below for
-# notes on that) is to add the letsencrypt node as a nameserver to every node
+# notes on that) is to add the acme node as a nameserver to every node
 # that needs to acquire certificates using ACME, because otherwise the API host
-# for letsencrypt.org can't be resolved.
+# for acme.test can't be resolved.
 #
 # A configuration example of a full node setup using this would be this:
 #
 # {
-#   letsencrypt = import ./common/letsencrypt;
+#   acme = import ./common/acme/server;
 #
 #   example = { nodes, ... }: {
 #     networking.nameservers = [
-#       nodes.letsencrypt.config.networking.primaryIPAddress
+#       nodes.acme.config.networking.primaryIPAddress
 #     ];
 #     security.pki.certificateFiles = [
-#       nodes.letsencrypt.config.test-support.letsencrypt.caCert
+#       nodes.acme.config.test-support.acme.caCert
 #     ];
 #   };
 # }
@@ -33,9 +33,9 @@
 # override networking.nameservers like this:
 #
 # {
-#   letsencrypt = { nodes, ... }: {
-#     imports = [ ./common/letsencrypt ];
-#     networking.nameservers = [
+#   acme = { nodes, lib, ... }: {
+#     imports = [ ./common/acme/server ];
+#     networking.nameservers = lib.mkForce [
 #       nodes.myresolver.config.networking.primaryIPAddress
 #     ];
 #   };
@@ -55,16 +55,16 @@
 let
   snakeOilCerts = import ./snakeoil-certs.nix;
 
-  wfeDomain = "acme-v02.api.letsencrypt.org";
+  wfeDomain = "acme.test";
   wfeCertFile = snakeOilCerts.${wfeDomain}.cert;
   wfeKeyFile = snakeOilCerts.${wfeDomain}.key;
 
-  siteDomain = "letsencrypt.org";
+  siteDomain = "acme.test";
   siteCertFile = snakeOilCerts.${siteDomain}.cert;
   siteKeyFile = snakeOilCerts.${siteDomain}.key;
   pebble = pkgs.pebble;
   resolver = let
-    message = "You need to define a resolver for the letsencrypt test module.";
+    message = "You need to define a resolver for the acme test module.";
     firstNS = lib.head config.networking.nameservers;
   in if config.networking.nameservers == [] then throw message else firstNS;
 
@@ -76,15 +76,16 @@ let
     httpPort = 80;
     tlsPort = 443;
     ocspResponderURL = "http://0.0.0.0:4002";
+    strict = true;
   };
 
   pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf);
   pebbleDataDir = "/root/pebble";
 
 in {
-  imports = [ ../resolver.nix ];
+  imports = [ ../../resolver.nix ];
 
-  options.test-support.letsencrypt.caCert = lib.mkOption {
+  options.test-support.acme.caCert = lib.mkOption {
     type = lib.types.path;
     description = ''
       A certificate file to use with the <literal>nodes</literal> attribute to
@@ -98,7 +99,7 @@ in {
       resolver.enable = let
         isLocalResolver = config.networking.nameservers == [ "127.0.0.1" ];
       in lib.mkOverride 900 isLocalResolver;
-      letsencrypt.caCert = snakeOilCerts.ca.cert;
+      acme.caCert = snakeOilCerts.ca.cert;
     };
 
     # This has priority 140, because modules/testing/test-instrumentation.nix
@@ -126,8 +127,7 @@ in {
         '';
         serviceConfig = {
           # Required to bind on privileged ports.
-          User = "root";
-          Group = "root";
+          AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
         };
       };
     };
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix b/nixpkgs/nixos/tests/common/acme/server/mkcerts.nix
index e7ac2bae46bd..2474019cbac3 100644
--- a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.nix
+++ b/nixpkgs/nixos/tests/common/acme/server/mkcerts.nix
@@ -1,10 +1,9 @@
 { pkgs ? import <nixpkgs> {}
 , lib ? pkgs.lib
-
-, domains ? [ "acme-v02.api.letsencrypt.org" "letsencrypt.org" ]
+, domains ? [ "acme.test" ]
 }:
 
-pkgs.runCommand "letsencrypt-snakeoil-ca" {
+pkgs.runCommand "acme-snakeoil-ca" {
   nativeBuildInputs = [ pkgs.openssl ];
 } ''
   addpem() {
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh b/nixpkgs/nixos/tests/common/acme/server/mkcerts.sh
index cc7f8ca650dd..cc7f8ca650dd 100755
--- a/nixpkgs/nixos/tests/common/letsencrypt/mkcerts.sh
+++ b/nixpkgs/nixos/tests/common/acme/server/mkcerts.sh
diff --git a/nixpkgs/nixos/tests/common/acme/server/snakeoil-certs.nix b/nixpkgs/nixos/tests/common/acme/server/snakeoil-certs.nix
new file mode 100644
index 000000000000..fd537c3260f1
--- /dev/null
+++ b/nixpkgs/nixos/tests/common/acme/server/snakeoil-certs.nix
@@ -0,0 +1,171 @@
+# Generated via mkcert.sh in the same directory.
+{
+  ca.key = builtins.toFile "ca.key" ''
+    -----BEGIN PRIVATE KEY-----
+    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
+    JUsBXFNz132nP4iIr3UKrPedQZijSi4=
+    -----END PRIVATE KEY-----
+  '';
+  ca.cert = builtins.toFile "ca.cert" ''
+    -----BEGIN CERTIFICATE-----
+    MIIFDzCCAvegAwIBAgIUTRDYSWJvmlhwIR3pzVrIQfnboLEwDQYJKoZIhvcNAQEL
+    BQAwFjEUMBIGA1UEAwwLU25ha2VvaWwgQ0EwIBcNMjAwMzIyMjI1NjE3WhgPMjEy
+    MDAyMjcyMjU2MTdaMBYxFDASBgNVBAMMC1NuYWtlb2lsIENBMIICIjANBgkqhkiG
+    9w0BAQEFAAOCAg8AMIICCgKCAgEAwp1WRhJ+vHs15Q1hOYI7Aj6rrUeJ8cP8LyGw
+    MQdlZNlnkOhxr7diXa8+anq9iF3e+mLaUHqnfn33rWi7THhU6/l8vcqhKcdgH75h
+    BHC57olm7FBmc7B8Fu/+JD4ABQcvU8CZ/5PPdpUerkGGtEEt/Ql/OZCzGfy2V1Mg
+    pSAWviMU9TqL5hqjDq+JxgEkUD+nf558p+NSp2rf3bacmmuc4H2MAOmFulMXMsLw
+    UqTDlzNP/NgRWRsgC7d50Pn35q7SnLzI7DSwRWrJVfs2DtTzGy20wlvEpiU44c7m
+    qV7QR67r6HtuNd911pb3D9cpWk8dGpcIkFia9VxDlFixBU4Dk3kcolQ8Q7p6c/u6
+    BnMM3HThvJwoHesNGmGhAs9c70txWE0M/jIqphJMerOG49VPdCNJMFCW3lo46xju
+    2PUKuItfRmnw4O3ADJ/XhwojWzaz4+rf4H2lWwq25Jt2VY5Ly00Npm9pb+/rVYou
+    Odtu4jT7jUupcdhVZa/w14kazlX4IT76DsVH186ICYWS1eGZIvsnGxkGucPGDA2A
+    r+HNPHSgOwGrVYTUutHNc4EDY7lhdwb6HEskshlKJ1U+odQ2JSfWAKoKjaXnYDUf
+    ZKadN+EjIQe3Y/ZXgei0TAPnNXxv0/tZQ25APr6KXqbePt9KA3Ak2HxIn5dR8Kjc
+    P21w5tcCAwEAAaNTMFEwHQYDVR0OBBYEFCIoeYSYjtMiPrmxfHmcrsZkyTpvMB8G
+    A1UdIwQYMBaAFCIoeYSYjtMiPrmxfHmcrsZkyTpvMA8GA1UdEwEB/wQFMAMBAf8w
+    DQYJKoZIhvcNAQELBQADggIBAHPdwOgAxyhIhbqFObNftW8K3sptorB/Fj6jwYCm
+    mHleFueqQnjTHMWsflOjREvQp1M307FWooGj+KQkjwvAyDc/Hmy7WgJxBg9p3vc+
+    /Xf/e7ZfBl8rv7vH8VXW/BC1vVsILdFncrgTrP8/4psV50/cl1F4+nPBiekvvxwZ
+    k+R7SgeSvcWT7YlOG8tm1M3al4F4mWzSRkYjkrXmwRCKAiya9xcGSt0Bob+LoM/O
+    mpDGV/PMC1WAoDc1mMuXN2hSc0n68xMcuFs+dj/nQYn8uL5pzOxpX9560ynKyLDv
+    yOzQlM2VuZ7H2hSIeYOFgrtHJJwhDtzjmUNDQpQdp9Fx+LONQTS1VLCTXND2i/3F
+    10X6PkdnLEn09RiPt5qy20pQkICxoEydmlwpFs32musYfJPdBPkZqZWrwINBv2Wb
+    HfOmEB4xUvXufZ5Ju5icgggBkyNA3PCLo0GZFRrMtvA7i9IXOcXNR+njhKa9246V
+    QQfeWiz05RmIvgShJYVsnZWtael8ni366d+UXypBYncohimyNlAD1n+Bh3z0PvBB
+    +FK4JgOSeouM4SuBHdwmlZ/H0mvfUG81Y8Jbrw0yuRHtuCtX5HpN5GKpZPHDE7aQ
+    fEShVB/GElC3n3DvgK9OJBeVVhYQgUEfJi4rsSxt3cdEI0NrdckUoZbApWVJ3CBc
+    F8Y7
+    -----END CERTIFICATE-----
+  '';
+  "acme.test".key = builtins.toFile "acme.test.key" ''
+    -----BEGIN RSA PRIVATE KEY-----
+    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
+    -----END RSA PRIVATE KEY-----
+  '';
+  "acme.test".cert = builtins.toFile "acme.test.cert" ''
+    -----BEGIN CERTIFICATE-----
+    MIIEoTCCAokCAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls
+    IENBMCAXDTIwMDMyMjIyNTYxOFoYDzIxMjAwMjI3MjI1NjE4WjAUMRIwEAYDVQQD
+    DAlhY21lLnRlc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCWBBNm
+    Mp+zdofDQn33eTuMUCz6FVE9///McwCJSQ8pRg9NKXVPFL9s9uFbNKiibTSPhIuE
+    YYaFt36We9ODS68pvGySABN/DlyVubVk36DHgO7HCMtXfEjGl5Jj48rOznPzD+T4
+    AmH7M4/JfAfe63cL6iCnVL/kiGbNXdr/JT/qTTOkbGM3pk9FNcWvP3cjWk94KQnP
+    3SXu2P7a4Vz3G0zbQ1BfnZ/RjahKFwbx8p01lXO4ceRleStkiGi7nn+dHLaMqAV4
+    PcZBB9r2vA9atXJtDq0owyShrMH9SeTL3FxMjYslqt/GAcM72/3IUG+ZHhQzwHeQ
+    zzY0egQ20dpnaaaIwZnNMRCV/zHBjIcWuoEUhVFYRSvuuv87lCv2Ag3RPi7frscJ
+    7FVgArNs7Y/2HvlzPOMwygaRtfN71IxD+KSvESbAAeCvVfGHqJBiaA82TwBHd336
+    jYjtYlkxRhkBEue6FWv0E1e/nXSKplOpfyVzIvl8SPdJPgBv4fut969m3o1TbqIk
+    sFgCOsDaZK8f7C+RujGuBJLzFg+Q5bw0s0Rtuh3Oh8ikH5Jornc4iTRuP1zVgCCt
+    I0RH9MNOANetZQ2uV9Vn8zv4AR15TTrCLuxWFWJ/o4EPc6mApI2N4TpO4kfzQ+Lk
+    xa6BIUGvv3Zdvq6FWg+JU4U36qIYHpSTAGBIqQIDAQABMA0GCSqGSIb3DQEBCwUA
+    A4ICAQBCDs0V4z00Ze6Ask3qDOLAPo4k85QCfItlRZmwl2XbPZq7kbe13MqF2wxx
+    yiLalm6veK+ehU9MYN104hJZnuce5iEcZurk+8A+Pwn1Ifz+oWKVbUtUP3uV8Sm3
+    chktJ2H1bebXtNJE5TwvdHiUkXU9ywQt2FkxiTSl6+eac7JKEQ8lVN/o6uYxF5ds
+    +oIZplb7bv2XxsRCzq55F2tJX7fIzqXrSa+lQTnfLGmDVMAQX4TRB/lx0Gqd1a9y
+    qGfFnZ7xVyW97f6PiL8MoxPfd2I2JzrzGyP/igNbFOW0ho1OwfxVmvZeS7fQSc5e
+    +qu+nwnFfl0S4cHRif3G3zmz8Ryx9LM5TYkH41qePIHxoEO2sV0DgWJvbSjysV2S
+    EU2a31dJ0aZ+z6YtZVpHlujKMVzxVTrqj74trS4LvU5h/9hv7e1gjYdox1TO0HMK
+    mtDfgBevB21Tvxpz67Ijf31HvfTmCerKJEOjGnbYmyYpMeMNSONRDcToWk8sUwvi
+    OWa5jlUFRAxgXNM09vCTPi9aRUhcFqACqfAd6I1NqGVlfplLWrc7SWaSa+PsLfBf
+    4EOZfk8iEKBVeYXNjg+CcD8j8yk/oEs816/jpihIk8haCDRWYWGKyyGnwn6OQb8d
+    MdRO2b7Oi/AAmEF3jMlICqv286GIYK5qTKk2/CKHlOLPnsWEuA==
+    -----END CERTIFICATE-----
+  '';
+}
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/common.nix b/nixpkgs/nixos/tests/common/letsencrypt/common.nix
deleted file mode 100644
index bd559c8dacc5..000000000000
--- a/nixpkgs/nixos/tests/common/letsencrypt/common.nix
+++ /dev/null
@@ -1,12 +0,0 @@
-{ lib, nodes, pkgs, ... }: let
-  letsencrypt-ca = nodes.letsencrypt.config.test-support.letsencrypt.caCert;
-in {
-  networking.nameservers = [
-    nodes.letsencrypt.config.networking.primaryIPAddress
-  ];
-
-  security.acme.acceptTerms = true;
-  security.acme.email = "webmaster@example.com";
-
-  security.pki.certificateFiles = [ letsencrypt-ca ];
-}
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix b/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix
deleted file mode 100644
index ca4f71ae688a..000000000000
--- a/nixpkgs/nixos/tests/common/letsencrypt/snakeoil-certs.nix
+++ /dev/null
@@ -1,254 +0,0 @@
-# Generated via mkcert.sh in the same directory.
-{
-  ca.key = builtins.toFile "ca.key" ''
-    -----BEGIN PRIVATE KEY-----
-    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
-    Eq4OVTSu/s8gmY94tgbjeOaLUPEPmg==
-    -----END PRIVATE KEY-----
-  '';
-  ca.cert = builtins.toFile "ca.cert" ''
-    -----BEGIN CERTIFICATE-----
-    MIIFDzCCAvegAwIBAgIUU9rbCLTuvaI6gjSsFsJJjfLWIX8wDQYJKoZIhvcNAQEL
-    BQAwFjEUMBIGA1UEAwwLU25ha2VvaWwgQ0EwIBcNMTkxMDE4MDc1NDEyWhgPMjEx
-    OTA5MjQwNzU0MTJaMBYxFDASBgNVBAMMC1NuYWtlb2lsIENBMIICIjANBgkqhkiG
-    9w0BAQEFAAOCAg8AMIICCgKCAgEA0NG9tyNbKyWcEdjDHb0iSuaXMC3611PuIBGR
-    J1jck/MnlcHsmvvL5jTTpbyt88X/mYmP+2kNEWSTDodvlXZYB5q9kCoUE39R8H2Q
-    P9OhaJQ9/w3EvgzCTEk1a9e/f1y53XlVWVKlO7Y7wQFikiEvB9oUhdVDj4vYAQ0f
-    DMAj+kII/FmIW5LfauO/5TveqgJpulNRfkO0WDPWUCFiPNTdDLOcCaHIO5+ktfYl
-    eunj4ewD2qWRWLqetYBRln2oZgNtexCyGXeep/MozhdHqW/bAtF6WAg0a2CgVi6j
-    4r/usL3WbWbwCyLciL9PGcF5QZBYNy2wAIT539Fcc6WMrEJssss5IMtudp/kontJ
-    MfgeKpunzpKX4GJT0lU29nV8f23v0hNPLtGvRTtH2aZAclhGSVFMJ4LCYC1GuzKK
-    0H92r8aM3wtuV6r824nmX0l5QO5jlHJWWwv1lBacozJciVNngkPMEsLD15fdaMXG
-    JTpLlS4HeNYK/aRl0EriiJK4G35H7Y4NrQwvu4OzvKq3ReNhY22YyMf++AGrJrBo
-    eBk0LYkpLxJ07LYqAumgleOA5SVmwSDL5MmsLm41JT6Yo9B+umPUOLRHP5LXO6Bk
-    H6qpbsi2+N03qG0zxwC7DXgGG9/azLQaOQwwlHPNbH7gzITK/6GFyqxbLVLIOQGO
-    piWkRtECAwEAAaNTMFEwHQYDVR0OBBYEFAZcEiVphGxBT4OWXbM6lKu96dvbMB8G
-    A1UdIwQYMBaAFAZcEiVphGxBT4OWXbM6lKu96dvbMA8GA1UdEwEB/wQFMAMBAf8w
-    DQYJKoZIhvcNAQELBQADggIBAGJ5Jnxq1IQ++IRYxCE7r7BqzzF+HTx0EWKkSOmt
-    eSPqeOdhC26hJlclgGZXAF/Xosmn8vkSQMHhj/jr4HI0VF9IyvDUJm8AKsnOgu/7
-    DUey3lEUdOtJpTG9NyTOcrzxToMJ+hWlFLZKxx2dk4FLIvTLjmo1VHM97Bat7XYW
-    IrL9RRIZ25V+eCYtlR7XYjceGFQ0rCdp8SFIQwC6C/AH2tV3b1AJFsND9PcoLu7c
-    //fH+WUQCcD/N0grdC/QCX7AFWzd4rKQ8gjfND4TSYFTSDwW10Mud4kAVhY2P1sY
-    Y3ZpnxWrCHbIZMbszlbMyD+cjsCBnNvOtYGm7pDut/371rllVcB/uOWYWMCtKPoj
-    0elPrwNMrK+P+wceNBCRQO+9gwzB589F2morFTtsob/qtpAygW8Sfl8M+iLWXeYS
-    c3LBLnj0TpgXKRWg7wgIWKSZx9v6pgy70U0qvkjNS1XseUCPf7hfAbxT3xF+37Dw
-    zZRwF4WAWqdnJoOey21mgc+a2DQzqtykA6KfHgCqNFfDbQXPXvNy25DDThbk+paX
-    G2M2EWtr+Nv9s/zm7Xv/pOXlgMFavaj+ikqZ4wfJf6c/sMOdZJtMA4TsYtAJgbc8
-    ts+0eymTq4v5S8/fW51Lbjw6hc1Kcm8k7NbHSi9sEjBfxFLTZNQ5eb4NGr9Od3sU
-    kgwJ
-    -----END CERTIFICATE-----
-  '';
-  "acme-v02.api.letsencrypt.org".key = builtins.toFile "acme-v02.api.letsencrypt.org.key" ''
-    -----BEGIN RSA PRIVATE KEY-----
-    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
-    -----END RSA PRIVATE KEY-----
-  '';
-  "acme-v02.api.letsencrypt.org".cert = builtins.toFile "acme-v02.api.letsencrypt.org.cert" ''
-    -----BEGIN CERTIFICATE-----
-    MIIEtDCCApwCAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls
-    IENBMCAXDTE5MTAxODA3NTQxM1oYDzIxMTkwOTI0MDc1NDEzWjAnMSUwIwYDVQQD
-    DBxhY21lLXYwMi5hcGkubGV0c2VuY3J5cHQub3JnMIICIjANBgkqhkiG9w0BAQEF
-    AAOCAg8AMIICCgKCAgEApny0WhfDwEXe6WDTCw8qBuMAPDr88pj6kbhQWfzAW2c0
-    TggJEtjs9dktENeTpSl14nnLVMiSYIJPYY3KbOIFQH1qDaOuQ7NaOhj9CdMTm5r9
-    bl+CYAyqLIMQ9AAZDhUcQjOy3moiL7ClFHlkFYuEzZBO9DF7hJpfUFIs0Idg50mN
-    oZh/K/fb4P2skNjfCjjomTRUmZHxT6G00ImSTtSaYbN/WHut1xXwJvOoT1nlEA/P
-    ghKmJJ9ZuRMSddUJmjL+sT09L8LVkK8CKeHi4r58DHM0D0u8owIFV9qsXd5UvZHa
-    NgvQ4OAWGukMX+TxRuqkUZkaj84vnNL+ttEMl4jedw0ImzNtCOYehDyTPRkfng5P
-    LWMSvWbwyP8jDd2578mSbx5BF7ypYX366+vknjIFyZ5WezcC1pscIHxLoEwuhuf+
-    knN+kFkLOHeYbqQrU6mxSnu9q0hnNvGUkTP0a/1aLOGRfQ5C/pxpE/Rebi8qfM/O
-    JFd4mSxGL93JUTXWAItiIeBnQpIne65/Ska9dWynOEfIb0okdet3kfmNHz3zc17d
-    Z5g4AdOSCgHAlQgFt/Qd8W6xXUe4C5Mfv2ctxRrfQhDwtB6rMByPwzImnciC2h3v
-    CwD3vS/vjUyWICyhZyi2LZDUQz+sCKBXCYYcYh8ThFO40j5x1OnYMq7XQvyl8QkC
-    AwEAATANBgkqhkiG9w0BAQsFAAOCAgEAkx0GLPuCvKSLTHxVLh5tP4jxSGG/zN37
-    PeZLu3QJTdRdRc8bgeOGXAVEVFbqOLTNTsuY1mvpiv2V6wxR6nns+PIHeLY/UOdc
-    mOreKPtMU2dWPp3ybec2Jwii6PhAXZJ26AKintmug1psMw7662crR3SCnn85/CvW
-    192vhr5gM1PqLBIlbsX0tAqxAwBe1YkxBb9vCq8NVghJlKme49xnwGULMTGs15MW
-    hIPx6sW93zwrGiTsDImH49ILGF+NcX1AgAq90nG0j/l5zhDgXGJglX+K1xP99X1R
-    de3I4uoufPa5q+Pjmhy7muL+o4Qt0D0Vm86RqqjTkNPsr7gAJtt66A7TJrYiIoKn
-    GTIBsgM6egeFLLYQsT0ap/59HJismO2Pjx4Jk/jHOkC8TJsXQNRq1Km76VMBnuc0
-    2CMoD9pb38GjUUH94D4hJK4Ls/gJMF3ftKUyR8Sr/LjE6qU6Yj+ZpeEQP4kW9ANq
-    Lv9KSNDQQpRTL4LwGLTGomksLTQEekge7/q4J2TQRZNYJ/mxnrBKRcv9EAMgBMXq
-    Q+7GHtKDv9tJVlMfG/MRD3CMuuSRiT3OVbvMMkFzsPkqxYAP1CqE/JGvh67TzKI+
-    MUfXKehA6TKuxrTVqCtoFIfGaqA9IWyoRTtugYq/xssB9ESeEYGeaM1A9Yueqz+h
-    KkBZO00jHSE=
-    -----END CERTIFICATE-----
-  '';
-  "letsencrypt.org".key = builtins.toFile "letsencrypt.org.key" ''
-    -----BEGIN RSA PRIVATE KEY-----
-    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
-    -----END RSA PRIVATE KEY-----
-  '';
-  "letsencrypt.org".cert = builtins.toFile "letsencrypt.org.cert" ''
-    -----BEGIN CERTIFICATE-----
-    MIIEpzCCAo8CAgKaMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC1NuYWtlb2ls
-    IENBMCAXDTE5MTAxODA3NTQxNVoYDzIxMTkwOTI0MDc1NDE1WjAaMRgwFgYDVQQD
-    DA9sZXRzZW5jcnlwdC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-    AQD12l08TLMPf8EF2zu0D/nWz5aYsXJa4WurjIx3ZH6+LmC8rueUs1UqFiCJOYrZ
-    Sb5QSka5wmpkdxNJkDUHPhL/w0P8Aj0joSbC8GKdjn8+5vEQAuT1iIMD4jMfxkYU
-    zzBeDt8xtskCzK/5IcC2vaOYKyCCum4Pl+DOzan4XarT6hWh4XAwA5R0B/aM200s
-    SPZDoyJHler7AU5xG1eU2VdYhfc2ua5s7/E6kM2mzKPJgLkt35bToxLltMdJ2/no
-    CRSDY+6AwKGPXlM510QkgrzM9cVOUxjJ71IrCOE1Rmi997jFcJpOPaebOty4wovP
-    5LewpB5NaOJFxjfDjNOUBuG0ZcONeOEw5usehYzx7dxMvg0ky+201K1d+JzFt5Ns
-    iJi77t20XSr6JZpmp7Fzo90BoikVnRdLD6LmIt1BmYHDNjs0uUelC6l+HrN7SoNR
-    VkAwO5ujgkpRMHMfpBO6EfH65Sbstzxh00Cufuj+8xkNDKbUSJrErFm4IZqoW+rx
-    kricFWwd9xduEX9cPYcyJ3e3siZtERW72qdz4Sf5pxT9IlpoveuMxboctUyvr69C
-    sLNiS8vMpimhSb0PUpyfp3w5/GXaIJpj0KQyvn/onWnXBxN1w3shVD8MUF5MNq7J
-    ZvJmQ7+U+hmhqRbJc7H1L22AKXOEWY2BGRm/3A35CC40NwIDAQABMA0GCSqGSIb3
-    DQEBCwUAA4ICAQBbJwE+qc0j6JGHWe0TGjv1viJU3WuyJkMRi+ejx0p/k7Ntp5An
-    2wLC7b/lVP/Nh+PKY/iXWn/BErv2MUo4POc1g8svgxsmMMh5KGGieIfGs7xT+JMH
-    dzZZM+pUpIB5fEO5JfjiOEOKDdAvRSs0mTAVYZEokGkXSNWyylvEaA16mHtMgPjo
-    Lm75d0O66RfJDdd/hTl8umGpF7kEGW1qYk2QmuPr7AqOa8na7olL5fMPh6Q7yRqx
-    GIS9JKQ0fWl8Ngk09WfwUN/kEMcp9Jl5iunNRkbpUJIM/lHFkSA7yOFFL+dVWzd4
-    2r+ddJXTFzW8Rwt65l8SV2MEhijEamKva3mqKLIRWxDsfFVT1T04LWFtnzMW4Z29
-    UHF9Pi7XSyKz0Y/Lz31mNTkjJYbOvbnwok8lc3wFWHc+lummZk8IkCq8xfqzwmwX
-    Ow6EV+Q6VaQpOHumQZ12pBBLtL8DyDhWaRUgVy2vYpwYsMYa5BFMcKCynjlSewo9
-    G2hNoW45cQZP1qHltRR9Xad7SaP7iTETDCiR7AWOqSpDipSh9eMfVW97ZbSfz+vl
-    xl8PZEZMTRIIRVXsPP+E8gtDUhUQp2+Vcz8r6q71qslXM09xl/501uaNjCc3hH2R
-    iw2N77Lho1F3FrBbHdML3RYHZI55eC9iQw6R4S+R4b+iWLJoHzHrW61itg==
-    -----END CERTIFICATE-----
-  '';
-}
diff --git a/nixpkgs/nixos/tests/common/resolver.nix b/nixpkgs/nixos/tests/common/resolver.nix
index 6be8d1d18e62..09a74de20faa 100644
--- a/nixpkgs/nixos/tests/common/resolver.nix
+++ b/nixpkgs/nixos/tests/common/resolver.nix
@@ -18,7 +18,7 @@
       defining this option needs to be explicitly imported.
 
       The reason this option exists is for the
-      <filename>nixos/tests/common/letsencrypt</filename> module, which
+      <filename>nixos/tests/common/acme/server</filename> module, which
       needs that option to disable the resolver once the user has set its own
       resolver.
     '';
diff --git a/nixpkgs/nixos/tests/containers-custom-pkgs.nix b/nixpkgs/nixos/tests/containers-custom-pkgs.nix
new file mode 100644
index 000000000000..397a4a905e6d
--- /dev/null
+++ b/nixpkgs/nixos/tests/containers-custom-pkgs.nix
@@ -0,0 +1,42 @@
+# Test for NixOS' container support.
+
+import ./make-test-python.nix ({ pkgs, lib, ...} : let
+
+  customPkgs = pkgs // {
+    hello = pkgs.hello.overrideAttrs(old: {
+      name = "custom-hello";
+    });
+  };
+
+in {
+  name = "containers-hosts";
+  meta = with lib.maintainers; {
+    maintainers = [ adisbladis ];
+  };
+
+  machine =
+    { ... }:
+    {
+      virtualisation.memorySize = 256;
+      virtualisation.vlans = [];
+
+      containers.simple = {
+        autoStart = true;
+        pkgs = customPkgs;
+        config = {pkgs, config, ... }: {
+          environment.systemPackages = [
+            pkgs.hello
+          ];
+        };
+      };
+
+    };
+
+  testScript = ''
+    start_all()
+    machine.wait_for_unit("default.target")
+    machine.succeed(
+        "test $(nixos-container run simple -- readlink -f /run/current-system/sw/bin/hello) = ${customPkgs.hello}/bin/hello"
+    )
+  '';
+})
diff --git a/nixpkgs/nixos/tests/deluge.nix b/nixpkgs/nixos/tests/deluge.nix
index 37689c3d9137..3cf179a38216 100644
--- a/nixpkgs/nixos/tests/deluge.nix
+++ b/nixpkgs/nixos/tests/deluge.nix
@@ -5,9 +5,10 @@ import ./make-test-python.nix ({ pkgs, ...} : {
   };
 
   nodes = {
-    simple = {
+    simple1 = {
       services.deluge = {
         enable = true;
+        package = pkgs.deluge-1_x;
         web = {
           enable = true;
           openFirewall = true;
@@ -15,50 +16,92 @@ import ./make-test-python.nix ({ pkgs, ...} : {
       };
     };
 
-    declarative =
-      { ... }:
+    declarative1 = {
+      services.deluge = {
+        enable = true;
+        package = pkgs.deluge-1_x;
+        openFirewall = true;
+        declarative = true;
+        config = {
+          allow_remote = true;
+          download_location = "/var/lib/deluge/my-download";
+          daemon_port = 58846;
+          listen_ports = [ 6881 6889 ];
+        };
+        web = {
+          enable = true;
+          port =  3142;
+        };
+        authFile = pkgs.writeText "deluge-auth" ''
+          localclient:a7bef72a890:10
+          andrew:password:10
+          user3:anotherpass:5
+        '';
+      };
+    };
 
-      {
-        services.deluge = {
+    simple2 = {
+      services.deluge = {
+        enable = true;
+        package = pkgs.deluge-2_x;
+        web = {
           enable = true;
           openFirewall = true;
-          declarative = true;
-          config = {
-            allow_remote = true;
-            download_location = "/var/lib/deluge/my-download";
-            daemon_port = 58846;
-            listen_ports = [ 6881 6889 ];
-          };
-          web = {
-            enable = true;
-            port =  3142;
-          };
-          authFile = pkgs.writeText "deluge-auth" ''
-            localclient:a7bef72a890:10
-            andrew:password:10
-            user3:anotherpass:5
-          '';
         };
-        environment.systemPackages = [ pkgs.deluge ];
       };
+    };
+
+    declarative2 = {
+      services.deluge = {
+        enable = true;
+        package = pkgs.deluge-2_x;
+        openFirewall = true;
+        declarative = true;
+        config = {
+          allow_remote = true;
+          download_location = "/var/lib/deluge/my-download";
+          daemon_port = 58846;
+          listen_ports = [ 6881 6889 ];
+        };
+        web = {
+          enable = true;
+          port =  3142;
+        };
+        authFile = pkgs.writeText "deluge-auth" ''
+          localclient:a7bef72a890:10
+          andrew:password:10
+          user3:anotherpass:5
+        '';
+      };
+    };
 
   };
 
   testScript = ''
     start_all()
 
-    simple.wait_for_unit("deluged")
-    simple.wait_for_unit("delugeweb")
-    simple.wait_for_open_port("8112")
-    declarative.wait_for_unit("network.target")
-    declarative.wait_until_succeeds("curl --fail http://simple:8112")
+    simple1.wait_for_unit("deluged")
+    simple2.wait_for_unit("deluged")
+    simple1.wait_for_unit("delugeweb")
+    simple2.wait_for_unit("delugeweb")
+    simple1.wait_for_open_port("8112")
+    simple2.wait_for_open_port("8112")
+    declarative1.wait_for_unit("network.target")
+    declarative2.wait_for_unit("network.target")
+    declarative1.wait_until_succeeds("curl --fail http://simple1:8112")
+    declarative2.wait_until_succeeds("curl --fail http://simple2:8112")
 
-    declarative.wait_for_unit("deluged")
-    declarative.wait_for_unit("delugeweb")
-    declarative.wait_until_succeeds("curl --fail http://declarative:3142")
-    declarative.succeed("deluge-console 'help' | grep -q 'rm - Remove a torrent'")
-    declarative.succeed(
-        "deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm - Remove a torrent'"
+    declarative1.wait_for_unit("deluged")
+    declarative2.wait_for_unit("deluged")
+    declarative1.wait_for_unit("delugeweb")
+    declarative2.wait_for_unit("delugeweb")
+    declarative1.wait_until_succeeds("curl --fail http://declarative1:3142")
+    declarative2.wait_until_succeeds("curl --fail http://declarative2:3142")
+    declarative1.succeed(
+        "deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm.*Remove a torrent'"
+    )
+    declarative2.succeed(
+        "deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm.*Remove a torrent'"
     )
   '';
 })
diff --git a/nixpkgs/nixos/tests/dokuwiki.nix b/nixpkgs/nixos/tests/dokuwiki.nix
index 38bde10f47ed..2b907133ed5a 100644
--- a/nixpkgs/nixos/tests/dokuwiki.nix
+++ b/nixpkgs/nixos/tests/dokuwiki.nix
@@ -1,29 +1,74 @@
-import ./make-test-python.nix ({ lib, ... }:
+import ./make-test-python.nix ({ pkgs, ... }:
 
-with lib;
+let
+  template-bootstrap3 = pkgs.stdenv.mkDerivation {
+    name = "bootstrap3";
+    # Download the theme from the dokuwiki site
+    src = pkgs.fetchurl {
+      url = https://github.com/giterlizzi/dokuwiki-template-bootstrap3/archive/v2019-05-22.zip;
+      sha256 = "4de5ff31d54dd61bbccaf092c9e74c1af3a4c53e07aa59f60457a8f00cfb23a6";
+    };
+    # We need unzip to build this package
+    buildInputs = [ pkgs.unzip ];
+    # Installing simply means copying all files to the output directory
+    installPhase = "mkdir -p $out; cp -R * $out/";
+  };
+
+
+  # Let's package the icalevents plugin
+  plugin-icalevents = pkgs.stdenv.mkDerivation {
+    name = "icalevents";
+    # Download the plugin from the dokuwiki site
+    src = pkgs.fetchurl {
+      url = https://github.com/real-or-random/dokuwiki-plugin-icalevents/releases/download/2017-06-16/dokuwiki-plugin-icalevents-2017-06-16.zip;
+      sha256 = "e40ed7dd6bbe7fe3363bbbecb4de481d5e42385b5a0f62f6a6ce6bf3a1f9dfa8";
+    };
+    # We need unzip to build this package
+    buildInputs = [ pkgs.unzip ];
+    sourceRoot = ".";
+    # Installing simply means copying all files to the output directory
+    installPhase = "mkdir -p $out; cp -R * $out/";
+  };
 
-{
+in {
   name = "dokuwiki";
-  meta.maintainers = with maintainers; [ maintainers."1000101" ];
-
-  nodes.machine =
-    { pkgs, ... }:
-    { services.dokuwiki = {
-        enable = true;
-        acl = " ";
-        superUser = null;
-        nginx = {
-          forceSSL = false;
-          enableACME = false;
-        };
-      }; 
+  meta.maintainers = with pkgs.lib.maintainers; [ "1000101" ];
+
+  machine = { ... }: {
+    services.dokuwiki."site1.local" = {
+      aclUse = false;
+      superUser = "admin";
+      nginx = {
+        forceSSL = false;
+        enableACME = false;
+      };
+    };
+    services.dokuwiki."site2.local" = {
+      aclUse = true;
+      superUser = "admin";
+      nginx = {
+        forceSSL = false;
+        enableACME = false;
+      };
+      templates = [ template-bootstrap3 ];
+      plugins = [ plugin-icalevents ];
     };
+    networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ];
+  };
 
   testScript = ''
-    machine.start()
-    machine.wait_for_unit("phpfpm-dokuwiki.service")
+    site_names = ["site1.local", "site2.local"]
+
+    start_all()
+
+    machine.wait_for_unit("phpfpm-dokuwiki-site1.local.service")
+    machine.wait_for_unit("phpfpm-dokuwiki-site2.local.service")
+
     machine.wait_for_unit("nginx.service")
+
     machine.wait_for_open_port(80)
-    machine.succeed("curl -sSfL http://localhost/ | grep 'DokuWiki'")
+
+    machine.succeed("curl -sSfL http://site1.local/ | grep 'DokuWiki'")
+    machine.succeed("curl -sSfL http://site2.local/ | grep 'DokuWiki'")
   '';
 })
diff --git a/nixpkgs/nixos/tests/dovecot.nix b/nixpkgs/nixos/tests/dovecot.nix
index c19850f418bc..bcbe234fd805 100644
--- a/nixpkgs/nixos/tests/dovecot.nix
+++ b/nixpkgs/nixos/tests/dovecot.nix
@@ -8,7 +8,7 @@ import ./make-test-python.nix {
     services.dovecot2.protocols = [ "imap" "pop3" ];
     environment.systemPackages = let
       sendTestMail = pkgs.writeScriptBin "send-testmail" ''
-        #!${pkgs.stdenv.shell}
+        #!${pkgs.runtimeShell}
         exec sendmail -vt <<MAIL
         From: root@localhost
         To: alice@localhost
@@ -19,7 +19,7 @@ import ./make-test-python.nix {
       '';
 
       sendTestMailViaDeliveryAgent = pkgs.writeScriptBin "send-lda" ''
-        #!${pkgs.stdenv.shell}
+        #!${pkgs.runtimeShell}
 
         exec ${pkgs.dovecot}/libexec/dovecot/deliver -d bob <<MAIL
         From: root@localhost
diff --git a/nixpkgs/nixos/tests/flannel.nix b/nixpkgs/nixos/tests/flannel.nix
index 9991c5eaa329..7615732c20ca 100644
--- a/nixpkgs/nixos/tests/flannel.nix
+++ b/nixpkgs/nixos/tests/flannel.nix
@@ -1,20 +1,24 @@
-import ./make-test.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ lib, ...} : {
   name = "flannel";
 
-  meta = with pkgs.stdenv.lib.maintainers; {
+  meta = with lib.maintainers; {
     maintainers = [ offline ];
   };
 
   nodes = let
-    flannelConfig = {
+    flannelConfig = { pkgs, ... } : {
       services.flannel = {
         enable = true;
+        backend = {
+          Type = "udp";
+          Port = 8285;
+        };
         network = "10.1.0.0/16";
         iface = "eth1";
         etcd.endpoints = ["http://etcd:2379"];
       };
 
-      networking.firewall.allowedUDPPorts = [ 8472 ];
+      networking.firewall.allowedUDPPorts = [ 8285 ];
     };
   in {
     etcd = { ... }: {
@@ -32,25 +36,22 @@ import ./make-test.nix ({ pkgs, ...} : {
       networking.firewall.allowedTCPPorts = [ 2379 ];
     };
 
-    node1 = { ... }: {
-      require = [flannelConfig];
-    };
-
-    node2 = { ... }: {
-      require = [flannelConfig];
-    };
+    node1 = flannelConfig;
+    node2 = flannelConfig;
   };
 
   testScript = ''
-    startAll;
+    start_all()
 
-    $node1->waitForUnit("flannel.service");
-    $node2->waitForUnit("flannel.service");
+    node1.wait_for_unit("flannel.service")
+    node2.wait_for_unit("flannel.service")
 
-    my $ip1 = $node1->succeed("ip -4 addr show flannel.1 | grep -oP '(?<=inet).*(?=/)'");
-    my $ip2 = $node2->succeed("ip -4 addr show flannel.1 | grep -oP '(?<=inet).*(?=/)'");
+    node1.wait_until_succeeds("ip l show dev flannel0")
+    ip1 = node1.succeed("ip -4 addr show flannel0 | grep -oP '(?<=inet).*(?=/)'")
+    node2.wait_until_succeeds("ip l show dev flannel0")
+    ip2 = node2.succeed("ip -4 addr show flannel0 | grep -oP '(?<=inet).*(?=/)'")
 
-    $node1->waitUntilSucceeds("ping -c 1 $ip2");
-    $node2->waitUntilSucceeds("ping -c 1 $ip1");
+    node1.wait_until_succeeds(f"ping -c 1 {ip2}")
+    node2.wait_until_succeeds(f"ping -c 1 {ip1}")
   '';
 })
diff --git a/nixpkgs/nixos/tests/gerrit.nix b/nixpkgs/nixos/tests/gerrit.nix
index e8b5cb4c4feb..6cee64a20095 100644
--- a/nixpkgs/nixos/tests/gerrit.nix
+++ b/nixpkgs/nixos/tests/gerrit.nix
@@ -24,7 +24,6 @@ in {
           enable = true;
           serverId = "aa76c84b-50b0-4711-a0a0-1ee30e45bbd0";
           listenAddress = "[::]:80";
-          jvmPackage = pkgs.jdk12_headless;
           jvmHeapLimit = "1g";
 
           plugins = [ lfs ];
diff --git a/nixpkgs/nixos/tests/gnome3-xorg.nix b/nixpkgs/nixos/tests/gnome3-xorg.nix
index f793bb922ad7..b59badcd5de4 100644
--- a/nixpkgs/nixos/tests/gnome3-xorg.nix
+++ b/nixpkgs/nixos/tests/gnome3-xorg.nix
@@ -1,7 +1,7 @@
-import ./make-test-python.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, lib, ...} : {
   name = "gnome3-xorg";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = pkgs.gnome3.maintainers;
+  meta = with lib; {
+    maintainers = teams.gnome.members;
   };
 
   machine = { nodes, ... }: let
diff --git a/nixpkgs/nixos/tests/gnome3.nix b/nixpkgs/nixos/tests/gnome3.nix
index 486c146d8dc3..17e72c5f6510 100644
--- a/nixpkgs/nixos/tests/gnome3.nix
+++ b/nixpkgs/nixos/tests/gnome3.nix
@@ -1,7 +1,7 @@
-import ./make-test-python.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, lib, ...} : {
   name = "gnome3";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = pkgs.gnome3.maintainers;
+  meta = with lib; {
+    maintainers = teams.gnome.members;
   };
 
   machine =
diff --git a/nixpkgs/nixos/tests/hardened.nix b/nixpkgs/nixos/tests/hardened.nix
index cbf76f9e5587..5ed0dfcf9ab8 100644
--- a/nixpkgs/nixos/tests/hardened.nix
+++ b/nixpkgs/nixos/tests/hardened.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ...} : {
+import ./make-test.nix ({ pkgs, latestKernel ? false, ... } : {
   name = "hardened";
   meta = with pkgs.stdenv.lib.maintainers; {
     maintainers = [ joachifm ];
@@ -10,6 +10,8 @@ import ./make-test.nix ({ pkgs, ...} : {
     { users.users.alice = { isNormalUser = true; extraGroups = [ "proc" ]; };
       users.users.sybil = { isNormalUser = true; group = "wheel"; };
       imports = [ ../modules/profiles/hardened.nix ];
+      boot.kernelPackages =
+        lib.mkIf latestKernel pkgs.linuxPackages_latest_hardened;
       environment.memoryAllocator.provider = "graphene-hardened";
       nix.useSandbox = false;
       virtualisation.emptyDiskImages = [ 4096 ];
@@ -23,7 +25,9 @@ import ./make-test.nix ({ pkgs, ...} : {
           options = [ "noauto" ];
         };
       };
-      boot.extraModulePackages = [ config.boot.kernelPackages.wireguard ];
+      boot.extraModulePackages =
+        optional (versionOlder config.boot.kernelPackages.kernel.version "5.6")
+          config.boot.kernelPackages.wireguard;
       boot.kernelModules = [ "wireguard" ];
     };
 
@@ -76,7 +80,8 @@ import ./make-test.nix ({ pkgs, ...} : {
 
       # Test userns
       subtest "userns", sub {
-          $machine->fail("unshare --user");
+          $machine->succeed("unshare --user true");
+          $machine->fail("su -l alice -c 'unshare --user true'");
       };
 
       # Test dmesg restriction
diff --git a/nixpkgs/nixos/tests/hydra/common.nix b/nixpkgs/nixos/tests/hydra/common.nix
new file mode 100644
index 000000000000..f612717dc968
--- /dev/null
+++ b/nixpkgs/nixos/tests/hydra/common.nix
@@ -0,0 +1,47 @@
+{ system, ... }:
+{
+  baseConfig = { pkgs, ... }: let
+    trivialJob = pkgs.writeTextDir "trivial.nix" ''
+     { trivial = builtins.derivation {
+         name = "trivial";
+         system = "${system}";
+         builder = "/bin/sh";
+         allowSubstitutes = false;
+         preferLocalBuild = true;
+         args = ["-c" "echo success > $out; exit 0"];
+       };
+     }
+    '';
+
+    createTrivialProject = pkgs.stdenv.mkDerivation {
+      name = "create-trivial-project";
+      dontUnpack = true;
+      buildInputs = [ pkgs.makeWrapper ];
+      installPhase = "install -m755 -D ${./create-trivial-project.sh} $out/bin/create-trivial-project.sh";
+      postFixup = ''
+        wrapProgram "$out/bin/create-trivial-project.sh" --prefix PATH ":" ${pkgs.stdenv.lib.makeBinPath [ pkgs.curl ]} --set EXPR_PATH ${trivialJob}
+      '';
+    };
+  in {
+    virtualisation.memorySize = 2048;
+    time.timeZone = "UTC";
+    environment.systemPackages = [ createTrivialProject pkgs.jq ];
+    services.hydra = {
+      enable = true;
+      # Hydra needs those settings to start up, so we add something not harmfull.
+      hydraURL = "example.com";
+      notificationSender = "example@example.com";
+      extraConfig = ''
+        email_notification = 1
+      '';
+    };
+    services.postfix.enable = true;
+    nix = {
+      buildMachines = [{
+        hostName = "localhost";
+        systems = [ system ];
+      }];
+      binaryCaches = [];
+    };
+  };
+}
diff --git a/nixpkgs/nixos/tests/hydra/db-migration.nix b/nixpkgs/nixos/tests/hydra/db-migration.nix
new file mode 100644
index 000000000000..cf74acfd67aa
--- /dev/null
+++ b/nixpkgs/nixos/tests/hydra/db-migration.nix
@@ -0,0 +1,92 @@
+{ system ? builtins.currentSystem
+, pkgs ? import ../../.. { inherit system; }
+, ...
+}:
+
+let inherit (import ./common.nix { inherit system; }) baseConfig; in
+
+with import ../../lib/testing-python.nix { inherit system pkgs; };
+with pkgs.lib;
+
+{ mig = makeTest {
+    name = "hydra-db-migration";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ ma27 ];
+    };
+
+    nodes = {
+      original = { pkgs, lib, ... }: {
+        imports = [ baseConfig ];
+
+        # An older version of Hydra before the db change
+        # for testing purposes.
+        services.hydra.package = pkgs.hydra-migration.overrideAttrs (old: {
+          inherit (old) pname;
+          version = "2020-02-06";
+          src = pkgs.fetchFromGitHub {
+            owner = "NixOS";
+            repo = "hydra";
+            rev = "2b4f14963b16b21ebfcd6b6bfa7832842e9b2afc";
+            sha256 = "16q0cffcsfx5pqd91n9k19850c1nbh4vvbd9h8yi64ihn7v8bick";
+          };
+        });
+      };
+
+      migration_phase1 = { pkgs, lib, ... }: {
+        imports = [ baseConfig ];
+        services.hydra.package = pkgs.hydra-migration;
+      };
+
+      finished = { pkgs, lib, ... }: {
+        imports = [ baseConfig ];
+        services.hydra.package = pkgs.hydra-unstable;
+      };
+    };
+
+    testScript = { nodes, ... }: let
+      next = nodes.migration_phase1.config.system.build.toplevel;
+      finished = nodes.finished.config.system.build.toplevel;
+    in ''
+      original.start()
+      original.wait_for_unit("multi-user.target")
+      original.wait_for_unit("postgresql.service")
+      original.wait_for_unit("hydra-init.service")
+      original.require_unit_state("hydra-queue-runner.service")
+      original.require_unit_state("hydra-evaluator.service")
+      original.require_unit_state("hydra-notify.service")
+      original.succeed("hydra-create-user admin --role admin --password admin")
+      original.wait_for_open_port(3000)
+      original.succeed("create-trivial-project.sh")
+      original.wait_until_succeeds(
+          'curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" |  jq .buildstatus | xargs test 0 -eq'
+      )
+
+      out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+      assert "jobset_id" not in out
+
+      original.succeed(
+          "${next}/bin/switch-to-configuration test >&2"
+      )
+      original.wait_for_unit("hydra-init.service")
+
+      out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+      assert "jobset_id|integer|||" in out
+
+      original.succeed("hydra-backfill-ids")
+
+      original.succeed(
+          "${finished}/bin/switch-to-configuration test >&2"
+      )
+      original.wait_for_unit("hydra-init.service")
+
+      out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+      assert "jobset_id|integer||not null|" in out
+
+      original.wait_until_succeeds(
+          'curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" |  jq .buildstatus | xargs test 0 -eq'
+      )
+
+      original.shutdown()
+    '';
+  };
+}
diff --git a/nixpkgs/nixos/tests/hydra/default.nix b/nixpkgs/nixos/tests/hydra/default.nix
index 1c0ed3369b1c..2336e4033d6d 100644
--- a/nixpkgs/nixos/tests/hydra/default.nix
+++ b/nixpkgs/nixos/tests/hydra/default.nix
@@ -3,102 +3,57 @@
 , pkgs ? import ../../.. { inherit system config; }
 }:
 
-let
-
-  trivialJob = pkgs.writeTextDir "trivial.nix" ''
-   { trivial = builtins.derivation {
-       name = "trivial";
-       system = "${system}";
-       builder = "/bin/sh";
-       allowSubstitutes = false;
-       preferLocalBuild = true;
-       args = ["-c" "echo success > $out; exit 0"];
-     };
-   }
-  '';
+with import ../../lib/testing-python.nix { inherit system pkgs; };
+with pkgs.lib;
 
-  createTrivialProject = pkgs.stdenv.mkDerivation {
-    name = "create-trivial-project";
-    dontUnpack = true;
-    buildInputs = [ pkgs.makeWrapper ];
-    installPhase = "install -m755 -D ${./create-trivial-project.sh} $out/bin/create-trivial-project.sh";
-    postFixup = ''
-      wrapProgram "$out/bin/create-trivial-project.sh" --prefix PATH ":" ${pkgs.stdenv.lib.makeBinPath [ pkgs.curl ]} --set EXPR_PATH ${trivialJob}
-    '';
-  };
+let
 
-  callTest = f: f { inherit system pkgs; };
+  inherit (import ./common.nix { inherit system; }) baseConfig;
 
   hydraPkgs = {
-    inherit (pkgs) nixStable nixUnstable nixFlakes;
+    inherit (pkgs) hydra-migration hydra-unstable;
   };
 
-  tests = pkgs.lib.flip pkgs.lib.mapAttrs hydraPkgs (name: nix:
-    callTest (import ../make-test-python.nix ({ pkgs, lib, ... }:
-      {
-        name = "hydra-with-${name}";
-        meta = with pkgs.stdenv.lib.maintainers; {
-          maintainers = [ pstn lewo ma27 ];
-        };
-
-        machine = { pkgs, ... }:
-          {
-            virtualisation.memorySize = 1024;
-            time.timeZone = "UTC";
-
-            environment.systemPackages = [ createTrivialProject pkgs.jq ];
-            services.hydra = {
-              enable = true;
-
-              #Hydra needs those settings to start up, so we add something not harmfull.
-              hydraURL = "example.com";
-              notificationSender = "example@example.com";
-
-              package = pkgs.hydra.override { inherit nix; };
-
-              extraConfig = ''
-                email_notification = 1
-              '';
-            };
-            services.postfix.enable = true;
-            nix = {
-              buildMachines = [{
-                hostName = "localhost";
-                systems = [ system ];
-              }];
-
-              binaryCaches = [];
-            };
-          };
-
-        testScript = ''
-          # let the system boot up
-          machine.wait_for_unit("multi-user.target")
-          # test whether the database is running
-          machine.wait_for_unit("postgresql.service")
-          # test whether the actual hydra daemons are running
-          machine.wait_for_unit("hydra-init.service")
-          machine.require_unit_state("hydra-queue-runner.service")
-          machine.require_unit_state("hydra-evaluator.service")
-          machine.require_unit_state("hydra-notify.service")
-
-          machine.succeed("hydra-create-user admin --role admin --password admin")
-
-          # create a project with a trivial job
-          machine.wait_for_open_port(3000)
-
-          # make sure the build as been successfully built
-          machine.succeed("create-trivial-project.sh")
-
-          machine.wait_until_succeeds(
-              'curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" |  jq .buildstatus | xargs test 0 -eq'
-          )
-
-          machine.wait_until_succeeds(
-              'journalctl -eu hydra-notify.service -o cat | grep -q "sending mail notification to hydra@localhost"'
-          )
-        '';
-      })));
+  makeHydraTest = with pkgs.lib; name: package: makeTest {
+    name = "hydra-${name}";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ pstn lewo ma27 ];
+    };
+
+    machine = { pkgs, lib, ... }: {
+      imports = [ baseConfig ];
+      services.hydra = { inherit package; };
+    };
+
+    testScript = ''
+      # let the system boot up
+      machine.wait_for_unit("multi-user.target")
+      # test whether the database is running
+      machine.wait_for_unit("postgresql.service")
+      # test whether the actual hydra daemons are running
+      machine.wait_for_unit("hydra-init.service")
+      machine.require_unit_state("hydra-queue-runner.service")
+      machine.require_unit_state("hydra-evaluator.service")
+      machine.require_unit_state("hydra-notify.service")
+
+      machine.succeed("hydra-create-user admin --role admin --password admin")
+
+      # create a project with a trivial job
+      machine.wait_for_open_port(3000)
+
+      # make sure the build as been successfully built
+      machine.succeed("create-trivial-project.sh")
+
+      machine.wait_until_succeeds(
+          'curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" |  jq .buildstatus | xargs test 0 -eq'
+      )
+
+      machine.wait_until_succeeds(
+          'journalctl -eu hydra-notify.service -o cat | grep -q "sending mail notification to hydra@localhost"'
+      )
+    '';
+  };
 
 in
-  tests
+
+mapAttrs makeHydraTest hydraPkgs
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/default.nix b/nixpkgs/nixos/tests/initrd-network-ssh/default.nix
index 73d9f938e226..017de6882081 100644
--- a/nixpkgs/nixos/tests/initrd-network-ssh/default.nix
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/default.nix
@@ -3,7 +3,7 @@ import ../make-test-python.nix ({ lib, ... }:
 {
   name = "initrd-network-ssh";
   meta = with lib.maintainers; {
-    maintainers = [ willibutz ];
+    maintainers = [ willibutz emily ];
   };
 
   nodes = with lib; {
@@ -17,9 +17,9 @@ import ../make-test-python.nix ({ lib, ... }:
           enable = true;
           ssh = {
             enable = true;
-            authorizedKeys = [ "${readFile ./openssh.pub}" ];
+            authorizedKeys = [ (readFile ./id_ed25519.pub) ];
             port = 22;
-            hostRSAKey = ./dropbear.priv;
+            hostKeys = [ ./ssh_host_ed25519_key ];
           };
         };
         boot.initrd.preLVMCommands = ''
@@ -42,11 +42,11 @@ import ../make-test-python.nix ({ lib, ... }:
               "${toString (head (splitString " " (
                 toString (elemAt (splitString "\n" config.networking.extraHosts) 2)
               )))} "
-              "${readFile ./dropbear.pub}"
+              "${readFile ./ssh_host_ed25519_key.pub}"
             ];
           };
           sshKey = {
-            source = ./openssh.priv; # dont use this anywhere else
+            source = ./id_ed25519;
             mode = "0600";
           };
         };
@@ -56,7 +56,17 @@ import ../make-test-python.nix ({ lib, ... }:
   testScript = ''
     start_all()
     client.wait_for_unit("network.target")
-    client.wait_until_succeeds("ping -c 1 server")
+
+
+    def ssh_is_up(_) -> bool:
+        status, _ = client.execute("nc -z server 22")
+        return status == 0
+
+
+    with client.nested("waiting for SSH server to come up"):
+        retry(ssh_is_up)
+
+
     client.succeed(
         "ssh -i /etc/sshKey -o UserKnownHostsFile=/etc/knownHosts server 'touch /fnord'"
     )
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.priv b/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.priv
deleted file mode 100644
index af340535f0a3..000000000000
--- a/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.priv
+++ /dev/null
Binary files differdiff --git a/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.pub b/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.pub
deleted file mode 100644
index 385c625522aa..000000000000
--- a/nixpkgs/nixos/tests/initrd-network-ssh/dropbear.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzJ0OniLB91MpPC86I1m3wwJeAc+Gme7bAuaLIU/cSfPwxT5NO7MfCp0Pu94gYDKtDXMs/wXg0bTAVDeAFFkdIj6kBBumEmQLCTL48q2UxDIXVLT/E/AAgj6q7WwgCg7fwm4Vjn4z7aUyBx8EfRy+5/SQyeYla3D/lFYgMi5x4D6J+yeR+JPAptDE/IR5IizNV7mY0ZcoXYyHrrehI1tTYEEqjX13ZqS4OCBFWwHe1QHhRNM+jHhcATbgikjAj8FyFPtLvc+dSVtkuhQktQl36Bi8zMUQcV6+mM7Ln6DBcDlM9urHKLYPTWmUAyhxM955iglOn5z0RaAIcyNMT6hz0rHaNf0BIlmbXoTC0XGjHh/OnoOEC/zg0JqgQTnPiU45K4TnRSSXp2GfiDfiQAK0+HaXACkjuFR68u7WCZpB1Bse1OgKNClFqtRhIr5DilUb2/e5DCCmFkddMUcjmYqzZdbXNt7fo8CFULe+mbiCp8+tMg4aRTaDZ/Hk93nCvGE5TP2ypEMbfL6nRVKvXOjhdvSQQgKwx+O003FDEHCSG0Bpageh7yVpna+SPrbGklce7MjTpbx3iIwmvKpQ6asnK1L3KkahpY1S3NhQ+/S3Gs8KWQ5LAU+d3xiPX3jfIVHsCIIyxHDbwcJvxM4MFBFQpqRMD6E+LoM9RHjl4C9k2iQ== tmtynkky@duuni
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/generate-keys.nix b/nixpkgs/nixos/tests/initrd-network-ssh/generate-keys.nix
index 0183e12d7a88..3d7978890ab0 100644
--- a/nixpkgs/nixos/tests/initrd-network-ssh/generate-keys.nix
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/generate-keys.nix
@@ -1,12 +1,10 @@
 with import ../../.. {};
 
 runCommand "gen-keys" {
-    buildInputs = [ dropbear openssh ];
+    buildInputs = [ openssh ];
   }
   ''
     mkdir $out
-    dropbearkey -t rsa -f $out/dropbear.priv -s 4096 | sed -n 2p > $out/dropbear.pub
-    ssh-keygen -q -t rsa -b 4096 -N "" -f client
-    mv client $out/openssh.priv
-    mv client.pub $out/openssh.pub
+    ssh-keygen -q -t ed25519 -N "" -f $out/ssh_host_ed25519_key
+    ssh-keygen -q -t ed25519 -N "" -f $out/id_ed25519
   ''
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519 b/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519
new file mode 100644
index 000000000000..f914b3f712fc
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACAVcX+32Yqig25RxRA8bel/f604wV0p/63um+Oku/3vfwAAAJi/AJZMvwCW
+TAAAAAtzc2gtZWQyNTUxOQAAACAVcX+32Yqig25RxRA8bel/f604wV0p/63um+Oku/3vfw
+AAAEAPLjQusjrB90Lk3996G3AbtTeK+XweNgxaegYnml/A/RVxf7fZiqKDblHFEDxt6X9/
+rTjBXSn/re6b46S7/e9/AAAAEG5peGJsZEBsb2NhbGhvc3QBAgMEBQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519.pub b/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519.pub
new file mode 100644
index 000000000000..40de4a8ac602
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/id_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVxf7fZiqKDblHFEDxt6X9/rTjBXSn/re6b46S7/e9/ nixbld@localhost
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/openssh.priv b/nixpkgs/nixos/tests/initrd-network-ssh/openssh.priv
deleted file mode 100644
index 816d65435fd7..000000000000
--- a/nixpkgs/nixos/tests/initrd-network-ssh/openssh.priv
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/openssh.pub b/nixpkgs/nixos/tests/initrd-network-ssh/openssh.pub
deleted file mode 100644
index 5b72b8085f27..000000000000
--- a/nixpkgs/nixos/tests/initrd-network-ssh/openssh.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDv70DY8I85MCUWatpuWtRYD5Vl0C4t8zold4ew4XtlsLYXqW9aa8Mz3bkNCqGICNyBae3lYdZLlj5vuUae7NPt/Ip6Bd3zScJGaqWlIbeytfT+XFFpAAkvN+gONywX5x6zBCjoZKxicIdXEw2zTTuBttVjd/uj6xZm0t3Ek8PaIe+XlmssrR3VEsyZTpx8iEgAGUvRLwRaK/b1FE56mwJCdLR2crZv6+ifVIJiiCC8Ax7ZOgAgAnz66pph8YDKf2rx+NmJEfEuYoOr3S0qgJQvmv/Z2YQgT63xP/c98eirVDNm2z1b2J2EF1PbV0RcG0bKgy1ySnmeOTmbzYtANiI5eS5KghSFI616HmDt8G/UG1VIRHEmDdR4mM94YoXB2fNqmYAoLbD/pXzFwgg00D5+FkDsH18PVECLZMQJn6DIxgNzhP5RKUxKb1x+9I6t/b7meC0VvziceOq8KXEIwu75sJYrwdqapTOET9rkttH7jwTs/IazcpX6xYU30o6dqROOP/qJCFdlGGB4Arf0XZdOTkyzlj4FFJK2cygxkDaCshX6MeLXNtaiRWpc8jlhGjmKxH8+C0oBXoV81a6ZxigUn0XjSkwdDqElUSa2sIHHsQClKXeZIZtAlSaKUsLnWo2HBBFsP/9m2kis3zYdMwrNnqSPuQMJ2x9/7CyeQheaYw== tmtynkky@duuni
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key b/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key
new file mode 100644
index 000000000000..f1e29459b7a3
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDP9Mz6qlxdQqA4omrgbOlVsxSGONCJstjW9zqquajlIAAAAJg0WGFGNFhh
+RgAAAAtzc2gtZWQyNTUxOQAAACDP9Mz6qlxdQqA4omrgbOlVsxSGONCJstjW9zqquajlIA
+AAAEA0Hjs7LfFPdTf3ThGx6GNKvX0ItgzgXs91Z3oGIaF6S8/0zPqqXF1CoDiiauBs6VWz
+FIY40Imy2Nb3Oqq5qOUgAAAAEG5peGJsZEBsb2NhbGhvc3QBAgMEBQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key.pub b/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key.pub
new file mode 100644
index 000000000000..3aa1587e1dce
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-ssh/ssh_host_ed25519_key.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM/0zPqqXF1CoDiiauBs6VWzFIY40Imy2Nb3Oqq5qOUg nixbld@localhost
diff --git a/nixpkgs/nixos/tests/installed-tests/default.nix b/nixpkgs/nixos/tests/installed-tests/default.nix
index a189ef63f222..b6bdfea22770 100644
--- a/nixpkgs/nixos/tests/installed-tests/default.nix
+++ b/nixpkgs/nixos/tests/installed-tests/default.nix
@@ -91,6 +91,7 @@ in
   ibus = callInstalledTest ./ibus.nix {};
   libgdata = callInstalledTest ./libgdata.nix {};
   glib-testing = callInstalledTest ./glib-testing.nix {};
+  libjcat = callInstalledTest ./libjcat.nix {};
   libxmlb = callInstalledTest ./libxmlb.nix {};
   malcontent = callInstalledTest ./malcontent.nix {};
   ostree = callInstalledTest ./ostree.nix {};
diff --git a/nixpkgs/nixos/tests/installed-tests/libjcat.nix b/nixpkgs/nixos/tests/installed-tests/libjcat.nix
new file mode 100644
index 000000000000..41493a730890
--- /dev/null
+++ b/nixpkgs/nixos/tests/installed-tests/libjcat.nix
@@ -0,0 +1,5 @@
+{ pkgs, makeInstalledTest, ... }:
+
+makeInstalledTest {
+  tested = pkgs.libjcat;
+}
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index babde4126c4c..c5abd458ec9a 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -65,7 +65,7 @@ let
   # partitions and filesystems.
   testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi
                   , grubIdentifier, preBootCommands, extraConfig
-                  , testCloneConfig
+                  , testSpecialisationConfig
                   }:
     let iface = if grubVersion == 1 then "ide" else "virtio";
         isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
@@ -220,7 +220,7 @@ let
 
       # Tests for validating clone configuration entries in grub menu
     ''
-    + optionalString testCloneConfig ''
+    + optionalString testSpecialisationConfig ''
       # Reboot Machine
       machine = create_machine_named("clone-default-config")
       ${preBootCommands}
@@ -262,7 +262,7 @@ let
     , bootLoader ? "grub" # either "grub" or "systemd-boot"
     , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false
     , enableOCR ? false, meta ? {}
-    , testCloneConfig ? false
+    , testSpecialisationConfig ? false
     }:
     makeTest {
       inherit enableOCR;
@@ -337,7 +337,7 @@ let
       testScript = testScriptFun {
         inherit bootLoader createPartitions preBootCommands
                 grubVersion grubDevice grubIdentifier grubUseEfi extraConfig
-                testCloneConfig;
+                testSpecialisationConfig;
       };
     };
 
@@ -411,11 +411,11 @@ let
     grubUseEfi = true;
   };
 
-  clone-test-extraconfig = {
+  specialisation-test-extraconfig = {
     extraConfig = ''
       environment.systemPackages = [ pkgs.grub2 ];
       boot.loader.grub.configurationName = "Home";
-      nesting.clone = [ {
+      specialisation.work.configuration = {
         boot.loader.grub.configurationName = lib.mkForce "Work";
 
         environment.etc = {
@@ -424,9 +424,9 @@ let
               gitproxy = none for work.com
               ";
         };
-      } ];
+      };
     '';
-    testCloneConfig = true;
+    testSpecialisationConfig = true;
   };
 
 
@@ -440,7 +440,7 @@ in {
   simple = makeInstallerTest "simple" simple-test-config;
 
   # Test cloned configurations with the simple grub configuration
-  simpleClone = makeInstallerTest "simpleClone" (simple-test-config // clone-test-extraconfig);
+  simpleSpecialised = makeInstallerTest "simpleSpecialised" (simple-test-config // specialisation-test-extraconfig);
 
   # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem
   simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" {
@@ -467,7 +467,7 @@ in {
   simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config;
 
   # Test cloned configurations with the uefi grub configuration
-  simpleUefiGrubClone = makeInstallerTest "simpleUefiGrubClone" (simple-uefi-grub-config // clone-test-extraconfig);
+  simpleUefiGrubSpecialisation = makeInstallerTest "simpleUefiGrubSpecialisation" (simple-uefi-grub-config // specialisation-test-extraconfig);
 
   # Same as the previous, but now with a separate /boot partition.
   separateBoot = makeInstallerTest "separateBoot" {
diff --git a/nixpkgs/nixos/tests/iodine.nix b/nixpkgs/nixos/tests/iodine.nix
index 8bd9603a6d6c..41fb2e7778d4 100644
--- a/nixpkgs/nixos/tests/iodine.nix
+++ b/nixpkgs/nixos/tests/iodine.nix
@@ -1,6 +1,7 @@
 import ./make-test-python.nix (
   { pkgs, ... }: let
     domain = "whatever.example.com";
+    password = "false;foo;exit;withspecialcharacters";
   in
     {
       name = "iodine";
@@ -21,7 +22,7 @@ import ./make-test-python.nix (
               services.iodine.server = {
                 enable = true;
                 ip = "10.53.53.1/24";
-                passwordFile = "${builtins.toFile "password" "foo"}";
+                passwordFile = "${builtins.toFile "password" password}";
                 inherit domain;
               };
 
@@ -41,7 +42,7 @@ import ./make-test-python.nix (
               server = domain;
             };
             systemd.tmpfiles.rules = [
-              "f /root/pw 0666 root root - foo"
+              "f /root/pw 0666 root root - ${password}"
             ];
             environment.systemPackages = [
               pkgs.nagiosPluginsOfficial
diff --git a/nixpkgs/nixos/tests/k3s.nix b/nixpkgs/nixos/tests/k3s.nix
new file mode 100644
index 000000000000..5bda6f493f0e
--- /dev/null
+++ b/nixpkgs/nixos/tests/k3s.nix
@@ -0,0 +1,78 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+let
+  # A suitable k3s pause image, also used for the test pod
+  pauseImage = pkgs.dockerTools.buildImage {
+    name = "test.local/pause";
+    tag = "local";
+    contents = with pkgs; [ tini coreutils busybox ];
+    config.Entrypoint = [ "/bin/tini" "--" "/bin/sleep" "inf" ];
+  };
+  testPodYaml = pkgs.writeText "test.yml" ''
+    # Don't use the default service account because there's a race where it may
+    # not be created yet; make our own instead.
+    apiVersion: v1
+    kind: ServiceAccount
+    metadata:
+      name: test
+    ---
+    apiVersion: v1
+    kind: Pod
+    metadata:
+      name: test
+    spec:
+      serviceAccountName: test
+      containers:
+      - name: test
+        image: test.local/pause:local
+        imagePullPolicy: Never
+        command: ["sh", "-c", "sleep inf"]
+  '';
+in
+{
+  name = "k3s";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ euank ];
+  };
+
+  nodes = {
+    k3s =
+      { pkgs, ... }: {
+        environment.systemPackages = [ pkgs.k3s pkgs.gzip ];
+
+        # k3s uses enough resources the default vm fails.
+        virtualisation.memorySize = pkgs.lib.mkDefault 1536;
+        virtualisation.diskSize = pkgs.lib.mkDefault 4096;
+
+        services.k3s.enable = true;
+        services.k3s.role = "server";
+        services.k3s.package = pkgs.k3s;
+        # Slightly reduce resource usage
+        services.k3s.extraFlags = "--no-deploy coredns,servicelb,traefik,local-storage,metrics-server --pause-image test.local/pause:local";
+
+        users.users = {
+          noprivs = {
+            isNormalUser = true;
+            description = "Can't access k3s by default";
+            password = "*";
+          };
+        };
+      };
+  };
+
+  testScript = ''
+    start_all()
+
+    k3s.wait_for_unit("k3s")
+    k3s.succeed("k3s kubectl cluster-info")
+    k3s.fail("sudo -u noprivs k3s kubectl cluster-info")
+    # k3s.succeed("k3s check-config") # fails with the current nixos kernel config, uncomment once this passes
+
+    k3s.succeed(
+        "zcat ${pauseImage} | k3s ctr image import -"
+    )
+
+    k3s.succeed("k3s kubectl apply -f ${testPodYaml}")
+    k3s.succeed("k3s kubectl wait --for 'condition=Ready' pod/test")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/kafka.nix b/nixpkgs/nixos/tests/kafka.nix
index f3de24e873bb..d29c802b47b4 100644
--- a/nixpkgs/nixos/tests/kafka.nix
+++ b/nixpkgs/nixos/tests/kafka.nix
@@ -77,7 +77,7 @@ let
           + "--from-beginning --max-messages 1"
       )
     '');
-  }) {});
+  }) { inherit system; });
 
 in with pkgs; {
   kafka_0_9  = makeKafkaTest "kafka_0_9"  apacheKafka_0_9;
diff --git a/nixpkgs/nixos/tests/magic-wormhole-mailbox-server.nix b/nixpkgs/nixos/tests/magic-wormhole-mailbox-server.nix
new file mode 100644
index 000000000000..144a07e13492
--- /dev/null
+++ b/nixpkgs/nixos/tests/magic-wormhole-mailbox-server.nix
@@ -0,0 +1,38 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "magic-wormhole-mailbox-server";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ mmahut ];
+  };
+
+  nodes = {
+    server = { ... }: {
+      networking.firewall.allowedTCPPorts = [ 4000 ];
+      services.magic-wormhole-mailbox-server.enable = true;
+    };
+
+    client_alice = { ... }: {
+      networking.firewall.enable = false;
+      environment.systemPackages = [ pkgs.magic-wormhole ];
+    };
+
+    client_bob = { ... }: {
+      environment.systemPackages = [ pkgs.magic-wormhole ];
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    # Start the wormhole relay server
+    server.wait_for_unit("magic-wormhole-mailbox-server.service")
+    server.wait_for_open_port(4000)
+
+    # Create a secret file and send it to Bob
+    client_alice.succeed("echo mysecret > secretfile")
+    client_alice.succeed("wormhole --relay-url=ws://server:4000/v1 send -0 secretfile &")
+
+    # Retrieve a secret file from Alice and check its content
+    client_bob.succeed("wormhole --relay-url=ws://server:4000/v1 receive -0 --accept-file")
+    client_bob.succeed("grep mysecret secretfile")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/mongodb.nix b/nixpkgs/nixos/tests/mongodb.nix
index ee7fc50f7ecc..a637ec4bfc00 100644
--- a/nixpkgs/nixos/tests/mongodb.nix
+++ b/nixpkgs/nixos/tests/mongodb.nix
@@ -33,7 +33,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
     nodes = {
       node = {...}: {
         environment.systemPackages = with pkgs; [
-#          mongodb-3_4
+          mongodb-3_4
           mongodb-3_6
           mongodb-4_0
         ];
@@ -43,7 +43,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
     testScript = ''
       node.start()
     ''
-#      + runMongoDBTest pkgs.mongodb-3_4
+      + runMongoDBTest pkgs.mongodb-3_4
       + runMongoDBTest pkgs.mongodb-3_6 
       + runMongoDBTest pkgs.mongodb-4_0
       + ''
diff --git a/nixpkgs/nixos/tests/mpd.nix b/nixpkgs/nixos/tests/mpd.nix
index 895b7e2014c8..60aef586ad5c 100644
--- a/nixpkgs/nixos/tests/mpd.nix
+++ b/nixpkgs/nixos/tests/mpd.nix
@@ -5,7 +5,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
       # License: http://creativecommons.org/licenses/by-sa/4.0/
 
       name = "Blue_Wave_Theory-Skyhawk_Beach.mp3";
-      url = https://freemusicarchive.org/file/music/ccCommunity/Blue_Wave_Theory/Surf_Music_Month_Challenge/Blue_Wave_Theory_-_04_-_Skyhawk_Beach.mp3;
+      url = "https://freemusicarchive.org/file/music/ccCommunity/Blue_Wave_Theory/Surf_Music_Month_Challenge/Blue_Wave_Theory_-_04_-_Skyhawk_Beach.mp3";
       sha256 = "0xw417bxkx4gqqy139bb21yldi37xx8xjfxrwaqa0gyw19dl6mgp";
     };
 
diff --git a/nixpkgs/nixos/tests/mysql.nix b/nixpkgs/nixos/tests/mysql.nix
index 84673181e1a4..11c1dabf9360 100644
--- a/nixpkgs/nixos/tests/mysql.nix
+++ b/nixpkgs/nixos/tests/mysql.nix
@@ -68,6 +68,11 @@ import ./make-test-python.nix ({ pkgs, ...} : {
             "testdb2.*" = "ALL PRIVILEGES";
           };
         }];
+        services.mysql.settings = {
+          mysqld = {
+            plugin-load-add = [ "ha_tokudb.so" "ha_rocksdb.so" ];
+          };
+        };
         services.mysql.package = pkgs.mariadb;
       };
 
@@ -106,5 +111,33 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     mariadb.succeed(
         "echo 'use testdb; select test_id from tests;' | sudo -u testuser mysql -u testuser -N | grep 42"
     )
+
+    # Check if TokuDB plugin works
+    mariadb.succeed(
+        "echo 'use testdb; create table tokudb (test_id INT, PRIMARY KEY (test_id)) ENGINE = TokuDB;' | sudo -u testuser mysql -u testuser"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; insert into tokudb values (25);' | sudo -u testuser mysql -u testuser"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; select test_id from tokudb;' | sudo -u testuser mysql -u testuser -N | grep 25"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; drop table tokudb;' | sudo -u testuser mysql -u testuser"
+    )
+
+    # Check if RocksDB plugin works
+    mariadb.succeed(
+        "echo 'use testdb; create table rocksdb (test_id INT, PRIMARY KEY (test_id)) ENGINE = RocksDB;' | sudo -u testuser mysql -u testuser"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; insert into rocksdb values (28);' | sudo -u testuser mysql -u testuser"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; select test_id from rocksdb;' | sudo -u testuser mysql -u testuser -N | grep 28"
+    )
+    mariadb.succeed(
+        "echo 'use testdb; drop table rocksdb;' | sudo -u testuser mysql -u testuser"
+    )
   '';
 })
diff --git a/nixpkgs/nixos/tests/nesting.nix b/nixpkgs/nixos/tests/nesting.nix
deleted file mode 100644
index a75806b24ff6..000000000000
--- a/nixpkgs/nixos/tests/nesting.nix
+++ /dev/null
@@ -1,44 +0,0 @@
-import ./make-test-python.nix {
-  name = "nesting";
-  nodes =  {
-    clone = { pkgs, ... }: {
-      environment.systemPackages = [ pkgs.cowsay ];
-      nesting.clone = [
-        ({ pkgs, ... }: {
-          environment.systemPackages = [ pkgs.hello ];
-        })
-      ];
-    };
-    children = { pkgs, ... }: {
-      environment.systemPackages = [ pkgs.cowsay ];
-      nesting.children = [
-        ({ pkgs, ... }: {
-          environment.systemPackages = [ pkgs.hello ];
-        })
-      ];
-    };
-  };
-  testScript = ''
-    clone.wait_for_unit("default.target")
-    clone.succeed("cowsay hey")
-    clone.fail("hello")
-
-    with subtest("Nested clones do inherit from parent"):
-        clone.succeed(
-            "/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
-        )
-        clone.succeed("cowsay hey")
-        clone.succeed("hello")
-
-    children.wait_for_unit("default.target")
-    children.succeed("cowsay hey")
-    children.fail("hello")
-
-    with subtest("Nested children do not inherit from parent"):
-        children.succeed(
-            "/run/current-system/fine-tune/child-1/bin/switch-to-configuration test"
-        )
-        children.fail("cowsay hey")
-        children.succeed("hello")
-  '';
-}
diff --git a/nixpkgs/nixos/tests/networking.nix b/nixpkgs/nixos/tests/networking.nix
index 0a6507d2dc88..3d8ab761a446 100644
--- a/nixpkgs/nixos/tests/networking.nix
+++ b/nixpkgs/nixos/tests/networking.nix
@@ -200,6 +200,7 @@ let
           useDHCP = false;
           interfaces.eth1 = {
             ipv4.addresses = mkOverride 0 [ ];
+            mtu = 1343;
             useDHCP = true;
           };
           interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
@@ -216,6 +217,9 @@ let
           with subtest("Wait until we have an ip address on each interface"):
               client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'")
 
+          with subtest("ensure MTU is set"):
+              assert "mtu 1343" in client.succeed("ip link show dev eth1")
+
           with subtest("Test vlan 1"):
               client.wait_until_succeeds("ping -c 1 192.168.1.1")
               client.wait_until_succeeds("ping -c 1 192.168.1.2")
@@ -455,11 +459,14 @@ let
           ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
           ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
           virtual = true;
+          mtu = 1342;
+          macAddress = "02:de:ad:be:ef:01";
         };
         networking.interfaces.tun0 = {
           ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
           ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
           virtual = true;
+          mtu = 1343;
         };
       };
 
@@ -471,7 +478,7 @@ let
 
         with subtest("Wait for networking to come up"):
             machine.start()
-            machine.wait_for_unit("network-online.target")
+            machine.wait_for_unit("network.target")
 
         with subtest("Test interfaces set up"):
             list = machine.succeed("ip tuntap list | sort").strip()
@@ -486,7 +493,12 @@ let
             """.format(
                 list, targetList
             )
-
+        with subtest("Test MTU and MAC Address are configured"):
+            assert "mtu 1342" in machine.succeed("ip link show dev tap0")
+            assert "mtu 1343" in machine.succeed("ip link show dev tun0")
+            assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0")
+      '' # network-addresses-* only exist in scripted networking
+      + optionalString (!networkd) ''
         with subtest("Test interfaces clean up"):
             machine.succeed("systemctl stop network-addresses-tap0")
             machine.sleep(10)
@@ -602,17 +614,17 @@ let
       };
 
       testScript = ''
-        targetIPv4Table = """
-        10.0.0.0/16 proto static scope link mtu 1500 
-        192.168.1.0/24 proto kernel scope link src 192.168.1.2 
-        192.168.2.0/24 via 192.168.1.1 proto static 
-        """.strip()
-
-        targetIPv6Table = """
-        2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium
-        2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium
-        fdfd:b3f0::/48 proto static metric 1024 pref medium
-        """.strip()
+        targetIPv4Table = [
+            "10.0.0.0/16 proto static scope link mtu 1500",
+            "192.168.1.0/24 proto kernel scope link src 192.168.1.2",
+            "192.168.2.0/24 via 192.168.1.1 proto static",
+        ]
+
+        targetIPv6Table = [
+            "2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium",
+            "2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium",
+            "fdfd:b3f0::/48 proto static metric 1024 pref medium",
+        ]
 
         machine.start()
         machine.wait_for_unit("network.target")
@@ -620,9 +632,9 @@ let
         with subtest("test routing tables"):
             ipv4Table = machine.succeed("ip -4 route list dev eth0 | head -n3").strip()
             ipv6Table = machine.succeed("ip -6 route list dev eth0 | head -n3").strip()
-            assert (
-                ipv4Table == targetIPv4Table
-            ), """
+            assert [
+                l.strip() for l in ipv4Table.splitlines()
+            ] == targetIPv4Table, """
               The IPv4 routing table does not match the expected one:
                 Result:
                   {}
@@ -631,9 +643,9 @@ let
               """.format(
                 ipv4Table, targetIPv4Table
             )
-            assert (
-                ipv6Table == targetIPv6Table
-            ), """
+            assert [
+                l.strip() for l in ipv6Table.splitlines()
+            ] == targetIPv6Table, """
               The IPv6 routing table does not match the expected one:
                 Result:
                   {}
diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix
index 75862feb202d..92ac5c46e8f0 100644
--- a/nixpkgs/nixos/tests/nextcloud/basic.nix
+++ b/nixpkgs/nixos/tests/nextcloud/basic.nix
@@ -32,7 +32,7 @@ in {
 
   testScript = let
     withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
       export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
       export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
@@ -41,12 +41,12 @@ in {
       "''${@}"
     '';
     copySharedFile = pkgs.writeScript "copy-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       echo 'hi' | ${withRcloneEnv} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
     '';
 
     diffSharedFile = pkgs.writeScript "diff-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
     '';
   in ''
diff --git a/nixpkgs/nixos/tests/nextcloud/with-mysql-and-memcached.nix b/nixpkgs/nixos/tests/nextcloud/with-mysql-and-memcached.nix
index b9ba5888187d..8db630be893a 100644
--- a/nixpkgs/nixos/tests/nextcloud/with-mysql-and-memcached.nix
+++ b/nixpkgs/nixos/tests/nextcloud/with-mysql-and-memcached.nix
@@ -61,14 +61,14 @@ in {
 
   testScript = let
     configureMemcached = pkgs.writeScript "configure-memcached" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       nextcloud-occ config:system:set memcached_servers 0 0 --value 127.0.0.1 --type string
       nextcloud-occ config:system:set memcached_servers 0 1 --value 11211 --type integer
       nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\APCu' --type string
       nextcloud-occ config:system:set memcache.distributed --value '\OC\Memcache\Memcached' --type string
     '';
     withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
       export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
       export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
@@ -76,12 +76,12 @@ in {
       export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})"
     '';
     copySharedFile = pkgs.writeScript "copy-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
     '';
 
     diffSharedFile = pkgs.writeScript "diff-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
     '';
   in ''
diff --git a/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix b/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
index 324853350af6..95219cac9be8 100644
--- a/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
+++ b/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
@@ -60,14 +60,14 @@ in {
 
   testScript = let
     configureRedis = pkgs.writeScript "configure-redis" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       nextcloud-occ config:system:set redis 'host' --value 'localhost' --type string
       nextcloud-occ config:system:set redis 'port' --value 6379 --type integer
       nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\Redis' --type string
       nextcloud-occ config:system:set memcache.locking --value '\OC\Memcache\Redis' --type string
     '';
     withRcloneEnv = pkgs.writeScript "with-rclone-env" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav
       export RCLONE_CONFIG_NEXTCLOUD_URL="http://nextcloud/remote.php/webdav/"
       export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud"
@@ -76,12 +76,12 @@ in {
       "''${@}"
     '';
     copySharedFile = pkgs.writeScript "copy-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       echo 'hi' | ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file
     '';
 
     diffSharedFile = pkgs.writeScript "diff-shared-file" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       diff <(echo 'hi') <(${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file)
     '';
   in ''
diff --git a/nixpkgs/nixos/tests/nginx-etag.nix b/nixpkgs/nixos/tests/nginx-etag.nix
index e357309d166a..63ab2e0c6c27 100644
--- a/nixpkgs/nixos/tests/nginx-etag.nix
+++ b/nixpkgs/nixos/tests/nginx-etag.nix
@@ -19,7 +19,7 @@ import ./make-test-python.nix {
         '';
       };
 
-      nesting.clone = lib.singleton {
+      specialisation.pass-checks.configuration = {
         services.nginx.virtualHosts.server = {
           root = lib.mkForce (pkgs.runCommandLocal "testdir2" {} ''
             mkdir "$out"
@@ -70,7 +70,7 @@ import ./make-test-python.nix {
 
   testScript = { nodes, ... }: let
     inherit (nodes.server.config.system.build) toplevel;
-    newSystem = "${toplevel}/fine-tune/child-1";
+    newSystem = "${toplevel}/specialisation/pass-checks";
   in ''
     start_all()
 
diff --git a/nixpkgs/nixos/tests/nginx-pubhtml.nix b/nixpkgs/nixos/tests/nginx-pubhtml.nix
new file mode 100644
index 000000000000..432913cb42d2
--- /dev/null
+++ b/nixpkgs/nixos/tests/nginx-pubhtml.nix
@@ -0,0 +1,20 @@
+import ./make-test-python.nix {
+  name = "nginx-pubhtml";
+
+  machine = { pkgs, ... }: {
+    services.nginx.enable = true;
+    services.nginx.virtualHosts.localhost = {
+      locations."~ ^/\\~([a-z0-9_]+)(/.*)?$".alias = "/home/$1/public_html$2";
+    };
+    users.users.foo.isNormalUser = true;
+  };
+
+  testScript = ''
+    machine.wait_for_unit("nginx")
+    machine.wait_for_open_port(80)
+    machine.succeed("chmod 0711 /home/foo")
+    machine.succeed("su -c 'mkdir -p /home/foo/public_html' foo")
+    machine.succeed("su -c 'echo bar > /home/foo/public_html/bar.txt' foo")
+    machine.succeed('test "$(curl -fvvv http://localhost/~foo/bar.txt)" = bar')
+  '';
+}
diff --git a/nixpkgs/nixos/tests/nginx.nix b/nixpkgs/nixos/tests/nginx.nix
index 7358800a6763..18822f095688 100644
--- a/nixpkgs/nixos/tests/nginx.nix
+++ b/nixpkgs/nixos/tests/nginx.nix
@@ -42,38 +42,35 @@ import ./make-test-python.nix ({ pkgs, ... }: {
 
       services.nginx.enableReload = true;
 
-      nesting.clone = [
-        {
-          services.nginx.virtualHosts.localhost = {
-            root = lib.mkForce (pkgs.runCommand "testdir2" {} ''
-              mkdir "$out"
-              echo content changed > "$out/index.html"
-            '');
-          };
-        }
-
-        {
-          services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }];
-        }
-
-        {
-          services.nginx.package = pkgs.nginxUnstable;
-        }
-
-        {
-          services.nginx.package = pkgs.nginxUnstable;
-          services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
-        }
-      ];
-    };
+      specialisation.etagSystem.configuration = {
+        services.nginx.virtualHosts.localhost = {
+          root = lib.mkForce (pkgs.runCommand "testdir2" {} ''
+            mkdir "$out"
+            echo content changed > "$out/index.html"
+          '');
+        };
+      };
+
+      specialisation.justReloadSystem.configuration = {
+        services.nginx.virtualHosts."1.my.test".listen = [ { addr = "127.0.0.1"; port = 8080; }];
+      };
 
+      specialisation.reloadRestartSystem.configuration = {
+        services.nginx.package = pkgs.nginxUnstable;
+      };
+
+      specialisation.reloadWithErrorsSystem.configuration = {
+        services.nginx.package = pkgs.nginxUnstable;
+        services.nginx.virtualHosts."!@$$(#*%".locations."~@#*$*!)".proxyPass = ";;;";
+      };
+    };
   };
 
   testScript = { nodes, ... }: let
-    etagSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-1";
-    justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-2";
-    reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-3";
-    reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/fine-tune/child-4";
+    etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etagSystem";
+    justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/justReloadSystem";
+    reloadRestartSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadRestartSystem";
+    reloadWithErrorsSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/reloadWithErrorsSystem";
   in ''
     url = "http://localhost/index.html"
 
diff --git a/nixpkgs/nixos/tests/os-prober.nix b/nixpkgs/nixos/tests/os-prober.nix
index 5407a62339fe..6a38f5ca531c 100644
--- a/nixpkgs/nixos/tests/os-prober.nix
+++ b/nixpkgs/nixos/tests/os-prober.nix
@@ -51,6 +51,8 @@ let
       hashed-mirrors =
       connect-timeout = 1
     '';
+    # save some memory
+    documentation.enable = false;
   };
   # /etc/nixos/configuration.nix for the vm
   configFile = pkgs.writeText "configuration.nix"  ''
diff --git a/nixpkgs/nixos/tests/php/default.nix b/nixpkgs/nixos/tests/php/default.nix
new file mode 100644
index 000000000000..9ab14f722d08
--- /dev/null
+++ b/nixpkgs/nixos/tests/php/default.nix
@@ -0,0 +1,7 @@
+{ system ? builtins.currentSystem,
+  config ? {},
+  pkgs ? import ../../.. { inherit system config; }
+}: {
+  fpm = import ./fpm.nix { inherit system pkgs; };
+  pcre = import ./pcre.nix { inherit system pkgs; };
+}
diff --git a/nixpkgs/nixos/tests/php/fpm.nix b/nixpkgs/nixos/tests/php/fpm.nix
new file mode 100644
index 000000000000..e93a31834185
--- /dev/null
+++ b/nixpkgs/nixos/tests/php/fpm.nix
@@ -0,0 +1,55 @@
+import ../make-test-python.nix ({pkgs, ...}: {
+  name = "php-fpm-nginx-test";
+  meta.maintainers = with pkgs.stdenv.lib.maintainers; [ etu ];
+
+  machine = { config, lib, pkgs, ... }: {
+    services.nginx = {
+      enable = true;
+
+      virtualHosts."phpfpm" = let
+        testdir = pkgs.writeTextDir "web/index.php" "<?php phpinfo();";
+      in {
+        root = "${testdir}/web";
+        locations."~ \.php$".extraConfig = ''
+          fastcgi_pass unix:${config.services.phpfpm.pools.foobar.socket};
+          fastcgi_index index.php;
+          include ${pkgs.nginx}/conf/fastcgi_params;
+          include ${pkgs.nginx}/conf/fastcgi.conf;
+        '';
+        locations."/" = {
+          tryFiles = "$uri $uri/ index.php";
+          index = "index.php index.html index.htm";
+        };
+      };
+    };
+
+    services.phpfpm.pools."foobar" = {
+      user = "nginx";
+      settings = {
+        "listen.group" = "nginx";
+        "listen.mode" = "0600";
+        "listen.owner" = "nginx";
+        "pm" = "dynamic";
+        "pm.max_children" = 5;
+        "pm.max_requests" = 500;
+        "pm.max_spare_servers" = 3;
+        "pm.min_spare_servers" = 1;
+        "pm.start_servers" = 2;
+      };
+    };
+  };
+  testScript = { ... }: ''
+    machine.wait_for_unit("nginx.service")
+    machine.wait_for_unit("phpfpm-foobar.service")
+
+    # Check so we get an evaluated PHP back
+    assert "PHP Version ${pkgs.php.version}" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+
+    # Check so we have database and some other extensions loaded
+    assert "json" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+    assert "opcache" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+    assert "pdo_mysql" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+    assert "pdo_pgsql" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+    assert "pdo_sqlite" in machine.succeed("curl -vvv -s http://127.0.0.1:80/")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/php-pcre.nix b/nixpkgs/nixos/tests/php/pcre.nix
index d5c22e0582a0..56a87778579f 100644
--- a/nixpkgs/nixos/tests/php-pcre.nix
+++ b/nixpkgs/nixos/tests/php/pcre.nix
@@ -1,7 +1,6 @@
-
-let testString = "can-use-subgroups"; in
-
-import ./make-test-python.nix ({ ...}: {
+let
+  testString = "can-use-subgroups";
+in import ../make-test-python.nix ({ ...}: {
   name = "php-httpd-pcre-jit-test";
   machine = { lib, pkgs, ... }: {
     time.timeZone = "UTC";
@@ -10,15 +9,13 @@ import ./make-test-python.nix ({ ...}: {
       adminAddr = "please@dont.contact";
       enablePHP = true;
       phpOptions = "pcre.jit = true";
-      extraConfig =
-      let
+      extraConfig = let
         testRoot = pkgs.writeText "index.php"
-        ''
-          <?php
+          ''
+            <?php
             preg_match('/(${testString})/', '${testString}', $result);
             var_dump($result);
-          ?>
-        '';
+          '';
       in
         ''
           Alias / ${testRoot}/
@@ -30,11 +27,11 @@ import ./make-test-python.nix ({ ...}: {
     };
   };
   testScript = { ... }:
-  ''
-    machine.wait_for_unit("httpd.service")
-    # Ensure php evaluation by matching on the var_dump syntax
-    assert 'string(${toString (builtins.stringLength testString)}) "${testString}"' in machine.succeed(
-        "curl -vvv -s http://127.0.0.1:80/index.php"
-    )
-  '';
+    ''
+      machine.wait_for_unit("httpd.service")
+      # Ensure php evaluation by matching on the var_dump syntax
+      assert 'string(${toString (builtins.stringLength testString)}) "${testString}"' in machine.succeed(
+          "curl -vvv -s http://127.0.0.1:80/index.php"
+      )
+    '';
 })
diff --git a/nixpkgs/nixos/tests/quorum.nix b/nixpkgs/nixos/tests/quorum.nix
new file mode 100644
index 000000000000..846d2a930188
--- /dev/null
+++ b/nixpkgs/nixos/tests/quorum.nix
@@ -0,0 +1,79 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "quorum";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ mmahut ];
+  };
+
+  nodes = {
+    machine = { ... }: {
+      services.quorum = {
+        enable = true;
+        permissioned = false;
+        staticNodes = [ "enode://dd333ec28f0a8910c92eb4d336461eea1c20803eed9cf2c056557f986e720f8e693605bba2f4e8f289b1162e5ac7c80c914c7178130711e393ca76abc1d92f57@0.0.0.0:30303?discport=0" ];
+        genesis = {
+          alloc = {
+            "189d23d201b03ae1cf9113672df29a5d672aefa3" = {
+              balance = "0x446c3b15f9926687d2c40534fdb564000000000000";
+            };
+            "44b07d2c28b8ed8f02b45bd84ac7d9051b3349e6" = {
+              balance = "0x446c3b15f9926687d2c40534fdb564000000000000";
+            };
+            "4c1ccd426833b9782729a212c857f2f03b7b4c0d" = {
+              balance = "0x446c3b15f9926687d2c40534fdb564000000000000";
+            };
+            "7ae555d0f6faad7930434abdaac2274fd86ab516" = {
+              balance = "0x446c3b15f9926687d2c40534fdb564000000000000";
+            };
+            c1056df7c02b6f1a353052eaf0533cc7cb743b52 = {
+              balance = "0x446c3b15f9926687d2c40534fdb564000000000000";
+            };
+          };
+          coinbase = "0x0000000000000000000000000000000000000000";
+          config = {
+            byzantiumBlock = 1;
+            chainId = 10;
+            eip150Block = 1;
+            eip150Hash =
+              "0x0000000000000000000000000000000000000000000000000000000000000000";
+            eip155Block = 1;
+            eip158Block = 1;
+            isQuorum = true;
+            istanbul = {
+              epoch = 30000;
+              policy = 0;
+            };
+          };
+        difficulty = "0x1";
+        extraData =
+          "0x0000000000000000000000000000000000000000000000000000000000000000f8aff869944c1ccd426833b9782729a212c857f2f03b7b4c0d94189d23d201b03ae1cf9113672df29a5d672aefa39444b07d2c28b8ed8f02b45bd84ac7d9051b3349e694c1056df7c02b6f1a353052eaf0533cc7cb743b52947ae555d0f6faad7930434abdaac2274fd86ab516b8410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0";
+        gasLimit = "0xe0000000";
+        gasUsed = "0x0";
+        mixHash =
+          "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365";
+        nonce = "0x0";
+        number = "0x0";
+        parentHash =
+          "0x0000000000000000000000000000000000000000000000000000000000000000";
+        timestamp = "0x5cffc201";
+		  };
+     };
+    };
+  };
+
+  testScript = ''
+    start_all()
+    machine.wait_until_succeeds("mkdir -p /var/lib/quorum/keystore")
+    machine.wait_until_succeeds(
+        'echo \{\\"address\\":\\"9377bc3936de934c497e22917b81aa8774ac3bb0\\",\\"crypto\\":\{\\"cipher\\":\\"aes-128-ctr\\",\\"ciphertext\\":\\"ad8341d8ef225650403fd366c955f41095e438dd966a3c84b3d406818c1e366c\\",\\"cipherparams\\":\{\\"iv\\":\\"2a09f7a72fd6dff7c43150ff437e6ac2\\"\},\\"kdf\\":\\"scrypt\\",\\"kdfparams\\":\{\\"dklen\\":32,\\"n\\":262144,\\"p\\":1,\\"r\\":8,\\"salt\\":\\"d1a153845bb80cd6274c87c5bac8ac09fdfac5ff131a6f41b5ed319667f12027\\"\},\\"mac\\":\\"a9621ad88fa1d042acca6fc2fcd711f7e05bfbadea3f30f379235570c8e270d3\\"\},\\"id\\":\\"89e847a3-1527-42f6-a321-77de0a14ce02\\",\\"version\\":3\}\\" > /var/lib/quorum/keystore/UTC--2020-03-23T11-08-34.144812212Z--9377bc3936de934c497e22917b81aa8774ac3bb0'
+    )
+    machine.wait_until_succeeds(
+        "echo fe2725c4e8f7617764b845e8d939a65c664e7956eb47ed7d934573f16488efc1 > /var/lib/quorum/nodekey"
+    )
+    machine.wait_until_succeeds("systemctl restart quorum")
+    machine.wait_for_unit("quorum.service")
+    machine.sleep(15)
+    machine.wait_until_succeeds(
+        'geth attach /var/lib/quorum/geth.ipc --exec "eth.accounts" | grep 0x9377bc3936de934c497e22917b81aa8774ac3bb0'
+    )
+  '';
+})
diff --git a/nixpkgs/nixos/tests/rabbitmq.nix b/nixpkgs/nixos/tests/rabbitmq.nix
index 8e7f34d06e32..f403e4ac2edc 100644
--- a/nixpkgs/nixos/tests/rabbitmq.nix
+++ b/nixpkgs/nixos/tests/rabbitmq.nix
@@ -15,7 +15,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
 
     machine.wait_for_unit("rabbitmq.service")
     machine.wait_until_succeeds(
-        'su -s ${pkgs.stdenv.shell} rabbitmq -c "rabbitmqctl status"'
+        'su -s ${pkgs.runtimeShell} rabbitmq -c "rabbitmqctl status"'
     )
   '';
 })
diff --git a/nixpkgs/nixos/tests/redmine.nix b/nixpkgs/nixos/tests/redmine.nix
index f0f4cbf6a21c..73eb684f33a9 100644
--- a/nixpkgs/nixos/tests/redmine.nix
+++ b/nixpkgs/nixos/tests/redmine.nix
@@ -15,13 +15,13 @@ let
         services.redmine.database.type = "mysql2";
         services.redmine.plugins = {
           redmine_env_auth = pkgs.fetchurl {
-            url = https://github.com/Intera/redmine_env_auth/archive/0.7.zip;
+            url = "https://github.com/Intera/redmine_env_auth/archive/0.7.zip";
             sha256 = "1xb8lyarc7mpi86yflnlgyllh9hfwb9z304f19dx409gqpia99sc";
           };
         };
         services.redmine.themes = {
           dkuk-redmine_alex_skin = pkgs.fetchurl {
-            url = https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip;
+            url = "https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip";
             sha256 = "0hrin9lzyi50k4w2bd2b30vrf1i4fi1c0gyas5801wn8i7kpm9yl";
           };
         };
@@ -43,13 +43,13 @@ let
         services.redmine.database.type = "postgresql";
         services.redmine.plugins = {
           redmine_env_auth = pkgs.fetchurl {
-            url = https://github.com/Intera/redmine_env_auth/archive/0.7.zip;
+            url = "https://github.com/Intera/redmine_env_auth/archive/0.7.zip";
             sha256 = "1xb8lyarc7mpi86yflnlgyllh9hfwb9z304f19dx409gqpia99sc";
           };
         };
         services.redmine.themes = {
           dkuk-redmine_alex_skin = pkgs.fetchurl {
-            url = https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip;
+            url = "https://bitbucket.org/dkuk/redmine_alex_skin/get/1842ef675ef3.zip";
             sha256 = "0hrin9lzyi50k4w2bd2b30vrf1i4fi1c0gyas5801wn8i7kpm9yl";
           };
         };
diff --git a/nixpkgs/nixos/tests/roundcube.nix b/nixpkgs/nixos/tests/roundcube.nix
index 1897b53e283a..97e1125694b6 100644
--- a/nixpkgs/nixos/tests/roundcube.nix
+++ b/nixpkgs/nixos/tests/roundcube.nix
@@ -12,6 +12,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
         database.password = "not production";
         package = pkgs.roundcube.withPlugins (plugins: [ plugins.persistent_login ]);
         plugins = [ "persistent_login" ];
+        dicts = with pkgs.aspellDicts; [ en fr de ];
       };
       services.nginx.virtualHosts.roundcube = {
         forceSSL = false;
diff --git a/nixpkgs/nixos/tests/rxe.nix b/nixpkgs/nixos/tests/rxe.nix
index 194a2e3d2b94..10753c4ed0c8 100644
--- a/nixpkgs/nixos/tests/rxe.nix
+++ b/nixpkgs/nixos/tests/rxe.nix
@@ -28,7 +28,7 @@ in {
     # Test if rxe interface comes up
     server.wait_for_unit("default.target")
     server.succeed("systemctl status rxe.service")
-    server.succeed("ibv_devices | grep rxe0")
+    server.succeed("ibv_devices | grep rxe_eth1")
 
     client.wait_for_unit("default.target")
 
diff --git a/nixpkgs/nixos/tests/specialisation.nix b/nixpkgs/nixos/tests/specialisation.nix
new file mode 100644
index 000000000000..b8d4b8279f4d
--- /dev/null
+++ b/nixpkgs/nixos/tests/specialisation.nix
@@ -0,0 +1,43 @@
+import ./make-test-python.nix {
+  name = "specialisation";
+  nodes =  {
+    inheritconf = { pkgs, ... }: {
+      environment.systemPackages = [ pkgs.cowsay ];
+      specialisation.inheritconf.configuration = { pkgs, ... }: {
+        environment.systemPackages = [ pkgs.hello ];
+      };
+    };
+    noinheritconf = { pkgs, ... }: {
+      environment.systemPackages = [ pkgs.cowsay ];
+      specialisation.noinheritconf = {
+        inheritParentConfig = false;
+        configuration = { pkgs, ... }: {
+          environment.systemPackages = [ pkgs.hello ];
+        };
+      };
+    };
+  };
+  testScript = ''
+    inheritconf.wait_for_unit("default.target")
+    inheritconf.succeed("cowsay hey")
+    inheritconf.fail("hello")
+
+    with subtest("Nested clones do inherit from parent"):
+        inheritconf.succeed(
+            "/run/current-system/specialisation/inheritconf/bin/switch-to-configuration test"
+        )
+        inheritconf.succeed("cowsay hey")
+        inheritconf.succeed("hello")
+
+        noinheritconf.wait_for_unit("default.target")
+        noinheritconf.succeed("cowsay hey")
+        noinheritconf.fail("hello")
+
+    with subtest("Nested children do not inherit from parent"):
+        noinheritconf.succeed(
+            "/run/current-system/specialisation/noinheritconf/bin/switch-to-configuration test"
+        )
+        noinheritconf.fail("cowsay hey")
+        noinheritconf.succeed("hello")
+  '';
+}
diff --git a/nixpkgs/nixos/tests/switch-test.nix b/nixpkgs/nixos/tests/switch-test.nix
index 7076bd77b770..9ef96cec5ef3 100644
--- a/nixpkgs/nixos/tests/switch-test.nix
+++ b/nixpkgs/nixos/tests/switch-test.nix
@@ -22,7 +22,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     # Ensures failures pass through using pipefail, otherwise failing to
     # switch-to-configuration is hidden by the success of `tee`.
     stderrRunner = pkgs.writeScript "stderr-runner" ''
-      #! ${pkgs.stdenv.shell}
+      #! ${pkgs.runtimeShell}
       set -e
       set -o pipefail
       exec env -i "$@" | tee /dev/stderr
diff --git a/nixpkgs/nixos/tests/systemd-confinement.nix b/nixpkgs/nixos/tests/systemd-confinement.nix
index b7b10fb36aac..f22836e227b0 100644
--- a/nixpkgs/nixos/tests/systemd-confinement.nix
+++ b/nixpkgs/nixos/tests/systemd-confinement.nix
@@ -3,14 +3,14 @@ import ./make-test.nix {
 
   machine = { pkgs, lib, ... }: let
     testServer = pkgs.writeScript "testserver.sh" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       export PATH=${lib.escapeShellArg "${pkgs.coreutils}/bin"}
-      ${lib.escapeShellArg pkgs.stdenv.shell} 2>&1
+      ${lib.escapeShellArg pkgs.runtimeShell} 2>&1
       echo "exit-status:$?"
     '';
 
     testClient = pkgs.writeScriptBin "chroot-exec" ''
-      #!${pkgs.stdenv.shell} -e
+      #!${pkgs.runtimeShell} -e
       output="$(echo "$@" | nc -NU "/run/test$(< /teststep).sock")"
       ret="$(echo "$output" | sed -nre '$s/^exit-status:([0-9]+)$/\1/p')"
       echo "$output" | head -n -1
diff --git a/nixpkgs/nixos/tests/systemd.nix b/nixpkgs/nixos/tests/systemd.nix
index 8028145939bb..ca2e36a443e9 100644
--- a/nixpkgs/nixos/tests/systemd.nix
+++ b/nixpkgs/nixos/tests/systemd.nix
@@ -22,7 +22,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     test-support.displayManager.auto.user = "alice";
 
     systemd.shutdown.test = pkgs.writeScript "test.shutdown" ''
-      #!${pkgs.stdenv.shell}
+      #!${pkgs.runtimeShell}
       PATH=${lib.makeBinPath (with pkgs; [ utillinux coreutils ])}
       mount -t 9p shared -o trans=virtio,version=9p2000.L /tmp/shared
       touch /tmp/shared/shutdown-test
diff --git a/nixpkgs/nixos/tests/traefik.nix b/nixpkgs/nixos/tests/traefik.nix
new file mode 100644
index 000000000000..0e21a7cf8437
--- /dev/null
+++ b/nixpkgs/nixos/tests/traefik.nix
@@ -0,0 +1,87 @@
+# Test Traefik as a reverse proxy of a local web service
+# and a Docker container.
+import ./make-test-python.nix ({ pkgs, ... }: {
+  name = "traefik";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ joko ];
+  };
+
+  nodes = {
+    client = { config, pkgs, ... }: {
+      environment.systemPackages = [ pkgs.curl ];
+    };
+    traefik = { config, pkgs, ... }: {
+      docker-containers.nginx = {
+        extraDockerOptions = [
+          "-l" "traefik.enable=true"
+          "-l" "traefik.http.routers.nginx.entrypoints=web"
+          "-l" "traefik.http.routers.nginx.rule=Host(`nginx.traefik.test`)"
+        ];
+        image = "nginx-container";
+        imageFile = pkgs.dockerTools.examples.nginx;
+      };
+
+      networking.firewall.allowedTCPPorts = [ 80 ];
+
+      services.traefik = {
+        enable = true;
+
+        dynamicConfigOptions = {
+          http.routers.simplehttp = {
+            rule = "Host(`simplehttp.traefik.test`)";
+            entryPoints = [ "web" ];
+            service = "simplehttp";
+          };
+
+          http.services.simplehttp = {
+            loadBalancer.servers = [{
+              url = "http://127.0.0.1:8000";
+            }];
+          };
+        };
+
+        staticConfigOptions = {
+          global = {
+            checkNewVersion = false;
+            sendAnonymousUsage = false;
+          };
+
+          entryPoints.web.address = ":80";
+
+          providers.docker.exposedByDefault = false;
+        };
+      };
+
+      systemd.services.simplehttp = {
+        script = "${pkgs.python3}/bin/python -m http.server 8000";
+        serviceConfig.Type = "simple";
+        wantedBy = [ "multi-user.target" ];
+      };
+
+      users.users.traefik.extraGroups = [ "docker" ];
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    traefik.wait_for_unit("docker-nginx.service")
+    traefik.wait_until_succeeds("docker ps | grep nginx-container")
+    traefik.wait_for_unit("simplehttp.service")
+    traefik.wait_for_unit("traefik.service")
+    traefik.wait_for_open_port(80)
+    traefik.wait_for_unit("multi-user.target")
+
+    client.wait_for_unit("multi-user.target")
+
+    with subtest("Check that a container can be reached via Traefik"):
+        assert "Hello from NGINX" in client.succeed(
+            "curl -sSf -H Host:nginx.traefik.test http://traefik/"
+        )
+
+    with subtest("Check that dynamic configuration works"):
+        assert "Directory listing for " in client.succeed(
+            "curl -sSf -H Host:simplehttp.traefik.test http://traefik/"
+        )
+  '';
+})
diff --git a/nixpkgs/nixos/tests/tuptime.nix b/nixpkgs/nixos/tests/tuptime.nix
new file mode 100644
index 000000000000..36ce2b1ae192
--- /dev/null
+++ b/nixpkgs/nixos/tests/tuptime.nix
@@ -0,0 +1,29 @@
+import ./make-test-python.nix ({ pkgs, ...} : {
+  name = "tuptime";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ evils ];
+  };
+
+  machine = { pkgs, ... }: {
+    imports = [ ../modules/profiles/minimal.nix ];
+    services.tuptime.enable = true;
+  };
+
+  testScript =
+    ''
+      # see if it starts
+      start_all()
+      machine.wait_for_unit("multi-user.target")
+      machine.succeed("tuptime | grep 'System startups:[[:blank:]]*1'")
+      machine.succeed("tuptime | grep 'System uptime:[[:blank:]]*100.0%'")
+      machine.shutdown()
+
+      # restart machine and see if it correctly reports the reboot
+      machine.start()
+      machine.wait_for_unit("multi-user.target")
+      machine.succeed("tuptime | grep 'System startups:[[:blank:]]*2'")
+      machine.succeed("tuptime | grep 'System shutdowns:[[:blank:]]*1 ok'")
+      machine.shutdown()
+    '';
+})
+
diff --git a/nixpkgs/nixos/tests/udisks2.nix b/nixpkgs/nixos/tests/udisks2.nix
index 0cbfa0c4c7be..64f5b6c40d20 100644
--- a/nixpkgs/nixos/tests/udisks2.nix
+++ b/nixpkgs/nixos/tests/udisks2.nix
@@ -3,7 +3,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
 let
 
   stick = pkgs.fetchurl {
-    url = http://nixos.org/~eelco/nix/udisks-test.img.xz;
+    url = "http://nixos.org/~eelco/nix/udisks-test.img.xz";
     sha256 = "0was1xgjkjad91nipzclaz5biv3m4b2nk029ga6nk7iklwi19l8b";
   };
 
diff --git a/nixpkgs/nixos/tests/virtualbox.nix b/nixpkgs/nixos/tests/virtualbox.nix
index f03dc1cc4138..aec8da6a2af3 100644
--- a/nixpkgs/nixos/tests/virtualbox.nix
+++ b/nixpkgs/nixos/tests/virtualbox.nix
@@ -23,7 +23,7 @@ let
     guestAdditions = pkgs.linuxPackages.virtualboxGuestAdditions;
 
     miniInit = ''
-      #!${pkgs.stdenv.shell} -xe
+      #!${pkgs.runtimeShell} -xe
       export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.utillinux ]}"
 
       mkdir -p /run/dbus
@@ -80,7 +80,7 @@ let
       touch /mnt-root/boot-done
       hostname "${vmName}"
       mkdir -p /nix/store
-      unshare -m ${escapeShellArg pkgs.stdenv.shell} -c '
+      unshare -m ${escapeShellArg pkgs.runtimeShell} -c '
         mount -t vboxsf nixstore /nix/store
         exec "$stage2Init"
       '
diff --git a/nixpkgs/nixos/tests/wireguard/default.nix b/nixpkgs/nixos/tests/wireguard/default.nix
index 8206823a9181..e3bc31c600f9 100644
--- a/nixpkgs/nixos/tests/wireguard/default.nix
+++ b/nixpkgs/nixos/tests/wireguard/default.nix
@@ -1,97 +1,71 @@
-let
-  wg-snakeoil-keys = import ./snakeoil-keys.nix;
-in
-
-import ../make-test-python.nix ({ pkgs, ...} : {
-  name = "wireguard";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ ma27 ];
-  };
-
-  nodes = {
-    peer0 = { lib, ... }: {
-      boot.kernel.sysctl = {
-        "net.ipv6.conf.all.forwarding" = "1";
-        "net.ipv6.conf.default.forwarding" = "1";
-        "net.ipv4.ip_forward" = "1";
-      };
-
-      networking.useDHCP = false;
-      networking.interfaces.eth1 = {
-        ipv4.addresses = lib.singleton {
-          address = "192.168.0.1";
-          prefixLength = 24;
-        };
-        ipv6.addresses = lib.singleton {
-          address = "fd00::1";
-          prefixLength = 64;
-        };
-      };
+import ../make-test-python.nix ({ pkgs, lib, ...} :
+  let
+    wg-snakeoil-keys = import ./snakeoil-keys.nix;
+    peer = (import ./make-peer.nix) { inherit lib; };
+  in
+  {
+    name = "wireguard";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ ma27 ];
+    };
 
-      networking.firewall.allowedUDPPorts = [ 23542 ];
-      networking.wireguard.interfaces.wg0 = {
-        ips = [ "10.23.42.1/32" "fc00::1/128" ];
-        listenPort = 23542;
+    nodes = {
+      peer0 = peer {
+        ip4 = "192.168.0.1";
+        ip6 = "fd00::1";
+        extraConfig = {
+          networking.firewall.allowedUDPPorts = [ 23542 ];
+          networking.wireguard.interfaces.wg0 = {
+            ips = [ "10.23.42.1/32" "fc00::1/128" ];
+            listenPort = 23542;
 
-        inherit (wg-snakeoil-keys.peer0) privateKey;
+            inherit (wg-snakeoil-keys.peer0) privateKey;
 
-        peers = lib.singleton {
-          allowedIPs = [ "10.23.42.2/32" "fc00::2/128" ];
+            peers = lib.singleton {
+              allowedIPs = [ "10.23.42.2/32" "fc00::2/128" ];
 
-          inherit (wg-snakeoil-keys.peer1) publicKey;
+              inherit (wg-snakeoil-keys.peer1) publicKey;
+            };
+          };
         };
       };
-    };
 
-    peer1 = { pkgs, lib, ... }: {
-      boot.kernel.sysctl = {
-        "net.ipv6.conf.all.forwarding" = "1";
-        "net.ipv6.conf.default.forwarding" = "1";
-        "net.ipv4.ip_forward" = "1";
-      };
-
-      networking.useDHCP = false;
-      networking.interfaces.eth1 = {
-        ipv4.addresses = lib.singleton {
-          address = "192.168.0.2";
-          prefixLength = 24;
-        };
-        ipv6.addresses = lib.singleton {
-          address = "fd00::2";
-          prefixLength = 64;
+      peer1 = peer {
+        ip4 = "192.168.0.2";
+        ip6 = "fd00::2";
+        extraConfig = {
+          networking.wireguard.interfaces.wg0 = {
+            ips = [ "10.23.42.2/32" "fc00::2/128" ];
+            listenPort = 23542;
+            allowedIPsAsRoutes = false;
+
+            inherit (wg-snakeoil-keys.peer1) privateKey;
+
+            peers = lib.singleton {
+              allowedIPs = [ "0.0.0.0/0" "::/0" ];
+              endpoint = "192.168.0.1:23542";
+              persistentKeepalive = 25;
+
+              inherit (wg-snakeoil-keys.peer0) publicKey;
+            };
+
+            postSetup = let inherit (pkgs) iproute; in ''
+              ${iproute}/bin/ip route replace 10.23.42.1/32 dev wg0
+              ${iproute}/bin/ip route replace fc00::1/128 dev wg0
+            '';
+          };
         };
       };
-
-      networking.wireguard.interfaces.wg0 = {
-        ips = [ "10.23.42.2/32" "fc00::2/128" ];
-        listenPort = 23542;
-        allowedIPsAsRoutes = false;
-
-        inherit (wg-snakeoil-keys.peer1) privateKey;
-
-        peers = lib.singleton {
-          allowedIPs = [ "0.0.0.0/0" "::/0" ];
-          endpoint = "192.168.0.1:23542";
-          persistentKeepalive = 25;
-
-          inherit (wg-snakeoil-keys.peer0) publicKey;
-        };
-
-        postSetup = let inherit (pkgs) iproute; in ''
-          ${iproute}/bin/ip route replace 10.23.42.1/32 dev wg0
-          ${iproute}/bin/ip route replace fc00::1/128 dev wg0
-        '';
-      };
     };
-  };
 
-  testScript = ''
-    start_all()
+    testScript = ''
+      start_all()
 
-    peer0.wait_for_unit("wireguard-wg0.service")
-    peer1.wait_for_unit("wireguard-wg0.service")
+      peer0.wait_for_unit("wireguard-wg0.service")
+      peer1.wait_for_unit("wireguard-wg0.service")
 
-    peer1.succeed("ping -c5 fc00::1")
-    peer1.succeed("ping -c5 10.23.42.1")
-  '';
-})
+      peer1.succeed("ping -c5 fc00::1")
+      peer1.succeed("ping -c5 10.23.42.1")
+    '';
+  }
+)
diff --git a/nixpkgs/nixos/tests/wireguard/make-peer.nix b/nixpkgs/nixos/tests/wireguard/make-peer.nix
new file mode 100644
index 000000000000..d2740549738b
--- /dev/null
+++ b/nixpkgs/nixos/tests/wireguard/make-peer.nix
@@ -0,0 +1,23 @@
+{ lib, ... }: { ip4, ip6, extraConfig }:
+lib.mkMerge [
+  {
+    boot.kernel.sysctl = {
+      "net.ipv6.conf.all.forwarding" = "1";
+      "net.ipv6.conf.default.forwarding" = "1";
+      "net.ipv4.ip_forward" = "1";
+    };
+
+    networking.useDHCP = false;
+    networking.interfaces.eth1 = {
+      ipv4.addresses = [{
+        address = ip4;
+        prefixLength = 24;
+      }];
+      ipv6.addresses = [{
+        address = ip6;
+        prefixLength = 64;
+      }];
+    };
+  }
+  extraConfig
+]
diff --git a/nixpkgs/nixos/tests/wireguard/wg-quick.nix b/nixpkgs/nixos/tests/wireguard/wg-quick.nix
new file mode 100644
index 000000000000..7354dd01a34a
--- /dev/null
+++ b/nixpkgs/nixos/tests/wireguard/wg-quick.nix
@@ -0,0 +1,63 @@
+import ../make-test-python.nix ({ pkgs, lib, ... }:
+  let
+    wg-snakeoil-keys = import ./snakeoil-keys.nix;
+    peer = (import ./make-peer.nix) { inherit lib; };
+  in
+  {
+    name = "wg-quick";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ xwvvvvwx ];
+    };
+
+    nodes = {
+      peer0 = peer {
+        ip4 = "192.168.0.1";
+        ip6 = "fd00::1";
+        extraConfig = {
+          networking.firewall.allowedUDPPorts = [ 23542 ];
+          networking.wg-quick.interfaces.wg0 = {
+            address = [ "10.23.42.1/32" "fc00::1/128" ];
+            listenPort = 23542;
+
+            inherit (wg-snakeoil-keys.peer0) privateKey;
+
+            peers = lib.singleton {
+              allowedIPs = [ "10.23.42.2/32" "fc00::2/128" ];
+
+              inherit (wg-snakeoil-keys.peer1) publicKey;
+            };
+          };
+        };
+      };
+
+      peer1 = peer {
+        ip4 = "192.168.0.2";
+        ip6 = "fd00::2";
+        extraConfig = {
+          networking.wg-quick.interfaces.wg0 = {
+            address = [ "10.23.42.2/32" "fc00::2/128" ];
+            inherit (wg-snakeoil-keys.peer1) privateKey;
+
+            peers = lib.singleton {
+              allowedIPs = [ "0.0.0.0/0" "::/0" ];
+              endpoint = "192.168.0.1:23542";
+              persistentKeepalive = 25;
+
+              inherit (wg-snakeoil-keys.peer0) publicKey;
+            };
+          };
+        };
+      };
+    };
+
+    testScript = ''
+      start_all()
+
+      peer0.wait_for_unit("wg-quick-wg0.service")
+      peer1.wait_for_unit("wg-quick-wg0.service")
+
+      peer1.succeed("ping -c5 fc00::1")
+      peer1.succeed("ping -c5 10.23.42.1")
+    '';
+  }
+)