about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/tests')
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix15
-rw-r--r--nixpkgs/nixos/tests/anbox.nix2
-rw-r--r--nixpkgs/nixos/tests/angie-api.nix148
-rw-r--r--nixpkgs/nixos/tests/btrbk-section-order.nix7
-rw-r--r--nixpkgs/nixos/tests/cinnamon-wayland.nix6
-rw-r--r--nixpkgs/nixos/tests/cinnamon.nix6
-rw-r--r--nixpkgs/nixos/tests/code-server.nix22
-rw-r--r--nixpkgs/nixos/tests/containers-custom-pkgs.nix2
-rw-r--r--nixpkgs/nixos/tests/dhparams.nix2
-rw-r--r--nixpkgs/nixos/tests/docker-tools.nix2
-rw-r--r--nixpkgs/nixos/tests/drawterm.nix58
-rw-r--r--nixpkgs/nixos/tests/ft2-clone.nix4
-rw-r--r--nixpkgs/nixos/tests/gitlab.nix2
-rw-r--r--nixpkgs/nixos/tests/gns3-server.nix55
-rw-r--r--nixpkgs/nixos/tests/google-oslogin/default.nix3
-rw-r--r--nixpkgs/nixos/tests/incron.nix6
-rw-r--r--nixpkgs/nixos/tests/incus/container.nix4
-rw-r--r--nixpkgs/nixos/tests/incus/virtual-machine.nix3
-rw-r--r--nixpkgs/nixos/tests/initrd-network-openvpn/default.nix15
-rw-r--r--nixpkgs/nixos/tests/installer-systemd-stage-1.nix1
-rw-r--r--nixpkgs/nixos/tests/installer.nix86
-rw-r--r--nixpkgs/nixos/tests/invidious.nix120
-rw-r--r--nixpkgs/nixos/tests/iscsi-root.nix4
-rw-r--r--nixpkgs/nixos/tests/livebook-service.nix4
-rw-r--r--nixpkgs/nixos/tests/lvm2/systemd-stage-1.nix4
-rw-r--r--nixpkgs/nixos/tests/lvm2/thinpool.nix2
-rw-r--r--nixpkgs/nixos/tests/lvm2/vdo.nix4
-rw-r--r--nixpkgs/nixos/tests/mate.nix27
-rw-r--r--nixpkgs/nixos/tests/munin.nix2
-rw-r--r--nixpkgs/nixos/tests/musescore.nix7
-rw-r--r--nixpkgs/nixos/tests/mympd.nix27
-rw-r--r--nixpkgs/nixos/tests/mysql/mariadb-galera.nix4
-rw-r--r--nixpkgs/nixos/tests/mysql/mysql-replication.nix4
-rw-r--r--nixpkgs/nixos/tests/mysql/mysql.nix4
-rw-r--r--nixpkgs/nixos/tests/nextcloud/basic.nix10
-rw-r--r--nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix2
-rw-r--r--nixpkgs/nixos/tests/nginx-http3.nix182
-rw-r--r--nixpkgs/nixos/tests/nginx-variants.nix10
-rw-r--r--nixpkgs/nixos/tests/nitter.nix21
-rw-r--r--nixpkgs/nixos/tests/nixos-rebuild-specialisations.nix2
-rw-r--r--nixpkgs/nixos/tests/npmrc.nix22
-rw-r--r--nixpkgs/nixos/tests/oci-containers.nix2
-rw-r--r--nixpkgs/nixos/tests/opentabletdriver.nix4
-rw-r--r--nixpkgs/nixos/tests/prometheus-exporters.nix51
-rw-r--r--nixpkgs/nixos/tests/rspamd-trainer.nix155
-rw-r--r--nixpkgs/nixos/tests/sogo.nix2
-rw-r--r--nixpkgs/nixos/tests/ssh-agent-auth.nix51
-rw-r--r--nixpkgs/nixos/tests/stunnel.nix4
-rw-r--r--nixpkgs/nixos/tests/systemd-boot.nix2
-rw-r--r--nixpkgs/nixos/tests/systemd-initrd-networkd.nix3
-rw-r--r--nixpkgs/nixos/tests/tomcat.nix2
-rw-r--r--nixpkgs/nixos/tests/varnish.nix6
-rw-r--r--nixpkgs/nixos/tests/zfs.nix3
53 files changed, 991 insertions, 205 deletions
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index c9234fc52536..02e3e91e2e3d 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -120,6 +120,7 @@ in {
   amazon-ssm-agent = handleTest ./amazon-ssm-agent.nix {};
   amd-sev = runTest ./amd-sev.nix;
   anbox = runTest ./anbox.nix;
+  angie-api = handleTest ./angie-api.nix {};
   anki-sync-server = handleTest ./anki-sync-server.nix {};
   anuko-time-tracker = handleTest ./anuko-time-tracker.nix {};
   apcupsd = handleTest ./apcupsd.nix {};
@@ -163,7 +164,7 @@ in {
   btrbk-no-timer = handleTest ./btrbk-no-timer.nix {};
   btrbk-section-order = handleTest ./btrbk-section-order.nix {};
   budgie = handleTest ./budgie.nix {};
-  buildbot = handleTestOn [ "x86_64-linux" ] ./buildbot.nix {};
+  buildbot = handleTest ./buildbot.nix {};
   buildkite-agents = handleTest ./buildkite-agents.nix {};
   c2fmzq = handleTest ./c2fmzq.nix {};
   caddy = handleTest ./caddy.nix {};
@@ -197,6 +198,7 @@ in {
   cntr = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cntr.nix {};
   cockpit = handleTest ./cockpit.nix {};
   cockroachdb = handleTestOn ["x86_64-linux"] ./cockroachdb.nix {};
+  code-server = handleTest ./code-server.nix {};
   coder = handleTest ./coder.nix {};
   collectd = handleTest ./collectd.nix {};
   connman = handleTest ./connman.nix {};
@@ -255,6 +257,7 @@ in {
   dolibarr = handleTest ./dolibarr.nix {};
   domination = handleTest ./domination.nix {};
   dovecot = handleTest ./dovecot.nix {};
+  drawterm = discoverTests (import ./drawterm.nix);
   drbd = handleTest ./drbd.nix {};
   dublin-traceroute = handleTest ./dublin-traceroute.nix {};
   earlyoom = handleTestOn ["x86_64-linux"] ./earlyoom.nix {};
@@ -315,6 +318,7 @@ in {
   freetube = discoverTests (import ./freetube.nix);
   freshrss-sqlite = handleTest ./freshrss-sqlite.nix {};
   freshrss-pgsql = handleTest ./freshrss-pgsql.nix {};
+  freshrss-http-auth = handleTest ./freshrss-http-auth.nix {};
   frigate = handleTest ./frigate.nix {};
   frp = handleTest ./frp.nix {};
   frr = handleTest ./frr.nix {};
@@ -340,6 +344,7 @@ in {
   gnome-extensions = handleTest ./gnome-extensions.nix {};
   gnome-flashback = handleTest ./gnome-flashback.nix {};
   gnome-xorg = handleTest ./gnome-xorg.nix {};
+  gns3-server = handleTest ./gns3-server.nix {};
   gnupg = handleTest ./gnupg.nix {};
   go-neb = handleTest ./go-neb.nix {};
   gobgpd = handleTest ./gobgpd.nix {};
@@ -406,7 +411,7 @@ in {
   incus = pkgs.recurseIntoAttrs (handleTest ./incus { inherit handleTestOn; });
   influxdb = handleTest ./influxdb.nix {};
   influxdb2 = handleTest ./influxdb2.nix {};
-  initrd-network-openvpn = handleTest ./initrd-network-openvpn {};
+  initrd-network-openvpn = handleTestOn [ "x86_64-linux" "i686-linux" ] ./initrd-network-openvpn {};
   initrd-network-ssh = handleTest ./initrd-network-ssh {};
   initrd-luks-empty-passphrase = handleTest ./initrd-luks-empty-passphrase.nix {};
   initrdNetwork = handleTest ./initrd-network.nix {};
@@ -541,6 +546,7 @@ in {
   munin = handleTest ./munin.nix {};
   mutableUsers = handleTest ./mutable-users.nix {};
   mxisd = handleTest ./mxisd.nix {};
+  mympd = handleTest ./mympd.nix {};
   mysql = handleTest ./mysql/mysql.nix {};
   mysql-autobackup = handleTest ./mysql/mysql-autobackup.nix {};
   mysql-backup = handleTest ./mysql/mysql-backup.nix {};
@@ -606,6 +612,7 @@ in {
   noto-fonts = handleTest ./noto-fonts.nix {};
   noto-fonts-cjk-qt-default-weight = handleTest ./noto-fonts-cjk-qt-default-weight.nix {};
   novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
+  npmrc = handleTest ./npmrc.nix {};
   nscd = handleTest ./nscd.nix {};
   nsd = handleTest ./nsd.nix {};
   ntfy-sh = handleTest ./ntfy-sh.nix {};
@@ -736,6 +743,7 @@ in {
   rosenpass = handleTest ./rosenpass.nix {};
   rshim = handleTest ./rshim.nix {};
   rspamd = handleTest ./rspamd.nix {};
+  rspamd-trainer = handleTest ./rspamd-trainer.nix {};
   rss2email = handleTest ./rss2email.nix {};
   rstudio-server = handleTest ./rstudio-server.nix {};
   rsyncd = handleTest ./rsyncd.nix {};
@@ -779,6 +787,7 @@ in {
   spark = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./spark {};
   sqlite3-to-mysql = handleTest ./sqlite3-to-mysql.nix {};
   sslh = handleTest ./sslh.nix {};
+  ssh-agent-auth = handleTest ./ssh-agent-auth.nix {};
   ssh-audit = handleTest ./ssh-audit.nix {};
   sssd = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./sssd.nix {};
   sssd-ldap = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./sssd-ldap.nix {};
@@ -829,7 +838,7 @@ in {
   systemd-initrd-vconsole = handleTest ./systemd-initrd-vconsole.nix {};
   systemd-initrd-networkd = handleTest ./systemd-initrd-networkd.nix {};
   systemd-initrd-networkd-ssh = handleTest ./systemd-initrd-networkd-ssh.nix {};
-  systemd-initrd-networkd-openvpn = handleTest ./initrd-network-openvpn { systemdStage1 = true; };
+  systemd-initrd-networkd-openvpn = handleTestOn [ "x86_64-linux" "i686-linux" ] ./initrd-network-openvpn { systemdStage1 = true; };
   systemd-initrd-vlan = handleTest ./systemd-initrd-vlan.nix {};
   systemd-journal = handleTest ./systemd-journal.nix {};
   systemd-machinectl = handleTest ./systemd-machinectl.nix {};
diff --git a/nixpkgs/nixos/tests/anbox.nix b/nixpkgs/nixos/tests/anbox.nix
index dfd6c13d9318..a00116536db7 100644
--- a/nixpkgs/nixos/tests/anbox.nix
+++ b/nixpkgs/nixos/tests/anbox.nix
@@ -15,7 +15,7 @@
     test-support.displayManager.auto.user = "alice";
 
     virtualisation.anbox.enable = true;
-    boot.kernelPackages = pkgs.linuxPackages_5_15;
+    boot.kernelPackages = pkgs.linuxKernel.packages.linux_5_15;
     virtualisation.memorySize = 2500;
   };
 
diff --git a/nixpkgs/nixos/tests/angie-api.nix b/nixpkgs/nixos/tests/angie-api.nix
new file mode 100644
index 000000000000..4c8d6b54247b
--- /dev/null
+++ b/nixpkgs/nixos/tests/angie-api.nix
@@ -0,0 +1,148 @@
+import ./make-test-python.nix ({lib, pkgs, ...}:
+let
+  hosts = ''
+    192.168.2.101 example.com
+    192.168.2.101 api.example.com
+    192.168.2.101 backend.example.com
+  '';
+
+in
+{
+  name = "angie-api";
+  meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
+
+  nodes = {
+    server = { pkgs, ... }: {
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.101"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+        firewall.allowedTCPPorts = [ 80 ];
+      };
+
+      services.nginx = {
+        enable = true;
+        package = pkgs.angie;
+
+        upstreams = {
+          "backend-http" = {
+            servers = { "backend.example.com:8080" = { fail_timeout = "0"; }; };
+            extraConfig = ''
+              zone upstream 256k;
+            '';
+          };
+          "backend-socket" = {
+            servers = { "unix:/run/example.sock" = { fail_timeout = "0"; }; };
+            extraConfig = ''
+              zone upstream 256k;
+            '';
+          };
+        };
+
+        virtualHosts."api.example.com" = {
+          locations."/console/" = {
+            extraConfig = ''
+              api /status/;
+
+              allow 192.168.2.201;
+              deny all;
+            '';
+          };
+        };
+
+        virtualHosts."example.com" = {
+          locations."/test/" = {
+            root = lib.mkForce (pkgs.runCommandLocal "testdir" {} ''
+              mkdir -p "$out/test"
+              cat > "$out/test/index.html" <<EOF
+              <html><body>Hello World!</body></html>
+              EOF
+            '');
+            extraConfig = ''
+              status_zone test_zone;
+
+              allow 192.168.2.201;
+              deny all;
+            '';
+          };
+          locations."/test/locked/" = {
+            extraConfig = ''
+              status_zone test_zone;
+
+              deny all;
+            '';
+          };
+          locations."/test/error/" = {
+            extraConfig = ''
+              status_zone test_zone;
+
+              allow all;
+            '';
+          };
+          locations."/upstream-http/" = {
+            proxyPass = "http://backend-http";
+          };
+          locations."/upstream-socket/" = {
+            proxyPass = "http://backend-socket";
+          };
+        };
+      };
+    };
+
+    client = { pkgs, ... }: {
+      environment.systemPackages = [ pkgs.jq ];
+      networking = {
+        interfaces.eth1 = {
+          ipv4.addresses = [
+            { address = "192.168.2.201"; prefixLength = 24; }
+          ];
+        };
+        extraHosts = hosts;
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+
+    server.wait_for_unit("nginx")
+    server.wait_for_open_port(80)
+
+    # Check Angie version
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.angie.version' | grep '${pkgs.angie.version}'")
+
+    # Check access
+    client.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 200'")
+    server.succeed("curl --verbose --head http://api.example.com/console/ | grep 'HTTP/1.1 403 Forbidden'")
+
+    # Check responses and requests
+    client.succeed("curl --verbose http://example.com/test/")
+    client.succeed("curl --verbose http://example.com/test/locked/")
+    client.succeed("curl --verbose http://example.com/test/locked/")
+    client.succeed("curl --verbose http://example.com/test/error/")
+    client.succeed("curl --verbose http://example.com/test/error/")
+    client.succeed("curl --verbose http://example.com/test/error/")
+    server.succeed("curl --verbose http://example.com/test/")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"200\"' | grep '1'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"403\"' | grep '3'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.responses.\"404\"' | grep '3'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.location_zones.test_zone.requests.total' | grep '7'")
+
+    # Check upstreams
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".state' | grep 'up'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '0'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".state' | grep 'up'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '0'")
+    client.succeed("curl --verbose http://example.com/upstream-http/")
+    client.succeed("curl --verbose http://example.com/upstream-socket/")
+    client.succeed("curl --verbose http://example.com/upstream-socket/")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-http\".peers.\"192.168.2.101:8080\".health.fails' | grep '1'")
+    client.succeed("curl --verbose http://api.example.com/console/ | jq -e '.http.upstreams.\"backend-socket\".peers.\"unix:/run/example.sock\".health.fails' | grep '2'")
+
+    server.shutdown()
+    client.shutdown()
+  '';
+})
diff --git a/nixpkgs/nixos/tests/btrbk-section-order.nix b/nixpkgs/nixos/tests/btrbk-section-order.nix
index 20f1afcf80ec..6082de947f66 100644
--- a/nixpkgs/nixos/tests/btrbk-section-order.nix
+++ b/nixpkgs/nixos/tests/btrbk-section-order.nix
@@ -29,10 +29,12 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
   };
 
   testScript = ''
+    import difflib
     machine.wait_for_unit("basic.target")
-    got = machine.succeed("cat /etc/btrbk/local.conf")
+    got = machine.succeed("cat /etc/btrbk/local.conf").strip()
     expect = """
     backend btrfs-progs-sudo
+    stream_compress no
     timestamp_format long
     target ssh://global-target/
      ssh_user root
@@ -46,6 +48,9 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
        ssh_user root
     """.strip()
     print(got)
+    if got != expect:
+      diff = difflib.unified_diff(expect.splitlines(keepends=True), got.splitlines(keepends=True), fromfile="expected", tofile="got")
+      print("".join(diff))
     assert got == expect
   '';
 })
diff --git a/nixpkgs/nixos/tests/cinnamon-wayland.nix b/nixpkgs/nixos/tests/cinnamon-wayland.nix
index 58dddbbb0866..824a606004cc 100644
--- a/nixpkgs/nixos/tests/cinnamon-wayland.nix
+++ b/nixpkgs/nixos/tests/cinnamon-wayland.nix
@@ -12,6 +12,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       autoLogin.user = nodes.machine.users.users.alice.name;
       defaultSession = "cinnamon-wayland";
     };
+
+    # For the sessionPath subtest.
+    services.xserver.desktopManager.cinnamon.sessionPath = [ pkgs.gnome.gpaste ];
   };
 
   enableOCR = true;
@@ -47,6 +50,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           machine.wait_until_succeeds("journalctl -b --grep 'Loaded applet menu@cinnamon.org'")
           machine.wait_until_succeeds("journalctl -b --grep 'calendar@cinnamon.org: Calendar events supported'")
 
+      with subtest("Check if sessionPath option actually works"):
+          machine.succeed("${eval "imports.gi.GIRepository.Repository.get_search_path\\(\\)"} | grep gpaste")
+
       with subtest("Open Cinnamon Settings"):
           machine.succeed("${su "cinnamon-settings themes >&2 &"}")
           machine.wait_until_succeeds("${eval "global.display.focus_window.wm_class"} | grep -i 'cinnamon-settings'")
diff --git a/nixpkgs/nixos/tests/cinnamon.nix b/nixpkgs/nixos/tests/cinnamon.nix
index 7637b55a2b12..eab907d0b712 100644
--- a/nixpkgs/nixos/tests/cinnamon.nix
+++ b/nixpkgs/nixos/tests/cinnamon.nix
@@ -7,6 +7,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     imports = [ ./common/user-account.nix ];
     services.xserver.enable = true;
     services.xserver.desktopManager.cinnamon.enable = true;
+
+    # For the sessionPath subtest.
+    services.xserver.desktopManager.cinnamon.sessionPath = [ pkgs.gnome.gpaste ];
   };
 
   enableOCR = true;
@@ -49,6 +52,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           machine.wait_until_succeeds("journalctl -b --grep 'Loaded applet menu@cinnamon.org'")
           machine.wait_until_succeeds("journalctl -b --grep 'calendar@cinnamon.org: Calendar events supported'")
 
+      with subtest("Check if sessionPath option actually works"):
+          machine.succeed("${eval "imports.gi.GIRepository.Repository.get_search_path\\(\\)"} | grep gpaste")
+
       with subtest("Open Cinnamon Settings"):
           machine.succeed("${su "cinnamon-settings themes >&2 &"}")
           machine.wait_until_succeeds("${eval "global.display.focus_window.wm_class"} | grep -i 'cinnamon-settings'")
diff --git a/nixpkgs/nixos/tests/code-server.nix b/nixpkgs/nixos/tests/code-server.nix
new file mode 100644
index 000000000000..7d523dfc617e
--- /dev/null
+++ b/nixpkgs/nixos/tests/code-server.nix
@@ -0,0 +1,22 @@
+import ./make-test-python.nix ({pkgs, lib, ...}:
+{
+  name = "code-server";
+
+  nodes = {
+    machine = {pkgs, ...}: {
+      services.code-server = {
+        enable = true;
+        auth = "none";
+      };
+    };
+  };
+
+  testScript = ''
+    start_all()
+    machine.wait_for_unit("code-server.service")
+    machine.wait_for_open_port(4444)
+    machine.succeed("curl -k --fail http://localhost:4444", timeout=10)
+  '';
+
+  meta.maintainers = [ lib.maintainers.drupol ];
+})
diff --git a/nixpkgs/nixos/tests/containers-custom-pkgs.nix b/nixpkgs/nixos/tests/containers-custom-pkgs.nix
index e8740ac63134..57184787c85f 100644
--- a/nixpkgs/nixos/tests/containers-custom-pkgs.nix
+++ b/nixpkgs/nixos/tests/containers-custom-pkgs.nix
@@ -9,7 +9,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: let
 in {
   name = "containers-custom-pkgs";
   meta = {
-    maintainers = with lib.maintainers; [ adisbladis erikarvstedt ];
+    maintainers = with lib.maintainers; [ erikarvstedt ];
   };
 
   nodes.machine = { config, ... }: {
diff --git a/nixpkgs/nixos/tests/dhparams.nix b/nixpkgs/nixos/tests/dhparams.nix
index 021042fafdb1..8d7082c11400 100644
--- a/nixpkgs/nixos/tests/dhparams.nix
+++ b/nixpkgs/nixos/tests/dhparams.nix
@@ -18,6 +18,8 @@ import ./make-test-python.nix {
         systemd.services.foo = {
           description = "Check systemd Ordering";
           wantedBy = [ "multi-user.target" ];
+          before = [ "shutdown.target" ];
+          conflicts = [ "shutdown.target" ];
           unitConfig = {
             # This is to make sure that the dhparams generation of foo occurs
             # before this service so we need this service to start as early as
diff --git a/nixpkgs/nixos/tests/docker-tools.nix b/nixpkgs/nixos/tests/docker-tools.nix
index fcdfa586fd55..90af817e75ed 100644
--- a/nixpkgs/nixos/tests/docker-tools.nix
+++ b/nixpkgs/nixos/tests/docker-tools.nix
@@ -11,7 +11,7 @@ let
       # Rootfs diffs for layers 1 and 2 are identical (and empty)
       layer1 = pkgs.dockerTools.buildImage {  name = "empty";  };
       layer2 = layer1.overrideAttrs (_: { fromImage = layer1; });
-      repeatedRootfsDiffs = pkgs.runCommandNoCC "image-with-links.tar" {
+      repeatedRootfsDiffs = pkgs.runCommand "image-with-links.tar" {
         nativeBuildInputs = [pkgs.jq];
       } ''
         mkdir contents
diff --git a/nixpkgs/nixos/tests/drawterm.nix b/nixpkgs/nixos/tests/drawterm.nix
new file mode 100644
index 000000000000..1d444bb55433
--- /dev/null
+++ b/nixpkgs/nixos/tests/drawterm.nix
@@ -0,0 +1,58 @@
+{ system, pkgs }:
+let
+  tests = {
+    xorg = {
+      node = { pkgs, ... }: {
+        imports = [ ./common/user-account.nix ./common/x11.nix ];
+        services.xserver.enable = true;
+        services.xserver.displayManager.sessionCommands = ''
+          ${pkgs.drawterm}/bin/drawterm -g 1024x768 &
+        '';
+        test-support.displayManager.auto.user = "alice";
+      };
+      systems = [ "x86_64-linux" "aarch64-linux" ];
+    };
+    wayland = {
+      node = { pkgs, ... }: {
+        imports = [ ./common/wayland-cage.nix ];
+        services.cage.program = "${pkgs.drawterm-wayland}/bin/drawterm";
+      };
+      systems = [ "x86_64-linux" ];
+    };
+  };
+
+  mkTest = name: machine:
+    import ./make-test-python.nix ({ pkgs, ... }: {
+      inherit name;
+
+      nodes = { "${name}" = machine; };
+
+      meta = with pkgs.lib.maintainers; {
+        maintainers = [ moody ];
+      };
+
+      enableOCR = true;
+
+      testScript = ''
+        @polling_condition
+        def drawterm_running():
+            machine.succeed("pgrep drawterm")
+
+        start_all()
+
+        machine.wait_for_unit("graphical.target")
+        drawterm_running.wait() # type: ignore[union-attr]
+        machine.wait_for_text("cpu")
+        machine.send_chars("cpu\n")
+        machine.wait_for_text("auth")
+        machine.send_chars("cpu\n")
+        machine.wait_for_text("ending")
+        machine.screenshot("out.png")
+      '';
+
+    });
+  mkTestOn = systems: name: machine:
+    if pkgs.lib.elem system systems then mkTest name machine
+    else { ... }: { };
+in
+builtins.mapAttrs (k: v: mkTestOn v.systems k v.node { inherit system; }) tests
diff --git a/nixpkgs/nixos/tests/ft2-clone.nix b/nixpkgs/nixos/tests/ft2-clone.nix
index a8395d4ebaa6..5476b38c00bd 100644
--- a/nixpkgs/nixos/tests/ft2-clone.nix
+++ b/nixpkgs/nixos/tests/ft2-clone.nix
@@ -4,12 +4,11 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     maintainers = [ fgaz ];
   };
 
-  nodes.machine = { config, pkgs, ... }: {
+  nodes.machine = { pkgs, ... }: {
     imports = [
       ./common/x11.nix
     ];
 
-    services.xserver.enable = true;
     sound.enable = true;
     environment.systemPackages = [ pkgs.ft2-clone ];
   };
@@ -30,4 +29,3 @@ import ./make-test-python.nix ({ pkgs, ... }: {
       machine.screenshot("screen")
     '';
 })
-
diff --git a/nixpkgs/nixos/tests/gitlab.nix b/nixpkgs/nixos/tests/gitlab.nix
index 88cd774f815a..8d3126425311 100644
--- a/nixpkgs/nixos/tests/gitlab.nix
+++ b/nixpkgs/nixos/tests/gitlab.nix
@@ -34,7 +34,7 @@ in {
     gitlab = { ... }: {
       imports = [ common/user-account.nix ];
 
-      virtualisation.memorySize = if pkgs.stdenv.is64bit then 4096 else 2047;
+      virtualisation.memorySize = 6144;
       virtualisation.cores = 4;
       virtualisation.useNixStoreImage = true;
       virtualisation.writableStore = false;
diff --git a/nixpkgs/nixos/tests/gns3-server.nix b/nixpkgs/nixos/tests/gns3-server.nix
new file mode 100644
index 000000000000..e37d751f5f64
--- /dev/null
+++ b/nixpkgs/nixos/tests/gns3-server.nix
@@ -0,0 +1,55 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "gns3-server";
+  meta.maintainers = [ lib.maintainers.anthonyroussel ];
+
+  nodes.machine =
+    { ... }:
+    let
+      tls-cert = pkgs.runCommand "selfSignedCerts" { buildInputs = [ pkgs.openssl ]; } ''
+        openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -days 365 \
+          -subj '/CN=localhost'
+        install -D -t $out key.pem cert.pem
+      '';
+    in {
+      services.gns3-server = {
+        enable = true;
+        auth = {
+          enable = true;
+          user = "user";
+          passwordFile = pkgs.writeText "gns3-auth-password-file" "password";
+        };
+        ssl = {
+          enable = true;
+          certFile = "${tls-cert}/cert.pem";
+          keyFile = "${tls-cert}/key.pem";
+        };
+        dynamips.enable = true;
+        ubridge.enable = true;
+        vpcs.enable = true;
+      };
+
+      security.pki.certificateFiles = [ "${tls-cert}/cert.pem" ];
+    };
+
+  testScript = let
+    createProject = pkgs.writeText "createProject.json" (builtins.toJSON {
+      name = "test_project";
+    });
+  in
+  ''
+    start_all()
+
+    machine.wait_for_unit("gns3-server.service")
+    machine.wait_for_open_port(3080)
+
+    with subtest("server is listening"):
+      machine.succeed("curl -sSfL -u user:password https://localhost:3080/v2/version")
+
+    with subtest("create dummy project"):
+      machine.succeed("curl -sSfL -u user:password https://localhost:3080/v2/projects -d @${createProject}")
+
+    with subtest("logging works"):
+      log_path = "/var/log/gns3/server.log"
+      machine.wait_for_file(log_path)
+  '';
+})
diff --git a/nixpkgs/nixos/tests/google-oslogin/default.nix b/nixpkgs/nixos/tests/google-oslogin/default.nix
index 72c87d7153bd..cd05af6b9ed7 100644
--- a/nixpkgs/nixos/tests/google-oslogin/default.nix
+++ b/nixpkgs/nixos/tests/google-oslogin/default.nix
@@ -12,7 +12,7 @@ let
 in {
   name = "google-oslogin";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ adisbladis flokli ];
+    maintainers = [ flokli ];
   };
 
   nodes = {
@@ -71,4 +71,3 @@ in {
     )
   '';
   })
-
diff --git a/nixpkgs/nixos/tests/incron.nix b/nixpkgs/nixos/tests/incron.nix
index c978ff27dfad..d016360ba0ef 100644
--- a/nixpkgs/nixos/tests/incron.nix
+++ b/nixpkgs/nixos/tests/incron.nix
@@ -13,9 +13,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
       '';
 
       # ensure the directory to be monitored exists before incron is started
-      system.activationScripts.incronTest = ''
-        mkdir /test
-      '';
+      systemd.tmpfiles.settings.incron-test = {
+        "/test".d = { };
+      };
     };
 
   testScript = ''
diff --git a/nixpkgs/nixos/tests/incus/container.nix b/nixpkgs/nixos/tests/incus/container.nix
index 2d3fa49e5bd1..2fa1709c7484 100644
--- a/nixpkgs/nixos/tests/incus/container.nix
+++ b/nixpkgs/nixos/tests/incus/container.nix
@@ -56,6 +56,10 @@ in
           retry(instance_is_up)
         machine.succeed("echo true | incus exec container /run/current-system/sw/bin/bash -")
 
+    with subtest("Container mounts lxcfs overlays"):
+        machine.succeed("incus exec container mount | grep 'lxcfs on /proc/cpuinfo type fuse.lxcfs'")
+        machine.succeed("incus exec container mount | grep 'lxcfs on /proc/meminfo type fuse.lxcfs'")
+
     with subtest("Container CPU limits can be managed"):
         set_container("limits.cpu 1")
         cpuinfo = machine.succeed("incus exec container grep -- -c ^processor /proc/cpuinfo").strip()
diff --git a/nixpkgs/nixos/tests/incus/virtual-machine.nix b/nixpkgs/nixos/tests/incus/virtual-machine.nix
index be5746ef63e2..343a25ca7297 100644
--- a/nixpkgs/nixos/tests/incus/virtual-machine.nix
+++ b/nixpkgs/nixos/tests/incus/virtual-machine.nix
@@ -53,5 +53,8 @@ in
 
     with subtest("lxd-agent is started"):
         machine.succeed("incus exec ${instance-name} systemctl is-active lxd-agent")
+
+    with subtest("lxd-agent has a valid path"):
+        machine.succeed("incus exec ${instance-name} -- bash -c 'true'")
   '';
 })
diff --git a/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix b/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
index 769049905eb8..69db7dd1037f 100644
--- a/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
+++ b/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
@@ -59,18 +59,19 @@ import ../make-test-python.nix ({ lib, ...}:
 
             # This command does not fork to keep the VM in the state where
             # only the initramfs is loaded
-            preLVMCommands =
-            ''
-              /bin/nc -p 1234 -lke /bin/echo TESTVALUE
-            '';
+            preLVMCommands = lib.mkIf (!systemdStage1)
+              ''
+                /bin/nc -p 1234 -lke /bin/echo TESTVALUE
+              '';
 
             network = {
               enable = true;
 
               # Work around udhcpc only getting a lease on eth0
-              postCommands = ''
-                /bin/ip addr add 192.168.1.2/24 dev eth1
-              '';
+              postCommands = lib.mkIf (!systemdStage1)
+                ''
+                  /bin/ip addr add 192.168.1.2/24 dev eth1
+                '';
 
               # Example configuration for OpenVPN
               # This is the main reason for this test
diff --git a/nixpkgs/nixos/tests/installer-systemd-stage-1.nix b/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
index d0c01a779ef1..662017935412 100644
--- a/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
+++ b/nixpkgs/nixos/tests/installer-systemd-stage-1.nix
@@ -22,6 +22,7 @@
     # lvm
     separateBoot
     separateBootFat
+    separateBootZfs
     simple
     simpleLabels
     simpleProvided
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index f7fc168eba8c..d83e49a3e8f7 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -878,6 +878,78 @@ in {
     '';
   };
 
+  # Same as the previous, but with ZFS /boot.
+  separateBootZfs = makeInstallerTest "separateBootZfs" {
+    extraInstallerConfig = {
+      boot.supportedFilesystems = [ "zfs" ];
+    };
+
+    extraConfig = ''
+      # Using by-uuid overrides the default of by-id, and is unique
+      # to the qemu disks, as they don't produce by-id paths for
+      # some reason.
+      boot.zfs.devNodes = "/dev/disk/by-uuid/";
+      networking.hostId = "00000000";
+    '';
+
+    createPartitions = ''
+      machine.succeed(
+          "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+          + " mkpart primary ext2 1M 256MB"   # /boot
+          + " mkpart primary linux-swap 256MB 1280M"
+          + " mkpart primary ext2 1280M -1s", # /
+          "udevadm settle",
+
+          "mkswap /dev/vda2 -L swap",
+          "swapon -L swap",
+
+          "mkfs.ext4 -L nixos /dev/vda3",
+          "mount LABEL=nixos /mnt",
+
+          # Use as many ZFS features as possible to verify that GRUB can handle them
+          "zpool create"
+            " -o compatibility=grub2"
+            " -O utf8only=on"
+            " -O normalization=formD"
+            " -O compression=lz4"      # Activate the lz4_compress feature
+            " -O xattr=sa"
+            " -O acltype=posixacl"
+            " bpool /dev/vda1",
+          "zfs create"
+            " -o recordsize=1M"        # Prepare activating the large_blocks feature
+            " -o mountpoint=legacy"
+            " -o relatime=on"
+            " -o quota=1G"
+            " -o filesystem_limit=100" # Activate the filesystem_limits features
+            " bpool/boot",
+
+          # Snapshotting the top-level dataset would trigger a bug in GRUB2: https://github.com/openzfs/zfs/issues/13873
+          "zfs snapshot bpool/boot@snap-1",                     # Prepare activating the livelist and bookmarks features
+          "zfs clone bpool/boot@snap-1 bpool/test",             # Activate the livelist feature
+          "zfs bookmark bpool/boot@snap-1 bpool/boot#bookmark", # Activate the bookmarks feature
+          "zpool checkpoint bpool",                             # Activate the zpool_checkpoint feature
+          "mkdir -p /mnt/boot",
+          "mount -t zfs bpool/boot /mnt/boot",
+          "touch /mnt/boot/empty",                              # Activate zilsaxattr feature
+          "dd if=/dev/urandom of=/mnt/boot/test bs=1M count=1", # Activate the large_blocks feature
+
+          # Print out all enabled and active ZFS features (and some other stuff)
+          "sync /mnt/boot",
+          "zpool get all bpool >&2",
+
+          # Abort early if GRUB2 doesn't like the disks
+          "grub-probe --target=device /mnt/boot >&2",
+      )
+    '';
+
+    # umount & export bpool before shutdown
+    # this is a fix for "cannot import 'bpool': pool was previously in use from another system."
+    postInstallCommands = ''
+      machine.succeed("umount /mnt/boot")
+      machine.succeed("zpool export bpool")
+    '';
+  };
+
   # zfs on / with swap
   zfsroot = makeInstallerTest "zfs-root" {
     extraInstallerConfig = {
@@ -897,7 +969,7 @@ in {
     createPartitions = ''
       machine.succeed(
           "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
-          + " mkpart primary 1M 100MB"  # bpool
+          + " mkpart primary 1M 100MB"  # /boot
           + " mkpart primary linux-swap 100M 1024M"
           + " mkpart primary 1024M -1s", # rpool
           "udevadm settle",
@@ -909,20 +981,12 @@ in {
           "zfs create -o mountpoint=legacy rpool/root/usr",
           "mkdir /mnt/usr",
           "mount -t zfs rpool/root/usr /mnt/usr",
-          "zpool create -o compatibility=grub2 bpool /dev/vda1",
-          "zfs create -o mountpoint=legacy bpool/boot",
+          "mkfs.vfat -n BOOT /dev/vda1",
           "mkdir /mnt/boot",
-          "mount -t zfs bpool/boot /mnt/boot",
+          "mount LABEL=BOOT /mnt/boot",
           "udevadm settle",
       )
     '';
-
-    # umount & export bpool before shutdown
-    # this is a fix for "cannot import 'bpool': pool was previously in use from another system."
-    postInstallCommands = ''
-      machine.succeed("umount /mnt/boot")
-      machine.succeed("zpool export bpool")
-    '';
   };
 
   # Create two physical LVM partitions combined into one volume group
diff --git a/nixpkgs/nixos/tests/invidious.nix b/nixpkgs/nixos/tests/invidious.nix
index 701e8e5e7a3f..e31cd87f6a00 100644
--- a/nixpkgs/nixos/tests/invidious.nix
+++ b/nixpkgs/nixos/tests/invidious.nix
@@ -5,48 +5,72 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     maintainers = [ sbruder ];
   };
 
-  nodes.machine = { config, lib, pkgs, ... }: {
-    services.invidious = {
-      enable = true;
+  nodes = {
+    postgres-tcp = { config, pkgs, ... }: {
+      services.postgresql = {
+        enable = true;
+        initialScript = pkgs.writeText "init-postgres-with-password" ''
+          CREATE USER invidious WITH PASSWORD 'correct horse battery staple';
+          CREATE DATABASE invidious WITH OWNER invidious;
+        '';
+        enableTCPIP = true;
+        authentication = ''
+          host invidious invidious samenet scram-sha-256
+        '';
+      };
+      networking.firewall.allowedTCPPorts = [ config.services.postgresql.port ];
     };
+    machine = { config, lib, pkgs, ... }: {
+      services.invidious = {
+        enable = true;
+      };
 
-    specialisation = {
-      nginx.configuration = {
-        services.invidious = {
-          nginx.enable = true;
-          domain = "invidious.example.com";
-        };
-        services.nginx.virtualHosts."invidious.example.com" = {
-          forceSSL = false;
-          enableACME = false;
+      specialisation = {
+        nginx.configuration = {
+          services.invidious = {
+            nginx.enable = true;
+            domain = "invidious.example.com";
+          };
+          services.nginx.virtualHosts."invidious.example.com" = {
+            forceSSL = false;
+            enableACME = false;
+          };
+          networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
         };
-        networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
-      };
-      postgres-tcp.configuration = {
-        services.invidious = {
-          database = {
-            createLocally = false;
-            host = "127.0.0.1";
-            passwordFile = toString (pkgs.writeText "database-password" "correct horse battery staple");
+        nginx-scale.configuration = {
+          services.invidious = {
+            nginx.enable = true;
+            domain = "invidious.example.com";
+            serviceScale = 3;
+          };
+          services.nginx.virtualHosts."invidious.example.com" = {
+            forceSSL = false;
+            enableACME = false;
           };
+          networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
         };
-        # Normally not needed because when connecting to postgres over TCP/IP
-        # the database is most likely on another host.
-        systemd.services.invidious = {
-          after = [ "postgresql.service" ];
-          requires = [ "postgresql.service" ];
+        nginx-scale-ytproxy.configuration = {
+          services.invidious = {
+            nginx.enable = true;
+            http3-ytproxy.enable = true;
+            domain = "invidious.example.com";
+            serviceScale = 3;
+          };
+          services.nginx.virtualHosts."invidious.example.com" = {
+            forceSSL = false;
+            enableACME = false;
+          };
+          networking.hosts."127.0.0.1" = [ "invidious.example.com" ];
         };
-        services.postgresql =
-          let
-            inherit (config.services.invidious.settings.db) dbname user;
-          in
-          {
-            enable = true;
-            initialScript = pkgs.writeText "init-postgres-with-password" ''
-              CREATE USER kemal WITH PASSWORD 'correct horse battery staple';
-              CREATE DATABASE invidious OWNER kemal;
-            '';
+        postgres-tcp.configuration = {
+          services.invidious = {
+            database = {
+              createLocally = false;
+              host = "postgres-tcp";
+              passwordFile = toString (pkgs.writeText "database-password" "correct horse battery staple");
+            };
           };
+        };
       };
     };
   };
@@ -63,6 +87,9 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     url = "http://localhost:${toString nodes.machine.config.services.invidious.port}"
     port = ${toString nodes.machine.config.services.invidious.port}
 
+    # start postgres vm now
+    postgres_tcp.start()
+
     machine.wait_for_open_port(port)
     curl_assert_status_code(f"{url}/search", 200)
 
@@ -70,9 +97,26 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     machine.wait_for_open_port(80)
     curl_assert_status_code("http://invidious.example.com/search", 200)
 
-    # Remove the state so the `initialScript` gets run
-    machine.succeed("systemctl stop postgresql")
-    machine.succeed("rm -r /var/lib/postgresql")
+    activate_specialisation("nginx-scale")
+    machine.wait_for_open_port(80)
+    # this depends on nginx round-robin behaviour for the upstream servers
+    curl_assert_status_code("http://invidious.example.com/search", 200)
+    curl_assert_status_code("http://invidious.example.com/search", 200)
+    curl_assert_status_code("http://invidious.example.com/search", 200)
+    machine.succeed("journalctl -eu invidious.service | grep -o '200 GET /search'")
+    machine.succeed("journalctl -eu invidious-1.service | grep -o '200 GET /search'")
+    machine.succeed("journalctl -eu invidious-2.service | grep -o '200 GET /search'")
+
+    activate_specialisation("nginx-scale-ytproxy")
+    machine.wait_for_unit("http3-ytproxy.service")
+    machine.wait_for_open_port(80)
+    machine.wait_until_succeeds("ls /run/http3-ytproxy/socket/http-proxy.sock")
+    curl_assert_status_code("http://invidious.example.com/search", 200)
+    # this should error out as no internet connectivity is available in the test
+    curl_assert_status_code("http://invidious.example.com/vi/dQw4w9WgXcQ/mqdefault.jpg", 502)
+    machine.succeed("journalctl -eu http3-ytproxy.service | grep -o 'dQw4w9WgXcQ'")
+
+    postgres_tcp.wait_for_unit("postgresql.service")
     activate_specialisation("postgres-tcp")
     machine.wait_for_open_port(port)
     curl_assert_status_code(f"{url}/search", 200)
diff --git a/nixpkgs/nixos/tests/iscsi-root.nix b/nixpkgs/nixos/tests/iscsi-root.nix
index eb0719edc379..0d7c48464eec 100644
--- a/nixpkgs/nixos/tests/iscsi-root.nix
+++ b/nixpkgs/nixos/tests/iscsi-root.nix
@@ -7,8 +7,8 @@ import ./make-test-python.nix (
       {
         name = "iscsi";
         meta = {
-          maintainers = pkgs.lib.teams.deshaw.members
-          ++ (with pkgs.lib.maintainers; [ ajs124 ]);
+          maintainers = lib.teams.deshaw.members
+            ++ lib.teams.helsinki-systems.members;
         };
 
         nodes = {
diff --git a/nixpkgs/nixos/tests/livebook-service.nix b/nixpkgs/nixos/tests/livebook-service.nix
index 9397e3cb75ff..56b4eb932f34 100644
--- a/nixpkgs/nixos/tests/livebook-service.nix
+++ b/nixpkgs/nixos/tests/livebook-service.nix
@@ -11,7 +11,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
         enableUserService = true;
         port = 20123;
         environmentFile = pkgs.writeText "livebook.env" ''
-          LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+          LIVEBOOK_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
         '';
         options = {
           cookie = "chocolate chip";
@@ -22,7 +22,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
 
   testScript = { nodes, ... }:
     let
-      user = nodes.machine.config.users.users.alice;
+      user = nodes.machine.users.users.alice;
       sudo = lib.concatStringsSep " " [
         "XDG_RUNTIME_DIR=/run/user/${toString user.uid}"
         "sudo"
diff --git a/nixpkgs/nixos/tests/lvm2/systemd-stage-1.nix b/nixpkgs/nixos/tests/lvm2/systemd-stage-1.nix
index b581f2b23507..1c95aadfcb3f 100644
--- a/nixpkgs/nixos/tests/lvm2/systemd-stage-1.nix
+++ b/nixpkgs/nixos/tests/lvm2/systemd-stage-1.nix
@@ -54,9 +54,9 @@
     '';
   }.${flavour};
 
-in import ../make-test-python.nix ({ pkgs, ... }: {
+in import ../make-test-python.nix ({ pkgs, lib, ... }: {
   name = "lvm2-${flavour}-systemd-stage-1";
-  meta.maintainers = with pkgs.lib.maintainers; [ das_j ];
+  meta.maintainers = lib.teams.helsinki-systems.members;
 
   nodes.machine = { pkgs, lib, ... }: {
     imports = [ extraConfig ];
diff --git a/nixpkgs/nixos/tests/lvm2/thinpool.nix b/nixpkgs/nixos/tests/lvm2/thinpool.nix
index 14781a8a6045..f49c8980613c 100644
--- a/nixpkgs/nixos/tests/lvm2/thinpool.nix
+++ b/nixpkgs/nixos/tests/lvm2/thinpool.nix
@@ -1,7 +1,7 @@
 { kernelPackages ? null }:
 import ../make-test-python.nix ({ pkgs, lib, ... }: {
   name = "lvm2-thinpool";
-  meta.maintainers = with pkgs.lib.maintainers; [ ajs124 ];
+  meta.maintainers = lib.teams.helsinki-systems.members;
 
   nodes.machine = { pkgs, lib, ... }: {
     virtualisation.emptyDiskImages = [ 4096 ];
diff --git a/nixpkgs/nixos/tests/lvm2/vdo.nix b/nixpkgs/nixos/tests/lvm2/vdo.nix
index 5b014c2f7222..75c1fc094e97 100644
--- a/nixpkgs/nixos/tests/lvm2/vdo.nix
+++ b/nixpkgs/nixos/tests/lvm2/vdo.nix
@@ -1,7 +1,7 @@
 { kernelPackages ? null }:
-import ../make-test-python.nix ({ pkgs, ... }: {
+import ../make-test-python.nix ({ pkgs, lib, ... }: {
   name = "lvm2-vdo";
-  meta.maintainers = with pkgs.lib.maintainers; [ ajs124 ];
+  meta.maintainers = lib.teams.helsinki-systems.members;
 
   nodes.machine = { pkgs, lib, ... }: {
     # Minimum required size for VDO volume: 5063921664 bytes
diff --git a/nixpkgs/nixos/tests/mate.nix b/nixpkgs/nixos/tests/mate.nix
index 78ba59c5fc20..48582e18d520 100644
--- a/nixpkgs/nixos/tests/mate.nix
+++ b/nixpkgs/nixos/tests/mate.nix
@@ -27,9 +27,12 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     hardware.pulseaudio.enable = true;
   };
 
+  enableOCR = true;
+
   testScript = { nodes, ... }:
     let
       user = nodes.machine.users.users.alice;
+      env = "DISPLAY=:0.0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${toString user.uid}/bus";
     in
     ''
       with subtest("Wait for login"):
@@ -48,11 +51,31 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           machine.wait_for_window("Bottom Panel")
           machine.wait_until_succeeds("pgrep caja")
           machine.wait_for_window("Caja")
+          machine.wait_for_text('(Applications|Places|System)')
+          machine.wait_for_text('(Computer|Home|Trash)')
+
+      with subtest("Lock the screen"):
+          machine.wait_until_succeeds("su - ${user.name} -c '${env} mate-screensaver-command -q' | grep 'The screensaver is inactive'")
+          machine.succeed("su - ${user.name} -c '${env} mate-screensaver-command -l >&2 &'")
+          machine.wait_until_succeeds("su - ${user.name} -c '${env} mate-screensaver-command -q' | grep 'The screensaver is active'")
+          machine.sleep(2)
+          machine.send_chars("${user.password}", delay=0.2)
+          machine.wait_for_text("${user.description}")
+          machine.screenshot("screensaver")
+          machine.send_chars("\n")
+          machine.wait_until_succeeds("su - ${user.name} -c '${env} mate-screensaver-command -q' | grep 'The screensaver is inactive'")
+
+      with subtest("Open MATE control center"):
+          machine.succeed("su - ${user.name} -c '${env} mate-control-center >&2 &'")
+          machine.wait_for_window("Control Center")
+          machine.wait_for_text('(Groups|Administration|Hardware)')
 
       with subtest("Open MATE terminal"):
-          machine.succeed("su - ${user.name} -c 'DISPLAY=:0.0 mate-terminal >&2 &'")
+          machine.succeed("su - ${user.name} -c '${env} mate-terminal >&2 &'")
           machine.wait_for_window("Terminal")
-          machine.sleep(20)
+
+      with subtest("Check if MATE has ever coredumped"):
+          machine.fail("coredumpctl --json=short | grep -E 'mate|marco|caja'")
           machine.screenshot("screen")
     '';
 })
diff --git a/nixpkgs/nixos/tests/munin.nix b/nixpkgs/nixos/tests/munin.nix
index 4ec17e0339df..e371b2dffa6b 100644
--- a/nixpkgs/nixos/tests/munin.nix
+++ b/nixpkgs/nixos/tests/munin.nix
@@ -37,8 +37,10 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     with subtest("ensure munin-node starts and listens on 4949"):
         one.wait_for_unit("munin-node.service")
         one.wait_for_open_port(4949)
+
     with subtest("ensure munin-cron output is correct"):
         one.wait_for_file("/var/lib/munin/one/one-uptime-uptime-g.rrd")
         one.wait_for_file("/var/www/munin/one/index.html")
+        one.wait_for_file("/var/www/munin/one/one/diskstat_iops_vda-day.png", timeout=60)
   '';
 })
diff --git a/nixpkgs/nixos/tests/musescore.nix b/nixpkgs/nixos/tests/musescore.nix
index 6aeb0558a49d..0720631ed284 100644
--- a/nixpkgs/nixos/tests/musescore.nix
+++ b/nixpkgs/nixos/tests/musescore.nix
@@ -63,14 +63,11 @@ in
 
     machine.send_key("tab")
     machine.send_key("tab")
-    machine.send_key("tab")
-    machine.send_key("tab")
-    machine.send_key("right")
-    machine.send_key("right")
     machine.send_key("ret")
 
-    machine.sleep(1)
+    machine.sleep(2)
 
+    machine.send_key("tab")
     # Type the beginning of https://de.wikipedia.org/wiki/Alle_meine_Entchen
     machine.send_chars("cdef6gg5aaaa7g")
     machine.sleep(1)
diff --git a/nixpkgs/nixos/tests/mympd.nix b/nixpkgs/nixos/tests/mympd.nix
new file mode 100644
index 000000000000..ac6a896966e6
--- /dev/null
+++ b/nixpkgs/nixos/tests/mympd.nix
@@ -0,0 +1,27 @@
+import ./make-test-python.nix ({pkgs, lib, ... }: {
+  name = "mympd";
+
+  nodes.mympd = {
+    services.mympd = {
+      enable = true;
+      settings = {
+        http_port = 8081;
+      };
+    };
+
+    services.mpd.enable = true;
+  };
+
+  testScript = ''
+    start_all();
+    machine.wait_for_unit("mympd.service");
+
+    # Ensure that mympd can connect to mpd
+    machine.wait_until_succeeds(
+      "journalctl -eu mympd -o cat | grep 'Connected to MPD'"
+    )
+
+    # Ensure that the web server is working
+    machine.succeed("curl http://localhost:8081 --compressed | grep -o myMPD")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/mysql/mariadb-galera.nix b/nixpkgs/nixos/tests/mysql/mariadb-galera.nix
index c9962f49c02f..7455abbce5fb 100644
--- a/nixpkgs/nixos/tests/mysql/mariadb-galera.nix
+++ b/nixpkgs/nixos/tests/mysql/mariadb-galera.nix
@@ -17,8 +17,8 @@ let
     galeraPackage ? pkgs.mariadb-galera
   }: makeTest {
     name = "${name}-galera-mariabackup";
-    meta = with pkgs.lib.maintainers; {
-      maintainers = [ izorkin ajs124 das_j ];
+    meta = {
+      maintainers = with lib.maintainers; [ izorkin ] ++ lib.teams.helsinki-systems.members;
     };
 
     # The test creates a Galera cluster with 3 nodes and is checking if mariabackup-based SST works. The cluster is tested by creating a DB and an empty table on one node,
diff --git a/nixpkgs/nixos/tests/mysql/mysql-replication.nix b/nixpkgs/nixos/tests/mysql/mysql-replication.nix
index 8f1695eb97e2..83da1e7b6cb8 100644
--- a/nixpkgs/nixos/tests/mysql/mysql-replication.nix
+++ b/nixpkgs/nixos/tests/mysql/mysql-replication.nix
@@ -18,8 +18,8 @@ let
     name ? mkTestName package,
   }: makeTest {
     name = "${name}-replication";
-    meta = with pkgs.lib.maintainers; {
-      maintainers = [ ajs124 das_j ];
+    meta = {
+      maintainers = lib.teams.helsinki-systems.members;
     };
 
     nodes = {
diff --git a/nixpkgs/nixos/tests/mysql/mysql.nix b/nixpkgs/nixos/tests/mysql/mysql.nix
index 3e059cad09e9..0a61f9d38fe2 100644
--- a/nixpkgs/nixos/tests/mysql/mysql.nix
+++ b/nixpkgs/nixos/tests/mysql/mysql.nix
@@ -18,8 +18,8 @@ let
     hasRocksDB ? pkgs.stdenv.hostPlatform.is64bit
   }: makeTest {
     inherit name;
-    meta = with lib.maintainers; {
-      maintainers = [ ajs124 das_j ];
+    meta = {
+      maintainers = lib.teams.helsinki-systems.members;
     };
 
     nodes = {
diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix
index ab1d8353dba0..428fe0aa10db 100644
--- a/nixpkgs/nixos/tests/nextcloud/basic.nix
+++ b/nixpkgs/nixos/tests/nextcloud/basic.nix
@@ -13,10 +13,12 @@ in {
     # The only thing the client needs to do is download a file.
     client = { ... }: {
       services.davfs2.enable = true;
-      system.activationScripts.davfs2-secrets = ''
-        echo "http://nextcloud/remote.php/dav/files/${adminuser} ${adminuser} ${adminpass}" > /tmp/davfs2-secrets
-        chmod 600 /tmp/davfs2-secrets
-      '';
+      systemd.tmpfiles.settings.nextcloud = {
+        "/tmp/davfs2-secrets"."f+" = {
+          mode = "0600";
+          argument = "http://nextcloud/remote.php/dav/files/${adminuser} ${adminuser} ${adminpass}";
+        };
+      };
       virtualisation.fileSystems = {
         "/mnt/dav" = {
           device = "http://nextcloud/remote.php/dav/files/${adminuser}";
diff --git a/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix b/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
index 586bf50fd939..d95af8a89d07 100644
--- a/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
+++ b/nixpkgs/nixos/tests/nextcloud/with-postgresql-and-redis.nix
@@ -32,7 +32,6 @@ in {
           adminpassFile = toString (pkgs.writeText "admin-pass-file" ''
             ${adminpass}
           '');
-          trustedProxies = [ "::1" ];
         };
         notify_push = {
           enable = true;
@@ -42,6 +41,7 @@ in {
         extraApps = {
           inherit (pkgs."nextcloud${lib.versions.major config.services.nextcloud.package.version}Packages".apps) notify_push;
         };
+        extraOptions.trusted_proxies = [ "::1" ];
       };
 
       services.redis.servers."nextcloud".enable = true;
diff --git a/nixpkgs/nixos/tests/nginx-http3.nix b/nixpkgs/nixos/tests/nginx-http3.nix
index fc9f31037f98..22f7f61f10ce 100644
--- a/nixpkgs/nixos/tests/nginx-http3.nix
+++ b/nixpkgs/nixos/tests/nginx-http3.nix
@@ -1,97 +1,113 @@
-import ./make-test-python.nix ({lib, pkgs, ...}:
+{ system ? builtins.currentSystem,
+  config ? {},
+  pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+
 let
   hosts = ''
     192.168.2.101 acme.test
   '';
 
 in
-{
-  name = "nginx-http3";
-  meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
-
-  nodes = {
-    server = { pkgs, ... }: {
-      networking = {
-        interfaces.eth1 = {
-          ipv4.addresses = [
-            { address = "192.168.2.101"; prefixLength = 24; }
-          ];
-        };
-        extraHosts = hosts;
-        firewall.allowedTCPPorts = [ 443 ];
-        firewall.allowedUDPPorts = [ 443 ];
-      };
-
-      security.pki.certificates = [
-        (builtins.readFile ./common/acme/server/ca.cert.pem)
-      ];
-
-      services.nginx = {
-        enable = true;
-        package = pkgs.nginxQuic;
-
-        virtualHosts."acme.test" = {
-          onlySSL = true;
-          sslCertificate = ./common/acme/server/acme.test.cert.pem;
-          sslCertificateKey = ./common/acme/server/acme.test.key.pem;
-          http2 = true;
-          http3 = true;
-          http3_hq = false;
-          quic = true;
-          reuseport = true;
-          root = lib.mkForce (pkgs.runCommandLocal "testdir" {} ''
-            mkdir "$out"
-            cat > "$out/index.html" <<EOF
-            <html><body>Hello World!</body></html>
-            EOF
-            cat > "$out/example.txt" <<EOF
-            Check http3 protocol.
-            EOF
-          '');
-        };
-      };
-    };
-
-    client = { pkgs, ... }: {
-      environment.systemPackages = [ pkgs.curlHTTP3 ];
-      networking = {
-        interfaces.eth1 = {
-          ipv4.addresses = [
-            { address = "192.168.2.201"; prefixLength = 24; }
-          ];
-        };
-        extraHosts = hosts;
-      };
 
-      security.pki.certificates = [
-        (builtins.readFile ./common/acme/server/ca.cert.pem)
-      ];
-    };
-  };
+builtins.listToAttrs (
+  builtins.map
+    (nginxPackage:
+      {
+        name = pkgs.lib.getName nginxPackage;
+        value = makeTest {
+          name = "nginx-http3-${pkgs.lib.getName nginxPackage}";
+          meta.maintainers = with pkgs.lib.maintainers; [ izorkin ];
 
-  testScript = ''
-    start_all()
+          nodes = {
+            server = { lib, pkgs, ... }: {
+              networking = {
+                interfaces.eth1 = {
+                  ipv4.addresses = [
+                    { address = "192.168.2.101"; prefixLength = 24; }
+                  ];
+                };
+                extraHosts = hosts;
+                firewall.allowedTCPPorts = [ 443 ];
+                firewall.allowedUDPPorts = [ 443 ];
+              };
 
-    server.wait_for_unit("nginx")
-    server.wait_for_open_port(443)
+              security.pki.certificates = [
+                (builtins.readFile ./common/acme/server/ca.cert.pem)
+              ];
 
-    # Check http connections
-    client.succeed("curl --verbose --http3-only https://acme.test | grep 'Hello World!'")
+              services.nginx = {
+                enable = true;
+                package = nginxPackage;
 
-    # Check downloadings
-    client.succeed("curl --verbose --http3-only https://acme.test/example.txt --output /tmp/example.txt")
-    client.succeed("cat /tmp/example.txt | grep 'Check http3 protocol.'")
+                virtualHosts."acme.test" = {
+                  onlySSL = true;
+                  sslCertificate = ./common/acme/server/acme.test.cert.pem;
+                  sslCertificateKey = ./common/acme/server/acme.test.key.pem;
+                  http2 = true;
+                  http3 = true;
+                  http3_hq = false;
+                  quic = true;
+                  reuseport = true;
+                  root = lib.mkForce (pkgs.runCommandLocal "testdir" {} ''
+                    mkdir "$out"
+                    cat > "$out/index.html" <<EOF
+                    <html><body>Hello World!</body></html>
+                    EOF
+                    cat > "$out/example.txt" <<EOF
+                    Check http3 protocol.
+                    EOF
+                  '');
+                };
+              };
+            };
 
-    # Check header reading
-    client.succeed("curl --verbose --http3-only --head https://acme.test | grep 'content-type'")
-    client.succeed("curl --verbose --http3-only --head https://acme.test | grep 'HTTP/3 200'")
-    client.succeed("curl --verbose --http3-only --head https://acme.test/error | grep 'HTTP/3 404'")
+            client = { pkgs, ... }: {
+              environment.systemPackages = [ pkgs.curlHTTP3 ];
+              networking = {
+                interfaces.eth1 = {
+                  ipv4.addresses = [
+                    { address = "192.168.2.201"; prefixLength = 24; }
+                  ];
+                };
+                extraHosts = hosts;
+              };
 
-    # Check change User-Agent
-    client.succeed("curl --verbose --http3-only --user-agent 'Curl test 3.0' https://acme.test")
-    server.succeed("cat /var/log/nginx/access.log | grep 'Curl test 3.0'")
+              security.pki.certificates = [
+                (builtins.readFile ./common/acme/server/ca.cert.pem)
+              ];
+            };
+          };
 
-    server.shutdown()
-    client.shutdown()
-  '';
-})
+          testScript = ''
+            start_all()
+
+            server.wait_for_unit("nginx")
+            server.wait_for_open_port(443)
+
+            # Check http connections
+            client.succeed("curl --verbose --http3-only https://acme.test | grep 'Hello World!'")
+
+            # Check downloadings
+            client.succeed("curl --verbose --http3-only https://acme.test/example.txt --output /tmp/example.txt")
+            client.succeed("cat /tmp/example.txt | grep 'Check http3 protocol.'")
+
+            # Check header reading
+            client.succeed("curl --verbose --http3-only --head https://acme.test | grep 'content-type'")
+            client.succeed("curl --verbose --http3-only --head https://acme.test | grep 'HTTP/3 200'")
+            client.succeed("curl --verbose --http3-only --head https://acme.test/error | grep 'HTTP/3 404'")
+
+            # Check change User-Agent
+            client.succeed("curl --verbose --http3-only --user-agent 'Curl test 3.0' https://acme.test")
+            server.succeed("cat /var/log/nginx/access.log | grep 'Curl test 3.0'")
+
+            server.shutdown()
+            client.shutdown()
+          '';
+        };
+      }
+    )
+    [ pkgs.angieQuic pkgs.nginxQuic ]
+)
diff --git a/nixpkgs/nixos/tests/nginx-variants.nix b/nixpkgs/nixos/tests/nginx-variants.nix
index 0faa0127669d..8c24052aacce 100644
--- a/nixpkgs/nixos/tests/nginx-variants.nix
+++ b/nixpkgs/nixos/tests/nginx-variants.nix
@@ -7,17 +7,17 @@ with import ../lib/testing-python.nix { inherit system pkgs; };
 
 builtins.listToAttrs (
   builtins.map
-    (nginxName:
+    (nginxPackage:
       {
-        name = nginxName;
+        name = pkgs.lib.getName nginxPackage;
         value = makeTest {
-          name = "nginx-variant-${nginxName}";
+          name = "nginx-variant-${pkgs.lib.getName nginxPackage}";
 
           nodes.machine = { pkgs, ... }: {
             services.nginx = {
               enable = true;
               virtualHosts.localhost.locations."/".return = "200 'foo'";
-              package = pkgs."${nginxName}";
+              package = nginxPackage;
             };
           };
 
@@ -29,5 +29,5 @@ builtins.listToAttrs (
         };
       }
     )
-    [ "nginxStable" "nginxMainline" "nginxQuic" "nginxShibboleth" "openresty" "tengine" ]
+    [ pkgs.angie pkgs.angieQuic pkgs.nginxStable pkgs.nginxMainline pkgs.nginxQuic pkgs.nginxShibboleth pkgs.openresty pkgs.tengine ]
 )
diff --git a/nixpkgs/nixos/tests/nitter.nix b/nixpkgs/nixos/tests/nitter.nix
index 8bc55ba8c69f..114f1aac7c7a 100644
--- a/nixpkgs/nixos/tests/nitter.nix
+++ b/nixpkgs/nixos/tests/nitter.nix
@@ -1,13 +1,28 @@
 import ./make-test-python.nix ({ pkgs, ... }:
 
+let
+  # In a real deployment this should naturally not common from the nix store
+  # and be seeded via agenix or as a non-nix managed file.
+  #
+  # These credentials are from the nitter wiki and are expired. We must provide
+  # credentials in the correct format, otherwise nitter fails to start. They
+  # must not be valid, as unauthorized errors are handled gracefully.
+  guestAccountFile = pkgs.writeText "guest_accounts.jsonl" ''
+    {"oauth_token":"1719213587296620928-BsXY2RIJEw7fjxoNwbBemgjJhueK0m","oauth_token_secret":"N0WB0xhL4ng6WTN44aZO82SUJjz7ssI3hHez2CUhTiYqy"}
+  '';
+in
 {
   name = "nitter";
   meta.maintainers = with pkgs.lib.maintainers; [ erdnaxe ];
 
   nodes.machine = {
-    services.nitter.enable = true;
-    # Test CAP_NET_BIND_SERVICE
-    services.nitter.server.port = 80;
+    services.nitter = {
+      enable = true;
+      # Test CAP_NET_BIND_SERVICE
+      server.port = 80;
+      # Provide dummy guest accounts
+      guestAccounts = guestAccountFile;
+    };
   };
 
   testScript = ''
diff --git a/nixpkgs/nixos/tests/nixos-rebuild-specialisations.nix b/nixpkgs/nixos/tests/nixos-rebuild-specialisations.nix
index 444ff7a3b977..9192b8a8a030 100644
--- a/nixpkgs/nixos/tests/nixos-rebuild-specialisations.nix
+++ b/nixpkgs/nixos/tests/nixos-rebuild-specialisations.nix
@@ -23,7 +23,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
 
       virtualisation = {
         cores = 2;
-        memorySize = 2048;
+        memorySize = 4096;
       };
     };
   };
diff --git a/nixpkgs/nixos/tests/npmrc.nix b/nixpkgs/nixos/tests/npmrc.nix
new file mode 100644
index 000000000000..dbf24d372feb
--- /dev/null
+++ b/nixpkgs/nixos/tests/npmrc.nix
@@ -0,0 +1,22 @@
+import ./make-test-python.nix ({ ... }:
+let
+  machineName = "machine";
+  settingName = "prefix";
+  settingValue = "/some/path";
+in
+{
+  name = "npmrc";
+
+  nodes."${machineName}".programs.npm = {
+    enable = true;
+    npmrc = ''
+      ${settingName} = ${settingValue}
+    '';
+  };
+
+  testScript = ''
+    ${machineName}.start()
+
+    assert ${machineName}.succeed("npm config get ${settingName}") == "${settingValue}\n"
+  '';
+})
diff --git a/nixpkgs/nixos/tests/oci-containers.nix b/nixpkgs/nixos/tests/oci-containers.nix
index 1afa9df36dfa..205ce623d089 100644
--- a/nixpkgs/nixos/tests/oci-containers.nix
+++ b/nixpkgs/nixos/tests/oci-containers.nix
@@ -12,7 +12,7 @@ let
     name = "oci-containers-${backend}";
 
     meta.maintainers = lib.teams.serokell.members
-                       ++ (with lib.maintainers; [ adisbladis benley mkaito ]);
+                       ++ (with lib.maintainers; [ benley mkaito ]);
 
     nodes = {
       ${backend} = { pkgs, ... }: {
diff --git a/nixpkgs/nixos/tests/opentabletdriver.nix b/nixpkgs/nixos/tests/opentabletdriver.nix
index b7583f6dd264..a71a007c4110 100644
--- a/nixpkgs/nixos/tests/opentabletdriver.nix
+++ b/nixpkgs/nixos/tests/opentabletdriver.nix
@@ -20,9 +20,11 @@ in {
     ''
       machine.start()
       machine.wait_for_x()
+
+      machine.wait_for_unit('graphical.target')
       machine.wait_for_unit("opentabletdriver.service", "${testUser}")
 
-      machine.succeed("cat /etc/udev/rules.d/99-opentabletdriver.rules")
+      machine.succeed("cat /etc/udev/rules.d/70-opentabletdriver.rules")
       # Will fail if service is not running
       # Needs to run as the same user that started the service
       machine.succeed("su - ${testUser} -c 'otd detect'")
diff --git a/nixpkgs/nixos/tests/prometheus-exporters.nix b/nixpkgs/nixos/tests/prometheus-exporters.nix
index 7840130d4a36..53e6626c0e32 100644
--- a/nixpkgs/nixos/tests/prometheus-exporters.nix
+++ b/nixpkgs/nixos/tests/prometheus-exporters.nix
@@ -431,8 +431,8 @@ let
     };
 
     kea = let
-      controlSocketPathV4 = "/run/kea-dhcp4/dhcp4.sock";
-      controlSocketPathV6 = "/run/kea-dhcp6/dhcp6.sock";
+      controlSocketPathV4 = "/run/kea/dhcp4.sock";
+      controlSocketPathV6 = "/run/kea/dhcp6.sock";
     in
     {
       exporterConfig = {
@@ -806,6 +806,7 @@ let
     nginx = {
       exporterConfig = {
         enable = true;
+        constLabels = [ "foo=bar" ];
       };
       metricProvider = {
         services.nginx = {
@@ -818,7 +819,7 @@ let
         wait_for_unit("nginx.service")
         wait_for_unit("prometheus-nginx-exporter.service")
         wait_for_open_port(9113)
-        succeed("curl -sSf http://localhost:9113/metrics | grep 'nginx_up 1'")
+        succeed("curl -sSf http://localhost:9113/metrics | grep 'nginx_up{foo=\"bar\"} 1'")
       '';
     };
 
@@ -1052,6 +1053,50 @@ let
       '';
     };
 
+    ping = {
+      exporterConfig = {
+        enable = true;
+
+        settings = {
+          targets = [ {
+            "localhost" = {
+              alias = "local machine";
+              env = "prod";
+              type = "domain";
+            };
+          } {
+            "127.0.0.1" = {
+              alias = "local machine";
+              type = "v4";
+            };
+          } {
+            "::1" = {
+              alias = "local machine";
+              type = "v6";
+            };
+          } {
+            "google.com" = {};
+          } ];
+          dns = {};
+          ping = {
+            interval = "2s";
+            timeout = "3s";
+            history-size = 42;
+            payload-size = 56;
+          };
+          log = {
+            level = "warn";
+          };
+        };
+      };
+
+      exporterTest = ''
+        wait_for_unit("prometheus-ping-exporter.service")
+        wait_for_open_port(9427)
+        succeed("curl -sSf http://localhost:9427/metrics | grep 'ping_up{.*} 1'")
+      '';
+    };
+
     postfix = {
       exporterConfig = {
         enable = true;
diff --git a/nixpkgs/nixos/tests/rspamd-trainer.nix b/nixpkgs/nixos/tests/rspamd-trainer.nix
new file mode 100644
index 000000000000..9c157903d24b
--- /dev/null
+++ b/nixpkgs/nixos/tests/rspamd-trainer.nix
@@ -0,0 +1,155 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+let
+  certs = import ./common/acme/server/snakeoil-certs.nix;
+  domain = certs.domain;
+in {
+  name = "rspamd-trainer";
+  meta = with pkgs.lib.maintainers; { maintainers = [ onny ]; };
+
+  nodes = {
+    machine = { options, config, ... }: {
+
+      security.pki.certificateFiles = [
+        certs.ca.cert
+      ];
+
+      networking.extraHosts = ''
+        127.0.0.1 ${domain}
+     '';
+
+      services.rspamd-trainer = {
+        enable = true;
+        settings = {
+          HOST = domain;
+          USERNAME = "spam@${domain}";
+          INBOXPREFIX = "INBOX/";
+        };
+        secrets = [
+          # Do not use this in production. This will make passwords
+          # world-readable in the Nix store
+          "${pkgs.writeText "secrets" ''
+            PASSWORD = test123
+          ''}"
+        ];
+      };
+
+      services.maddy = {
+        enable = true;
+        hostname = domain;
+        primaryDomain = domain;
+        ensureAccounts = [ "spam@${domain}" ];
+        ensureCredentials = {
+          # Do not use this in production. This will make passwords world-readable
+          # in the Nix store
+          "spam@${domain}".passwordFile = "${pkgs.writeText "postmaster" "test123"}";
+        };
+        tls = {
+          loader = "file";
+          certificates = [{
+            certPath = "${certs.${domain}.cert}";
+            keyPath = "${certs.${domain}.key}";
+          }];
+        };
+        config = builtins.replaceStrings [
+          "imap tcp://0.0.0.0:143"
+          "submission tcp://0.0.0.0:587"
+        ] [
+          "imap tls://0.0.0.0:993 tcp://0.0.0.0:143"
+          "submission tls://0.0.0.0:465 tcp://0.0.0.0:587"
+        ] options.services.maddy.config.default;
+      };
+
+      services.rspamd = {
+        enable = true;
+        locals = {
+          "redis.conf".text = ''
+            servers = "${config.services.redis.servers.rspamd.unixSocket}";
+          '';
+          "classifier-bayes.conf".text = ''
+            backend = "redis";
+            autolearn = true;
+          '';
+        };
+      };
+
+      services.redis.servers.rspamd = {
+        enable = true;
+        port = 0;
+        unixSocket = "/run/redis-rspamd/redis.sock";
+        user = config.services.rspamd.user;
+      };
+
+      environment.systemPackages = [
+        (pkgs.writers.writePython3Bin "send-testmail" { } ''
+          import smtplib
+          import ssl
+          from email.mime.text import MIMEText
+          context = ssl.create_default_context()
+          msg = MIMEText("Hello World")
+          msg['Subject'] = 'Test'
+          msg['From'] = "spam@${domain}"
+          msg['To'] = "spam@${domain}"
+          with smtplib.SMTP_SSL(host='${domain}', port=465, context=context) as smtp:
+              smtp.login('spam@${domain}', 'test123')
+              smtp.sendmail(
+                'spam@${domain}', 'spam@${domain}', msg.as_string()
+              )
+        '')
+        (pkgs.writers.writePython3Bin "create-mail-dirs" { } ''
+          import imaplib
+          with imaplib.IMAP4_SSL('${domain}') as imap:
+              imap.login('spam@${domain}', 'test123')
+              imap.create("\"INBOX/report_spam\"")
+              imap.create("\"INBOX/report_ham\"")
+              imap.create("\"INBOX/report_spam_reply\"")
+              imap.select("INBOX")
+              imap.copy("1", "\"INBOX/report_ham\"")
+              imap.logout()
+        '')
+        (pkgs.writers.writePython3Bin "test-imap" { } ''
+          import imaplib
+          with imaplib.IMAP4_SSL('${domain}') as imap:
+              imap.login('spam@${domain}', 'test123')
+              imap.select("INBOX/learned_ham")
+              status, refs = imap.search(None, 'ALL')
+              assert status == 'OK'
+              assert len(refs) == 1
+              status, msg = imap.fetch(refs[0], 'BODY[TEXT]')
+              assert status == 'OK'
+              assert msg[0][1].strip() == b"Hello World"
+              imap.logout()
+        '')
+      ];
+
+
+
+    };
+
+  };
+
+  testScript = { nodes }: ''
+    start_all()
+    machine.wait_for_unit("maddy.service")
+    machine.wait_for_open_port(143)
+    machine.wait_for_open_port(993)
+    machine.wait_for_open_port(587)
+    machine.wait_for_open_port(465)
+
+    # Send test mail to spam@domain
+    machine.succeed("send-testmail")
+
+    # Create mail directories required for rspamd-trainer and copy mail from
+    # INBOX into INBOX/report_ham
+    machine.succeed("create-mail-dirs")
+
+    # Start rspamd-trainer. It should read mail from INBOX/report_ham
+    machine.wait_for_unit("rspamd.service")
+    machine.wait_for_unit("redis-rspamd.service")
+    machine.wait_for_file("/run/rspamd/rspamd.sock")
+    machine.succeed("systemctl start rspamd-trainer.service")
+
+    # Check if mail got processed by rspamd-trainer successfully and check for
+    # it in INBOX/learned_ham
+    machine.succeed("test-imap")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/sogo.nix b/nixpkgs/nixos/tests/sogo.nix
index acdad8d0f473..e9059a2ab773 100644
--- a/nixpkgs/nixos/tests/sogo.nix
+++ b/nixpkgs/nixos/tests/sogo.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, ... }: {
   name = "sogo";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ ajs124 das_j ];
+    maintainers = [];
   };
 
   nodes = {
diff --git a/nixpkgs/nixos/tests/ssh-agent-auth.nix b/nixpkgs/nixos/tests/ssh-agent-auth.nix
new file mode 100644
index 000000000000..2274e463ce95
--- /dev/null
+++ b/nixpkgs/nixos/tests/ssh-agent-auth.nix
@@ -0,0 +1,51 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }:
+  let
+    inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
+  in {
+    name = "ssh-agent-auth";
+    meta.maintainers = with lib.maintainers; [ nicoo ];
+
+    nodes = let nodeConfig = n: { ... }: {
+      users.users = {
+        admin = {
+          isNormalUser = true;
+          extraGroups = [ "wheel" ];
+          openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
+        };
+        foo.isNormalUser = true;
+      };
+
+      security.pam.enableSSHAgentAuth = true;
+      security.${lib.replaceStrings [ "_" ] [ "-" ] n} = {
+        enable = true;
+        wheelNeedsPassword = true;  # We are checking `pam_ssh_agent_auth(8)` works for a sudoer
+      };
+
+      # Necessary for pam_ssh_agent_auth  >_>'
+      services.openssh.enable = true;
+    };
+    in lib.genAttrs [ "sudo" "sudo_rs" ] nodeConfig;
+
+    testScript = let
+      privateKeyPath = "/home/admin/.ssh/id_ecdsa";
+      userScript = pkgs.writeShellScript "test-script" ''
+        set -e
+        ssh-add -q ${privateKeyPath}
+
+        # faketty needed to ensure `sudo` doesn't write to the controlling PTY,
+        #  which would break the test-driver's line-oriented protocol.
+        ${lib.getExe pkgs.faketty} sudo -u foo -- id -un
+      '';
+    in ''
+      for vm in (sudo, sudo_rs):
+        sudo_impl = vm.name.replace("_", "-")
+        with subtest(f"wheel user can auth with ssh-agent for {sudo_impl}"):
+            vm.copy_from_host("${snakeOilPrivateKey}", "${privateKeyPath}")
+            vm.succeed("chmod -R 0700 /home/admin")
+            vm.succeed("chown -R admin:users /home/admin")
+
+            # Run `userScript` in an environment with an SSH-agent available
+            assert vm.succeed("sudo -u admin -- ssh-agent ${userScript} 2>&1").strip() == "foo"
+    '';
+  }
+)
diff --git a/nixpkgs/nixos/tests/stunnel.nix b/nixpkgs/nixos/tests/stunnel.nix
index 07fba435d4df..f8cfa0414761 100644
--- a/nixpkgs/nixos/tests/stunnel.nix
+++ b/nixpkgs/nixos/tests/stunnel.nix
@@ -19,8 +19,10 @@ let
   makeCert = { config, pkgs, ... }: {
     systemd.services.create-test-cert = {
       wantedBy = [ "sysinit.target" ];
-      before = [ "sysinit.target" ];
+      before = [ "sysinit.target" "shutdown.target" ];
+      conflicts = [ "shutdown.target" ];
       unitConfig.DefaultDependencies = false;
+      serviceConfig.Type = "oneshot";
       script = ''
         ${pkgs.openssl}/bin/openssl req -batch -x509 -newkey rsa -nodes -out /test-cert.pem -keyout /test-key.pem -subj /CN=${config.networking.hostName}
         ( umask 077; cat /test-key.pem /test-cert.pem > /test-key-and-cert.pem )
diff --git a/nixpkgs/nixos/tests/systemd-boot.nix b/nixpkgs/nixos/tests/systemd-boot.nix
index 256a18532b0a..c0b37a230df0 100644
--- a/nixpkgs/nixos/tests/systemd-boot.nix
+++ b/nixpkgs/nixos/tests/systemd-boot.nix
@@ -253,7 +253,7 @@ in
   };
 
   garbage-collect-entry = makeTest {
-    name = "systemd-boot-switch-test";
+    name = "systemd-boot-garbage-collect-entry";
     meta.maintainers = with pkgs.lib.maintainers; [ julienmalka ];
 
     nodes = {
diff --git a/nixpkgs/nixos/tests/systemd-initrd-networkd.nix b/nixpkgs/nixos/tests/systemd-initrd-networkd.nix
index 9c4ddb6e4b36..691f4300d7a2 100644
--- a/nixpkgs/nixos/tests/systemd-initrd-networkd.nix
+++ b/nixpkgs/nixos/tests/systemd-initrd-networkd.nix
@@ -33,7 +33,8 @@ let
       boot.initrd.network.flushBeforeStage2 = flush;
       systemd.services.check-flush = {
         requiredBy = ["multi-user.target"];
-        before = ["network-pre.target" "multi-user.target"];
+        before = [ "network-pre.target" "multi-user.target" "shutdown.target" ];
+        conflicts = [ "shutdown.target" ];
         wants = ["network-pre.target"];
         unitConfig.DefaultDependencies = false;
         serviceConfig.Type = "oneshot";
diff --git a/nixpkgs/nixos/tests/tomcat.nix b/nixpkgs/nixos/tests/tomcat.nix
index ff58ca8ac618..df5cb033b78f 100644
--- a/nixpkgs/nixos/tests/tomcat.nix
+++ b/nixpkgs/nixos/tests/tomcat.nix
@@ -1,4 +1,4 @@
-import ./make-test-python.nix ({ pkgs, ... }: {
+import ./make-test-python.nix ({ lib, pkgs, ... }: {
   name = "tomcat";
   meta.maintainers = [ lib.maintainers.anthonyroussel ];
 
diff --git a/nixpkgs/nixos/tests/varnish.nix b/nixpkgs/nixos/tests/varnish.nix
index 9dcdeec9d8c8..76cea1ada547 100644
--- a/nixpkgs/nixos/tests/varnish.nix
+++ b/nixpkgs/nixos/tests/varnish.nix
@@ -3,12 +3,12 @@
 , pkgs ? import ../.. { inherit system; }
 , package
 }:
-import ./make-test-python.nix ({ pkgs, ... }: let
+import ./make-test-python.nix ({ pkgs, lib, ... }: let
   testPath = pkgs.hello;
 in {
   name = "varnish";
-  meta = with pkgs.lib.maintainers; {
-    maintainers = [ ajs124 ];
+  meta = {
+    maintainers = lib.teams.helsinki-systems.members;
   };
 
   nodes = {
diff --git a/nixpkgs/nixos/tests/zfs.nix b/nixpkgs/nixos/tests/zfs.nix
index ad4ea254f34d..8fedcf095af6 100644
--- a/nixpkgs/nixos/tests/zfs.nix
+++ b/nixpkgs/nixos/tests/zfs.nix
@@ -19,7 +19,7 @@ let
     makeTest {
       name = "zfs-" + name;
       meta = with pkgs.lib.maintainers; {
-        maintainers = [ adisbladis elvishjerricco ];
+        maintainers = [ elvishjerricco ];
       };
 
       nodes.machine = { config, pkgs, lib, ... }:
@@ -210,6 +210,7 @@ in {
     enableSystemdStage1 = true;
   };
 
+  installerBoot = (import ./installer.nix { }).separateBootZfs;
   installer = (import ./installer.nix { }).zfsroot;
 
   expand-partitions = makeTest {