about summary refs log tree commit diff
path: root/nixos/tests
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/tests')
-rw-r--r--nixos/tests/3proxy.nix1
-rw-r--r--nixos/tests/acme.nix1
-rw-r--r--nixos/tests/activation/etc-overlay-immutable.nix30
-rw-r--r--nixos/tests/activation/etc-overlay-mutable.nix30
-rw-r--r--nixos/tests/activation/perlless.nix24
-rw-r--r--nixos/tests/adguardhome.nix1
-rw-r--r--nixos/tests/all-tests.nix12
-rw-r--r--nixos/tests/appliance-repart-image.nix33
-rw-r--r--nixos/tests/ayatana-indicators.nix53
-rw-r--r--nixos/tests/babeld.nix4
-rw-r--r--nixos/tests/bittorrent.nix4
-rw-r--r--nixos/tests/buildbot.nix2
-rw-r--r--nixos/tests/ceph-multi-node.nix8
-rw-r--r--nixos/tests/ceph-single-node-bluestore.nix8
-rw-r--r--nixos/tests/ceph-single-node.nix29
-rw-r--r--nixos/tests/cloud-init.nix1
-rw-r--r--nixos/tests/corerad.nix2
-rw-r--r--nixos/tests/curl-impersonate.nix2
-rw-r--r--nixos/tests/dolibarr.nix2
-rw-r--r--nixos/tests/elk.nix6
-rw-r--r--nixos/tests/ferm.nix2
-rw-r--r--nixos/tests/frp.nix25
-rw-r--r--nixos/tests/gitdaemon.nix3
-rw-r--r--nixos/tests/guix/publish.nix1
-rw-r--r--nixos/tests/haproxy.nix109
-rw-r--r--nixos/tests/hostname.nix1
-rw-r--r--nixos/tests/incus/default.nix5
-rw-r--r--nixos/tests/incus/lxd-to-incus.nix112
-rw-r--r--nixos/tests/installer.nix3
-rw-r--r--nixos/tests/kanidm.nix1
-rw-r--r--nixos/tests/keepalived.nix3
-rw-r--r--nixos/tests/lemmy.nix2
-rw-r--r--nixos/tests/miriway.nix2
-rw-r--r--nixos/tests/networking.nix3
-rw-r--r--nixos/tests/nfs/kerberos.nix1
-rw-r--r--nixos/tests/nginx-moreheaders.nix37
-rw-r--r--nixos/tests/nixops/default.nix6
-rw-r--r--nixos/tests/ntpd-rs.nix10
-rw-r--r--nixos/tests/opensmtpd-rspamd.nix1
-rw-r--r--nixos/tests/opensmtpd.nix1
-rw-r--r--nixos/tests/openssh.nix28
-rw-r--r--nixos/tests/owncast.nix2
-rw-r--r--nixos/tests/podman/default.nix2
-rw-r--r--nixos/tests/postgis.nix1
-rw-r--r--nixos/tests/prometheus-exporters.nix8
-rw-r--r--nixos/tests/qemu-vm-restrictnetwork.nix2
-rw-r--r--nixos/tests/rss2email.nix1
-rw-r--r--nixos/tests/ssh-audit.nix1
-rw-r--r--nixos/tests/suwayomi-server.nix46
-rw-r--r--nixos/tests/sysinit-reactivation.nix107
-rw-r--r--nixos/tests/systemd-networkd-dhcpserver.nix3
-rw-r--r--nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix8
-rw-r--r--nixos/tests/systemd-nspawn.nix1
-rw-r--r--nixos/tests/systemd-sysusers-immutable.nix64
-rw-r--r--nixos/tests/systemd-sysusers-mutable.nix71
-rw-r--r--nixos/tests/tayga.nix2
-rw-r--r--nixos/tests/terminal-emulators.nix2
-rw-r--r--nixos/tests/trafficserver.nix1
-rw-r--r--nixos/tests/ulogd/ulogd.py1
-rw-r--r--nixos/tests/upnp.nix2
-rw-r--r--nixos/tests/uptermd.nix1
-rw-r--r--nixos/tests/watchdogd.nix22
-rw-r--r--nixos/tests/web-apps/netbox-upgrade.nix4
-rw-r--r--nixos/tests/web-servers/stargazer.nix108
-rw-r--r--nixos/tests/web-servers/ttyd.nix19
-rw-r--r--nixos/tests/zrepl.nix1
66 files changed, 976 insertions, 113 deletions
diff --git a/nixos/tests/3proxy.nix b/nixos/tests/3proxy.nix
index 83d39de018a39..b80b4e166d481 100644
--- a/nixos/tests/3proxy.nix
+++ b/nixos/tests/3proxy.nix
@@ -134,6 +134,7 @@
   testScript = ''
     start_all()
 
+    peer0.systemctl("start network-online.target")
     peer0.wait_for_unit("network-online.target")
 
     peer1.wait_for_unit("3proxy.service")
diff --git a/nixos/tests/acme.nix b/nixos/tests/acme.nix
index e5f2d4c7934a1..272782dc2f621 100644
--- a/nixos/tests/acme.nix
+++ b/nixos/tests/acme.nix
@@ -522,6 +522,7 @@ in {
           'curl --data \'{"host": "${caDomain}", "addresses": ["${nodes.acme.networking.primaryIPAddress}"]}\' http://${dnsServerIP nodes}:8055/add-a'
       )
 
+      acme.systemctl("start network-online.target")
       acme.wait_for_unit("network-online.target")
       acme.wait_for_unit("pebble.service")
 
diff --git a/nixos/tests/activation/etc-overlay-immutable.nix b/nixos/tests/activation/etc-overlay-immutable.nix
new file mode 100644
index 0000000000000..70c3623b929c5
--- /dev/null
+++ b/nixos/tests/activation/etc-overlay-immutable.nix
@@ -0,0 +1,30 @@
+{ lib, ... }: {
+
+  name = "activation-etc-overlay-immutable";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { pkgs, ... }: {
+    system.etc.overlay.enable = true;
+    system.etc.overlay.mutable = false;
+
+    # Prerequisites
+    systemd.sysusers.enable = true;
+    users.mutableUsers = false;
+    boot.initrd.systemd.enable = true;
+    boot.kernelPackages = pkgs.linuxPackages_latest;
+
+    specialisation.new-generation.configuration = {
+      environment.etc."newgen".text = "newgen";
+    };
+  };
+
+  testScript = ''
+    machine.succeed("findmnt --kernel --type overlay /etc")
+    machine.fail("stat /etc/newgen")
+
+    machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
+
+    assert machine.succeed("cat /etc/newgen") == "newgen"
+  '';
+}
diff --git a/nixos/tests/activation/etc-overlay-mutable.nix b/nixos/tests/activation/etc-overlay-mutable.nix
new file mode 100644
index 0000000000000..cfe7604fceb84
--- /dev/null
+++ b/nixos/tests/activation/etc-overlay-mutable.nix
@@ -0,0 +1,30 @@
+{ lib, ... }: {
+
+  name = "activation-etc-overlay-mutable";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { pkgs, ... }: {
+    system.etc.overlay.enable = true;
+    system.etc.overlay.mutable = true;
+
+    # Prerequisites
+    boot.initrd.systemd.enable = true;
+    boot.kernelPackages = pkgs.linuxPackages_latest;
+
+    specialisation.new-generation.configuration = {
+      environment.etc."newgen".text = "newgen";
+    };
+  };
+
+  testScript = ''
+    machine.succeed("findmnt --kernel --type overlay /etc")
+    machine.fail("stat /etc/newgen")
+    machine.succeed("echo -n 'mutable' > /etc/mutable")
+
+    machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
+
+    assert machine.succeed("cat /etc/newgen") == "newgen"
+    assert machine.succeed("cat /etc/mutable") == "mutable"
+  '';
+}
diff --git a/nixos/tests/activation/perlless.nix b/nixos/tests/activation/perlless.nix
new file mode 100644
index 0000000000000..4d784b4542f45
--- /dev/null
+++ b/nixos/tests/activation/perlless.nix
@@ -0,0 +1,24 @@
+{ lib, ... }:
+
+{
+
+  name = "activation-perlless";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { pkgs, modulesPath, ... }: {
+    imports = [ "${modulesPath}/profiles/perlless.nix" ];
+
+    boot.kernelPackages = pkgs.linuxPackages_latest;
+
+    virtualisation.mountHostNixStore = false;
+    virtualisation.useNixStoreImage = true;
+  };
+
+  testScript = ''
+    perl_store_paths = machine.succeed("ls /nix/store | grep perl || true")
+    print(perl_store_paths)
+    assert len(perl_store_paths) == 0
+  '';
+
+}
diff --git a/nixos/tests/adguardhome.nix b/nixos/tests/adguardhome.nix
index a6f790b83f5fc..80613ce825340 100644
--- a/nixos/tests/adguardhome.nix
+++ b/nixos/tests/adguardhome.nix
@@ -126,6 +126,7 @@
 
     with subtest("Testing successful DHCP start"):
         dhcpConf.wait_for_unit("adguardhome.service")
+        client.systemctl("start network-online.target")
         client.wait_for_unit("network-online.target")
         # Test IP assignment via DHCP
         dhcpConf.wait_until_succeeds("ping -c 5 10.0.10.100")
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 63e957eace88d..1453a3875f6e7 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -285,6 +285,9 @@ in {
   activation = pkgs.callPackage ../modules/system/activation/test.nix { };
   activation-var = runTest ./activation/var.nix;
   activation-nix-channel = runTest ./activation/nix-channel.nix;
+  activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix;
+  activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix;
+  activation-perlless = runTest ./activation/perlless.nix;
   etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {};
   etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {};
   etebase-server = handleTest ./etebase-server.nix {};
@@ -569,8 +572,8 @@ in {
   netdata = handleTest ./netdata.nix {};
   networking.networkd = handleTest ./networking.nix { networkd = true; };
   networking.scripted = handleTest ./networking.nix { networkd = false; };
-  netbox_3_5 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_3_5; };
   netbox_3_6 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_3_6; };
+  netbox_3_7 = handleTest ./web-apps/netbox.nix { netbox = pkgs.netbox_3_7; };
   netbox-upgrade = handleTest ./web-apps/netbox-upgrade.nix {};
   # TODO: put in networking.nix after the test becomes more complete
   networkingProxy = handleTest ./networking-proxy.nix {};
@@ -587,6 +590,7 @@ in {
   nginx-globalredirect = handleTest ./nginx-globalredirect.nix {};
   nginx-http3 = handleTest ./nginx-http3.nix {};
   nginx-modsecurity = handleTest ./nginx-modsecurity.nix {};
+  nginx-moreheaders = handleTest ./nginx-moreheaders.nix {};
   nginx-njs = handleTest ./nginx-njs.nix {};
   nginx-proxyprotocol = handleTest ./nginx-proxyprotocol {};
   nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
@@ -808,6 +812,7 @@ in {
   stunnel = handleTest ./stunnel.nix {};
   sudo = handleTest ./sudo.nix {};
   sudo-rs = handleTest ./sudo-rs.nix {};
+  suwayomi-server = handleTest ./suwayomi-server.nix {};
   swap-file-btrfs = handleTest ./swap-file-btrfs.nix {};
   swap-partition = handleTest ./swap-partition.nix {};
   swap-random-encryption = handleTest ./swap-random-encryption.nix {};
@@ -819,6 +824,7 @@ in {
   syncthing-init = handleTest ./syncthing-init.nix {};
   syncthing-many-devices = handleTest ./syncthing-many-devices.nix {};
   syncthing-relay = handleTest ./syncthing-relay.nix {};
+  sysinit-reactivation = runTest ./sysinit-reactivation.nix;
   systemd = handleTest ./systemd.nix {};
   systemd-analyze = handleTest ./systemd-analyze.nix {};
   systemd-binfmt = handleTestOn ["x86_64-linux"] ./systemd-binfmt.nix {};
@@ -863,6 +869,8 @@ in {
   systemd-repart = handleTest ./systemd-repart.nix {};
   systemd-shutdown = handleTest ./systemd-shutdown.nix {};
   systemd-sysupdate = runTest ./systemd-sysupdate.nix;
+  systemd-sysusers-mutable = runTest ./systemd-sysusers-mutable.nix;
+  systemd-sysusers-immutable = runTest ./systemd-sysusers-immutable.nix;
   systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
   systemd-timesyncd-nscd-dnssec = handleTest ./systemd-timesyncd-nscd-dnssec.nix {};
   systemd-user-tmpfiles-rules = handleTest ./systemd-user-tmpfiles-rules.nix {};
@@ -902,6 +910,7 @@ in {
   trilium-server = handleTestOn ["x86_64-linux"] ./trilium-server.nix {};
   tsja = handleTest ./tsja.nix {};
   tsm-client-gui = handleTest ./tsm-client-gui.nix {};
+  ttyd = handleTest ./web-servers/ttyd.nix {};
   txredisapi = handleTest ./txredisapi.nix {};
   tuptime = handleTest ./tuptime.nix {};
   turbovnc-headless-server = handleTest ./turbovnc-headless-server.nix {};
@@ -941,6 +950,7 @@ in {
   vsftpd = handleTest ./vsftpd.nix {};
   warzone2100 = handleTest ./warzone2100.nix {};
   wasabibackend = handleTest ./wasabibackend.nix {};
+  watchdogd = handleTest ./watchdogd.nix {};
   webhook = runTest ./webhook.nix;
   wiki-js = handleTest ./wiki-js.nix {};
   wine = handleTest ./wine.nix {};
diff --git a/nixos/tests/appliance-repart-image.nix b/nixos/tests/appliance-repart-image.nix
index 3f256db846214..b18968d3b9631 100644
--- a/nixos/tests/appliance-repart-image.nix
+++ b/nixos/tests/appliance-repart-image.nix
@@ -8,9 +8,8 @@
 let
   rootPartitionLabel = "root";
 
-  bootLoaderConfigPath = "/loader/entries/nixos.conf";
-  kernelPath = "/EFI/nixos/kernel.efi";
-  initrdPath = "/EFI/nixos/initrd.efi";
+  imageId = "nixos-appliance";
+  imageVersion = "1-rc1";
 in
 {
   name = "appliance-gpt-image";
@@ -29,6 +28,9 @@ in
     # TODO(raitobezarius): revisit this when #244907 lands
     boot.loader.grub.enable = false;
 
+    system.image.id = imageId;
+    system.image.version = imageVersion;
+
     virtualisation.fileSystems = lib.mkForce {
       "/" = {
         device = "/dev/disk/by-partlabel/${rootPartitionLabel}";
@@ -48,19 +50,8 @@ in
               "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
                 "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
 
-              # TODO: create an abstraction for Boot Loader Specification (BLS) entries.
-              "${bootLoaderConfigPath}".source = pkgs.writeText "nixos.conf" ''
-                title NixOS
-                linux ${kernelPath}
-                initrd ${initrdPath}
-                options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
-              '';
-
-              "${kernelPath}".source =
-                "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
-
-              "${initrdPath}".source =
-                "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
+              "/EFI/Linux/${config.system.boot.loader.ukiFile}".source =
+                "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
             };
           repartConfig = {
             Type = "esp";
@@ -99,7 +90,7 @@ in
       "-f",
       "qcow2",
       "-b",
-      "${nodes.machine.system.build.image}/image.raw",
+      "${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}",
       "-F",
       "raw",
       tmp_disk_image.name,
@@ -108,9 +99,11 @@ in
     # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
     os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
 
+    os_release = machine.succeed("cat /etc/os-release")
+    assert 'IMAGE_ID="${imageId}"' in os_release
+    assert 'IMAGE_VERSION="${imageVersion}"' in os_release
+
     bootctl_status = machine.succeed("bootctl status")
-    assert "${bootLoaderConfigPath}" in bootctl_status
-    assert "${kernelPath}" in bootctl_status
-    assert "${initrdPath}" in bootctl_status
+    assert "Boot Loader Specification Type #2 (.efi)" in bootctl_status
   '';
 }
diff --git a/nixos/tests/ayatana-indicators.nix b/nixos/tests/ayatana-indicators.nix
index bc7ff75f390f7..c9cbbda4c601d 100644
--- a/nixos/tests/ayatana-indicators.nix
+++ b/nixos/tests/ayatana-indicators.nix
@@ -4,7 +4,7 @@ in {
   name = "ayatana-indicators";
 
   meta = {
-    maintainers = with lib.maintainers; [ OPNA2608 ];
+    maintainers = lib.teams.lomiri.members;
   };
 
   nodes.machine = { config, ... }: {
@@ -27,17 +27,56 @@ in {
     services.ayatana-indicators = {
       enable = true;
       packages = with pkgs; [
+        ayatana-indicator-datetime
         ayatana-indicator-messages
-      ];
+      ] ++ (with pkgs.lomiri; [
+        lomiri-indicator-network
+        telephony-service
+      ]);
     };
 
-    # Services needed by some indicators
+    # Setup needed by some indicators
+
     services.accounts-daemon.enable = true; # messages
+
+    # Lomiri-ish setup for Lomiri indicators
+    # TODO move into a Lomiri module, once the package set is far enough for the DE to start
+
+    networking.networkmanager.enable = true; # lomiri-network-indicator
+    # TODO potentially urfkill for lomiri-network-indicator?
+
+    services.dbus.packages = with pkgs.lomiri; [
+      libusermetrics
+    ];
+
+    environment.systemPackages = with pkgs.lomiri; [
+      lomiri-schemas
+    ];
+
+    services.telepathy.enable = true;
+
+    users.users.usermetrics = {
+      group = "usermetrics";
+      home = "/var/lib/usermetrics";
+      createHome = true;
+      isSystemUser = true;
+    };
+
+    users.groups.usermetrics = { };
   };
 
   # TODO session indicator starts up in a semi-broken state, but works fine after a restart. maybe being started before graphical session is truly up & ready?
   testScript = { nodes, ... }: let
-    runCommandPerIndicatorService = command: lib.strings.concatMapStringsSep "\n" command nodes.machine.systemd.user.targets."ayatana-indicators".wants;
+    runCommandOverServiceList = list: command:
+      lib.strings.concatMapStringsSep "\n" command list;
+
+    runCommandOverAyatanaIndicators = runCommandOverServiceList
+      (builtins.filter
+        (service: !(lib.strings.hasPrefix "lomiri" service || lib.strings.hasPrefix "telephony-service" service))
+        nodes.machine.systemd.user.targets."ayatana-indicators".wants);
+
+    runCommandOverAllIndicators = runCommandOverServiceList
+      nodes.machine.systemd.user.targets."ayatana-indicators".wants;
   in ''
     start_all()
     machine.wait_for_x()
@@ -50,8 +89,8 @@ in {
     machine.sleep(10)
 
     # Now check if all indicators were brought up successfully, and kill them for later
-  '' + (runCommandPerIndicatorService (service: let serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service; in ''
-    machine.succeed("pgrep -f ${serviceExec}")
+  '' + (runCommandOverAyatanaIndicators (service: let serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service; in ''
+    machine.succeed("pgrep -u ${user} -f ${serviceExec}")
     machine.succeed("pkill -f ${serviceExec}")
   '')) + ''
 
@@ -65,7 +104,7 @@ in {
     machine.sleep(10)
 
     # Now check if all indicator services were brought up successfully
-  '' + runCommandPerIndicatorService (service: ''
+  '' + runCommandOverAllIndicators (service: ''
     machine.wait_for_unit("${service}", "${user}")
   '');
 })
diff --git a/nixos/tests/babeld.nix b/nixos/tests/babeld.nix
index d4df6f86d089d..e497aa5b64e15 100644
--- a/nixos/tests/babeld.nix
+++ b/nixos/tests/babeld.nix
@@ -120,10 +120,6 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
     ''
       start_all()
 
-      client.wait_for_unit("network-online.target")
-      local_router.wait_for_unit("network-online.target")
-      remote_router.wait_for_unit("network-online.target")
-
       local_router.wait_for_unit("babeld.service")
       remote_router.wait_for_unit("babeld.service")
 
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 4a73fea6a09d0..473b05d4c98e8 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -115,6 +115,7 @@ in
       start_all()
 
       # Wait for network and miniupnpd.
+      router.systemctl("start network-online.target")
       router.wait_for_unit("network-online.target")
       router.wait_for_unit("miniupnpd")
 
@@ -129,6 +130,7 @@ in
       tracker.succeed("chmod 644 /tmp/test.torrent")
 
       # Start the tracker.  !!! use a less crappy tracker
+      tracker.systemctl("start network-online.target")
       tracker.wait_for_unit("network-online.target")
       tracker.wait_for_unit("opentracker.service")
       tracker.wait_for_open_port(6969)
@@ -140,6 +142,7 @@ in
 
       # Now we should be able to download from the client behind the NAT.
       tracker.wait_for_unit("httpd")
+      client1.systemctl("start network-online.target")
       client1.wait_for_unit("network-online.target")
       client1.succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent >&2 &")
       client1.wait_for_file("${download-dir}/test.tar.bz2")
@@ -152,6 +155,7 @@ in
 
       # Now download from the second client.  This can only succeed if
       # the first client created a NAT hole in the router.
+      client2.systemctl("start network-online.target")
       client2.wait_for_unit("network-online.target")
       client2.succeed(
           "transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht >&2 &"
diff --git a/nixos/tests/buildbot.nix b/nixos/tests/buildbot.nix
index 2f6926313b7cd..149d73bba09c5 100644
--- a/nixos/tests/buildbot.nix
+++ b/nixos/tests/buildbot.nix
@@ -71,6 +71,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     gitrepo.wait_for_unit("multi-user.target")
 
     with subtest("Repo is accessible via git daemon"):
+        bbmaster.systemctl("start network-online.target")
         bbmaster.wait_for_unit("network-online.target")
         bbmaster.succeed("rm -rfv /tmp/fakerepo")
         bbmaster.succeed("git clone git://gitrepo/fakerepo /tmp/fakerepo")
@@ -78,6 +79,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     with subtest("Master service and worker successfully connect"):
         bbmaster.wait_for_unit("buildbot-master.service")
         bbmaster.wait_until_succeeds("curl --fail -s --head http://bbmaster:8010")
+        bbworker.systemctl("start network-online.target")
         bbworker.wait_for_unit("network-online.target")
         bbworker.succeed("nc -z bbmaster 8010")
         bbworker.succeed("nc -z bbmaster 9989")
diff --git a/nixos/tests/ceph-multi-node.nix b/nixos/tests/ceph-multi-node.nix
index 556546beee764..b1352a4bc8f4e 100644
--- a/nixos/tests/ceph-multi-node.nix
+++ b/nixos/tests/ceph-multi-node.nix
@@ -185,6 +185,14 @@ let
     monA.succeed(
         "ceph osd pool create multi-node-test 32 32",
         "ceph osd pool ls | grep 'multi-node-test'",
+
+        # We need to enable an application on the pool, otherwise it will
+        # stay unhealthy in state POOL_APP_NOT_ENABLED.
+        # Creating a CephFS would do this automatically, but we haven't done that here.
+        # See: https://docs.ceph.com/en/reef/rados/operations/pools/#associating-a-pool-with-an-application
+        # We use the custom application name "nixos-test" for this.
+        "ceph osd pool application enable multi-node-test nixos-test",
+
         "ceph osd pool rename multi-node-test multi-node-other-test",
         "ceph osd pool ls | grep 'multi-node-other-test'",
     )
diff --git a/nixos/tests/ceph-single-node-bluestore.nix b/nixos/tests/ceph-single-node-bluestore.nix
index acaae4cf300e8..8bd1a78244a29 100644
--- a/nixos/tests/ceph-single-node-bluestore.nix
+++ b/nixos/tests/ceph-single-node-bluestore.nix
@@ -145,6 +145,14 @@ let
     monA.succeed(
         "ceph osd pool create single-node-test 32 32",
         "ceph osd pool ls | grep 'single-node-test'",
+
+        # We need to enable an application on the pool, otherwise it will
+        # stay unhealthy in state POOL_APP_NOT_ENABLED.
+        # Creating a CephFS would do this automatically, but we haven't done that here.
+        # See: https://docs.ceph.com/en/reef/rados/operations/pools/#associating-a-pool-with-an-application
+        # We use the custom application name "nixos-test" for this.
+        "ceph osd pool application enable single-node-test nixos-test",
+
         "ceph osd pool rename single-node-test single-node-other-test",
         "ceph osd pool ls | grep 'single-node-other-test'",
     )
diff --git a/nixos/tests/ceph-single-node.nix b/nixos/tests/ceph-single-node.nix
index a3a4072365af8..c34ec511dc6d2 100644
--- a/nixos/tests/ceph-single-node.nix
+++ b/nixos/tests/ceph-single-node.nix
@@ -145,6 +145,14 @@ let
     monA.succeed(
         "ceph osd pool create single-node-test 32 32",
         "ceph osd pool ls | grep 'single-node-test'",
+
+        # We need to enable an application on the pool, otherwise it will
+        # stay unhealthy in state POOL_APP_NOT_ENABLED.
+        # Creating a CephFS would do this automatically, but we haven't done that here.
+        # See: https://docs.ceph.com/en/reef/rados/operations/pools/#associating-a-pool-with-an-application
+        # We use the custom application name "nixos-test" for this.
+        "ceph osd pool application enable single-node-test nixos-test",
+
         "ceph osd pool rename single-node-test single-node-other-test",
         "ceph osd pool ls | grep 'single-node-other-test'",
     )
@@ -182,19 +190,16 @@ let
     monA.wait_until_succeeds("ceph -s | grep 'mgr: ${cfg.monA.name}(active,'")
     monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
 
-    # This test has been commented out due to the upstream issue with pyo3
-    # that has broken this dashboard
-    # Reference: https://www.spinics.net/lists/ceph-users/msg77812.html
     # Enable the dashboard and recheck health
-    # monA.succeed(
-    #     "ceph mgr module enable dashboard",
-    #     "ceph config set mgr mgr/dashboard/ssl false",
-    #     # default is 8080 but it's better to be explicit
-    #     "ceph config set mgr mgr/dashboard/server_port 8080",
-    # )
-    # monA.wait_for_open_port(8080)
-    # monA.wait_until_succeeds("curl -q --fail http://localhost:8080")
-    # monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
+    monA.succeed(
+        "ceph mgr module enable dashboard",
+        "ceph config set mgr mgr/dashboard/ssl false",
+        # default is 8080 but it's better to be explicit
+        "ceph config set mgr mgr/dashboard/server_port 8080",
+    )
+    monA.wait_for_open_port(8080)
+    monA.wait_until_succeeds("curl -q --fail http://localhost:8080")
+    monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
   '';
 in {
   name = "basic-single-node-ceph-cluster";
diff --git a/nixos/tests/cloud-init.nix b/nixos/tests/cloud-init.nix
index 786e01add7d4b..0b4c5a55c80a6 100644
--- a/nixos/tests/cloud-init.nix
+++ b/nixos/tests/cloud-init.nix
@@ -73,6 +73,7 @@ in makeTest {
   };
   testScript = ''
     # To wait until cloud-init terminates its run
+    unnamed.wait_for_unit("cloud-init-local.service")
     unnamed.wait_for_unit("cloud-final.service")
 
     unnamed.succeed("cat /tmp/cloudinit-write-file | grep -q 'cloudinit'")
diff --git a/nixos/tests/corerad.nix b/nixos/tests/corerad.nix
index b6f5d7fc6f75b..dd2bec794a1a0 100644
--- a/nixos/tests/corerad.nix
+++ b/nixos/tests/corerad.nix
@@ -56,6 +56,8 @@ import ./make-test-python.nix (
 
       with subtest("Wait for CoreRAD and network ready"):
           # Ensure networking is online and CoreRAD is ready.
+          router.systemctl("start network-online.target")
+          client.systemctl("start network-online.target")
           router.wait_for_unit("network-online.target")
           client.wait_for_unit("network-online.target")
           router.wait_for_unit("corerad.service")
diff --git a/nixos/tests/curl-impersonate.nix b/nixos/tests/curl-impersonate.nix
index 7954e9e5584c4..33b10da1dfd0f 100644
--- a/nixos/tests/curl-impersonate.nix
+++ b/nixos/tests/curl-impersonate.nix
@@ -144,6 +144,8 @@ in {
     start_all()
 
     with subtest("Wait for network"):
+        web.systemctl("start network-online.target")
+        curl.systemctl("start network-online.target")
         web.wait_for_unit("network-online.target")
         curl.wait_for_unit("network-online.target")
 
diff --git a/nixos/tests/dolibarr.nix b/nixos/tests/dolibarr.nix
index 4fdee9e9698f5..95557d317fab9 100644
--- a/nixos/tests/dolibarr.nix
+++ b/nixos/tests/dolibarr.nix
@@ -1,6 +1,6 @@
 import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "dolibarr";
-  meta.maintainers = [ lib.maintainers.raitobezarius ];
+  meta.maintainers = [ ];
 
   nodes.machine =
     { ... }:
diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix
index 900ea6320100f..b5a8cb532ae0a 100644
--- a/nixos/tests/elk.nix
+++ b/nixos/tests/elk.nix
@@ -1,6 +1,6 @@
 # To run the test on the unfree ELK use the following command:
 # cd path/to/nixpkgs
-# NIXPKGS_ALLOW_UNFREE=1 nix-build -A nixosTests.elk.unfree.ELK-6
+# NIXPKGS_ALLOW_UNFREE=1 nix-build -A nixosTests.elk.unfree.ELK-7
 
 { system ? builtins.currentSystem,
   config ? {},
@@ -120,7 +120,7 @@ let
               };
 
               elasticsearch-curator = {
-                enable = true;
+                enable = elk ? elasticsearch-curator;
                 actionYAML = ''
                 ---
                 actions:
@@ -246,7 +246,7 @@ let
           one.wait_until_succeeds(
               expect_hits("SuperdupercalifragilisticexpialidociousIndeed")
           )
-    '' + ''
+    '' + lib.optionalString (elk ? elasticsearch-curator) ''
       with subtest("Elasticsearch-curator works"):
           one.systemctl("stop logstash")
           one.systemctl("start elasticsearch-curator")
diff --git a/nixos/tests/ferm.nix b/nixos/tests/ferm.nix
index be43877445ebf..87c67ac623479 100644
--- a/nixos/tests/ferm.nix
+++ b/nixos/tests/ferm.nix
@@ -55,6 +55,8 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     ''
       start_all()
 
+      client.systemctl("start network-online.target")
+      server.systemctl("start network-online.target")
       client.wait_for_unit("network-online.target")
       server.wait_for_unit("network-online.target")
       server.wait_for_unit("ferm.service")
diff --git a/nixos/tests/frp.nix b/nixos/tests/frp.nix
index 2f5c0f8ec933b..1f57c031a53a5 100644
--- a/nixos/tests/frp.nix
+++ b/nixos/tests/frp.nix
@@ -18,10 +18,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
         enable = true;
         role = "server";
         settings = {
-          common = {
-            bind_port = 7000;
-            vhost_http_port = 80;
-          };
+          bindPort = 7000;
+          vhostHTTPPort = 80;
         };
       };
     };
@@ -59,15 +57,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
         enable = true;
         role = "client";
         settings = {
-          common = {
-            server_addr = "10.0.0.1";
-            server_port = 7000;
-          };
-          web = {
-            type = "http";
-            local_port = 80;
-            custom_domains = "10.0.0.1";
-          };
+          serverAddr = "10.0.0.1";
+          serverPort = 7000;
+          proxies = [
+            {
+              name = "web";
+              type = "http";
+              localPort = 80;
+              customDomains = [ "10.0.0.1" ];
+            }
+          ];
         };
       };
     };
diff --git a/nixos/tests/gitdaemon.nix b/nixos/tests/gitdaemon.nix
index bb07b6e97b7fb..052fa902b4504 100644
--- a/nixos/tests/gitdaemon.nix
+++ b/nixos/tests/gitdaemon.nix
@@ -59,6 +59,9 @@ in {
     with subtest("git daemon starts"):
         server.wait_for_unit("git-daemon.service")
 
+
+    server.systemctl("start network-online.target")
+    client.systemctl("start network-online.target")
     server.wait_for_unit("network-online.target")
     client.wait_for_unit("network-online.target")
 
diff --git a/nixos/tests/guix/publish.nix b/nixos/tests/guix/publish.nix
index a15e00b0fa981..eb56fc97478cc 100644
--- a/nixos/tests/guix/publish.nix
+++ b/nixos/tests/guix/publish.nix
@@ -80,6 +80,7 @@ in {
 
     # Now it's the client turn to make use of it.
     substitute_server = "http://server.local:${toString publishPort}"
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
     response = client.succeed(f"curl {substitute_server}")
     assert "Guix Substitute Server" in response
diff --git a/nixos/tests/haproxy.nix b/nixos/tests/haproxy.nix
index 555474d7f2999..1730938737577 100644
--- a/nixos/tests/haproxy.nix
+++ b/nixos/tests/haproxy.nix
@@ -1,22 +1,42 @@
-import ./make-test-python.nix ({ pkgs, ...}: {
+import ./make-test-python.nix ({ lib, pkgs, ...}: {
   name = "haproxy";
   nodes = {
-    machine = { ... }: {
-      services.haproxy = {
+    server = { ... }: {
+     services.haproxy = {
         enable = true;
         config = ''
+          global
+            limited-quic
+
           defaults
+            mode http
             timeout connect 10s
+            timeout client 10s
+            timeout server 10s
+
+            log /dev/log local0 debug err
+            option logasap
+            option httplog
+            option httpslog
 
           backend http_server
-            mode http
-            server httpd [::1]:8000
+            server httpd [::1]:8000 alpn http/1.1
 
           frontend http
-            bind *:80
-            mode http
+            bind :80
+            bind :443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h2,http/1.1
+            bind quic4@:443 ssl strict-sni crt /etc/ssl/fullchain.pem alpn h3 allow-0rtt
+
+            http-after-response add-header alt-svc 'h3=":443"; ma=60' if { ssl_fc }
+
             http-request use-service prometheus-exporter if { path /metrics }
             use_backend http_server
+
+          frontend http-cert-auth
+            bind :8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt
+            bind quic4@:8443 ssl strict-sni crt /etc/ssl/fullchain.pem verify required ca-file /etc/ssl/cacert.crt alpn h3
+
+            use_backend http_server
         '';
       };
       services.httpd = {
@@ -30,24 +50,75 @@ import ./make-test-python.nix ({ pkgs, ...}: {
           }];
         };
       };
+      networking.firewall.allowedTCPPorts = [ 80 443 8443 ];
+      networking.firewall.allowedUDPPorts = [ 443 8443 ];
+     };
+    client = { ... }: {
+      environment.systemPackages = [ pkgs.curlHTTP3 ];
     };
   };
   testScript = ''
+    # Helpers
+    def cmd(command):
+      print(f"+{command}")
+      r = os.system(command)
+      if r != 0:
+        raise Exception(f"Command {command} failed with exit code {r}")
+
+    def openssl(command):
+      cmd(f"${pkgs.openssl}/bin/openssl {command}")
+
+    # Generate CA.
+    openssl("req -new -newkey rsa:4096 -nodes -x509 -days 7 -subj '/C=ZZ/ST=Cloud/L=Unspecified/O=NixOS/OU=Tests/CN=CA Certificate' -keyout cacert.key -out cacert.crt")
+
+    # Generate and sign Server.
+    openssl("req -newkey rsa:4096 -nodes -subj '/CN=server/OU=Tests/O=NixOS' -keyout server.key -out server.csr")
+    openssl("x509 -req -in server.csr -out server.crt -CA cacert.crt -CAkey cacert.key -days 7")
+    cmd("cat server.crt server.key > fullchain.pem")
+
+    # Generate and sign Client.
+    openssl("req -newkey rsa:4096 -nodes -subj '/CN=client/OU=Tests/O=NixOS' -keyout client.key -out client.csr")
+    openssl("x509 -req -in client.csr -out client.crt -CA cacert.crt -CAkey cacert.key -days 7")
+    cmd("cat client.crt client.key > client.pem")
+
+    # Start the actual test.
     start_all()
-    machine.wait_for_unit("multi-user.target")
-    machine.wait_for_unit("haproxy.service")
-    machine.wait_for_unit("httpd.service")
-    assert "We are all good!" in machine.succeed("curl -fk http://localhost:80/index.txt")
-    assert "haproxy_process_pool_allocated_bytes" in machine.succeed(
-        "curl -fk http://localhost:80/metrics"
-    )
+    server.copy_from_host("fullchain.pem", "/etc/ssl/fullchain.pem")
+    server.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt")
+    server.succeed("chmod 0644 /etc/ssl/fullchain.pem /etc/ssl/cacert.crt")
+
+    client.copy_from_host("cacert.crt", "/etc/ssl/cacert.crt")
+    client.copy_from_host("client.pem", "/root/client.pem")
+
+    server.wait_for_unit("multi-user.target")
+    server.wait_for_unit("haproxy.service")
+    server.wait_for_unit("httpd.service")
+
+    assert "We are all good!" in client.succeed("curl -f http://server/index.txt")
+    assert "haproxy_process_pool_allocated_bytes" in client.succeed("curl -f http://server/metrics")
+
+    with subtest("https"):
+      assert "We are all good!" in client.succeed("curl -f --cacert /etc/ssl/cacert.crt https://server/index.txt")
+
+    with subtest("https-cert-auth"):
+      # Client must succeed in authenticating with the right certificate.
+      assert "We are all good!" in client.succeed("curl -f --cacert /etc/ssl/cacert.crt --cert-type pem --cert /root/client.pem https://server:8443/index.txt")
+      # Client must fail without certificate.
+      client.fail("curl --cacert /etc/ssl/cacert.crt https://server:8443/index.txt")
+
+    with subtest("h3"):
+      assert "We are all good!" in client.succeed("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server/index.txt")
+
+    with subtest("h3-cert-auth"):
+      # Client must succeed in authenticating with the right certificate.
+      assert "We are all good!" in client.succeed("curl -f --http3-only --cacert /etc/ssl/cacert.crt --cert-type pem --cert /root/client.pem https://server:8443/index.txt")
+      # Client must fail without certificate.
+      client.fail("curl -f --http3-only --cacert /etc/ssl/cacert.crt https://server:8443/index.txt")
 
     with subtest("reload"):
-        machine.succeed("systemctl reload haproxy")
+        server.succeed("systemctl reload haproxy")
         # wait some time to ensure the following request hits the reloaded haproxy
-        machine.sleep(5)
-        assert "We are all good!" in machine.succeed(
-            "curl -fk http://localhost:80/index.txt"
-        )
+        server.sleep(5)
+        assert "We are all good!" in client.succeed("curl -f http://server/index.txt")
   '';
 })
diff --git a/nixos/tests/hostname.nix b/nixos/tests/hostname.nix
index 6122e2ffeb83a..dffec956bc0b6 100644
--- a/nixos/tests/hostname.nix
+++ b/nixos/tests/hostname.nix
@@ -34,6 +34,7 @@ let
 
         machine = ${hostName}
 
+        machine.systemctl("start network-online.target")
         machine.wait_for_unit("network-online.target")
 
         # Test if NixOS computes the correct FQDN (either a FQDN or an error/null):
diff --git a/nixos/tests/incus/default.nix b/nixos/tests/incus/default.nix
index c88974605e306..26e8a4ac4c772 100644
--- a/nixos/tests/incus/default.nix
+++ b/nixos/tests/incus/default.nix
@@ -6,9 +6,8 @@
 }:
 {
   container = import ./container.nix { inherit system pkgs; };
+  lxd-to-incus = import ./lxd-to-incus.nix { inherit system pkgs; };
   preseed = import ./preseed.nix { inherit system pkgs; };
   socket-activated = import ./socket-activated.nix { inherit system pkgs; };
-  virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix {
-    inherit system pkgs;
-  };
+  virtual-machine = handleTestOn [ "x86_64-linux" ] ./virtual-machine.nix { inherit system pkgs; };
 }
diff --git a/nixos/tests/incus/lxd-to-incus.nix b/nixos/tests/incus/lxd-to-incus.nix
new file mode 100644
index 0000000000000..67245b54e7527
--- /dev/null
+++ b/nixos/tests/incus/lxd-to-incus.nix
@@ -0,0 +1,112 @@
+import ../make-test-python.nix (
+
+  { pkgs, lib, ... }:
+
+  let
+    releases = import ../../release.nix { configuration.documentation.enable = lib.mkForce false; };
+
+    container-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system};
+    container-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system};
+  in
+  {
+    name = "lxd-to-incus";
+
+    meta = {
+      maintainers = lib.teams.lxc.members;
+    };
+
+    nodes.machine =
+      { lib, ... }:
+      {
+        environment.systemPackages = [ pkgs.lxd-to-incus ];
+
+        virtualisation = {
+          diskSize = 6144;
+          cores = 2;
+          memorySize = 2048;
+
+          lxd.enable = true;
+          lxd.preseed = {
+            networks = [
+              {
+                name = "nixostestbr0";
+                type = "bridge";
+                config = {
+                  "ipv4.address" = "10.0.100.1/24";
+                  "ipv4.nat" = "true";
+                };
+              }
+            ];
+            profiles = [
+              {
+                name = "default";
+                devices = {
+                  eth0 = {
+                    name = "eth0";
+                    network = "nixostestbr0";
+                    type = "nic";
+                  };
+                  root = {
+                    path = "/";
+                    pool = "nixostest_pool";
+                    size = "35GiB";
+                    type = "disk";
+                  };
+                };
+              }
+              {
+                name = "nixos_notdefault";
+                devices = { };
+              }
+            ];
+            storage_pools = [
+              {
+                name = "nixostest_pool";
+                driver = "dir";
+              }
+            ];
+          };
+
+          incus.enable = true;
+        };
+      };
+
+    testScript = ''
+      def lxd_wait_for_preseed(_) -> bool:
+        _, output = machine.systemctl("is-active lxd-preseed.service")
+        return ("inactive" in output)
+
+      def lxd_instance_is_up(_) -> bool:
+          status, _ = machine.execute("lxc exec container --disable-stdin --force-interactive /run/current-system/sw/bin/true")
+          return status == 0
+
+      def incus_instance_is_up(_) -> bool:
+          status, _ = machine.execute("incus exec container --disable-stdin --force-interactive /run/current-system/sw/bin/true")
+          return status == 0
+
+      with machine.nested("initialize lxd and resources"):
+        machine.wait_for_unit("sockets.target")
+        machine.wait_for_unit("lxd.service")
+        retry(lxd_wait_for_preseed)
+
+        machine.succeed("lxc image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs}/*/*.tar.xz --alias nixos")
+        machine.succeed("lxc launch nixos container")
+        retry(lxd_instance_is_up)
+
+      machine.wait_for_unit("incus.service")
+
+      with machine.nested("run migration"):
+          machine.succeed("lxd-to-incus --yes")
+
+      with machine.nested("verify resources migrated to incus"):
+          machine.succeed("incus config show container")
+          retry(incus_instance_is_up)
+          machine.succeed("incus exec container -- true")
+          machine.succeed("incus profile show default | grep nixostestbr0")
+          machine.succeed("incus profile show default | grep nixostest_pool")
+          machine.succeed("incus profile show nixos_notdefault")
+          machine.succeed("incus storage show nixostest_pool")
+          machine.succeed("incus network show nixostestbr0")
+    '';
+  }
+)
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 21d5e1470d8e0..7576fae41f83b 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -158,7 +158,9 @@ let
       start_all()
       ${optionalString clevisTest ''
       tang.wait_for_unit("sockets.target")
+      tang.systemctl("start network-online.target")
       tang.wait_for_unit("network-online.target")
+      machine.systemctl("start network-online.target")
       machine.wait_for_unit("network-online.target")
       ''}
       machine.wait_for_unit("multi-user.target")
@@ -187,6 +189,7 @@ let
 
       ${optionalString clevisTest ''
         with subtest("Create the Clevis secret with Tang"):
+             machine.systemctl("start network-online.target")
              machine.wait_for_unit("network-online.target")
              machine.succeed('echo -n password | clevis encrypt sss \'{"t": 2, "pins": {"tpm2": {}, "tang": {"url": "http://192.168.1.2"}}}\' -y > /mnt/etc/nixos/clevis-secret.jwe')''}
 
diff --git a/nixos/tests/kanidm.nix b/nixos/tests/kanidm.nix
index 3f5bca397740e..fa24d4a8a5e13 100644
--- a/nixos/tests/kanidm.nix
+++ b/nixos/tests/kanidm.nix
@@ -67,6 +67,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
       ''
         start_all()
         server.wait_for_unit("kanidm.service")
+        client.systemctl("start network-online.target")
         client.wait_for_unit("network-online.target")
 
         with subtest("Test HTTP interface"):
diff --git a/nixos/tests/keepalived.nix b/nixos/tests/keepalived.nix
index d0bf9d4652003..ce291514591fe 100644
--- a/nixos/tests/keepalived.nix
+++ b/nixos/tests/keepalived.nix
@@ -1,5 +1,6 @@
-import ./make-test-python.nix ({ pkgs, ... }: {
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
   name = "keepalived";
+  maintainers = [ lib.maintainers.raitobezarius ];
 
   nodes = {
     node1 = { pkgs, ... }: {
diff --git a/nixos/tests/lemmy.nix b/nixos/tests/lemmy.nix
index de2c4938fe231..e8d747f89a9e7 100644
--- a/nixos/tests/lemmy.nix
+++ b/nixos/tests/lemmy.nix
@@ -59,6 +59,7 @@ in
         server.succeed("curl --fail localhost:${toString uiPort}")
 
     with subtest("Lemmy-UI responds through the caddy reverse proxy"):
+        server.systemctl("start network-online.target")
         server.wait_for_unit("network-online.target")
         server.wait_for_unit("caddy.service")
         server.wait_for_open_port(80)
@@ -66,6 +67,7 @@ in
         assert "Lemmy" in body, f"String Lemmy not found in response for ${lemmyNodeName}: \n{body}"
 
     with subtest("the server is exposed externally"):
+        client.systemctl("start network-online.target")
         client.wait_for_unit("network-online.target")
         client.succeed("curl -v --fail ${lemmyNodeName}")
 
diff --git a/nixos/tests/miriway.nix b/nixos/tests/miriway.nix
index f12c4d5ecc41e..a0987d9fc41b6 100644
--- a/nixos/tests/miriway.nix
+++ b/nixos/tests/miriway.nix
@@ -31,7 +31,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
         enable-x11=
 
         ctrl-alt=t:foot --maximized
-        ctrl-alt=a:env WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY=invalid alacritty --option window.startup_mode=maximized
+        ctrl-alt=a:env WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY= alacritty --option window.startup_mode=\"maximized\"
 
         shell-component=dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY
 
diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix
index 768d0cfa2238c..6bd89902eedb3 100644
--- a/nixos/tests/networking.nix
+++ b/nixos/tests/networking.nix
@@ -130,6 +130,7 @@ let
           start_all()
 
           client.wait_for_unit("network.target")
+          router.systemctl("start network-online.target")
           router.wait_for_unit("network-online.target")
 
           with subtest("Make sure DHCP server is not started"):
@@ -222,6 +223,7 @@ let
           start_all()
 
           client.wait_for_unit("network.target")
+          router.systemctl("start network-online.target")
           router.wait_for_unit("network-online.target")
 
           with subtest("Wait until we have an ip address on each interface"):
@@ -849,6 +851,7 @@ let
 
           client.wait_for_unit("network.target")
           client_with_privacy.wait_for_unit("network.target")
+          router.systemctl("start network-online.target")
           router.wait_for_unit("network-online.target")
 
           with subtest("Wait until we have an ip address"):
diff --git a/nixos/tests/nfs/kerberos.nix b/nixos/tests/nfs/kerberos.nix
index 1bace4058be59..5944b53319a0b 100644
--- a/nixos/tests/nfs/kerberos.nix
+++ b/nixos/tests/nfs/kerberos.nix
@@ -105,6 +105,7 @@ in
       server.wait_for_unit("rpc-gssd.service")
       server.wait_for_unit("rpc-svcgssd.service")
 
+      client.systemctl("start network-online.target")
       client.wait_for_unit("network-online.target")
 
       # add principals to client keytab
diff --git a/nixos/tests/nginx-moreheaders.nix b/nixos/tests/nginx-moreheaders.nix
new file mode 100644
index 0000000000000..560dcf9ce0b82
--- /dev/null
+++ b/nixos/tests/nginx-moreheaders.nix
@@ -0,0 +1,37 @@
+import ./make-test-python.nix {
+  name = "nginx-more-headers";
+
+  nodes = {
+    webserver = { pkgs, ... }: {
+      services.nginx = {
+        enable = true;
+
+        virtualHosts.test = {
+          locations = {
+            "/".return = "200 blub";
+            "/some" =  {
+              return = "200 blub";
+              extraConfig = ''
+                more_set_headers "Referrer-Policy: no-referrer";
+              '';
+            };
+          };
+          extraConfig = ''
+            more_set_headers "X-Powered-By: nixos";
+          '';
+        };
+      };
+    };
+  };
+
+  testScript = ''
+    webserver.wait_for_unit("nginx")
+    webserver.wait_for_open_port(80)
+
+    webserver.succeed("curl --fail --resolve test:80:127.0.0.1 --head --verbose http://test | grep -q \"X-Powered-By: nixos\"")
+    webserver.fail("curl --fail --resolve test:80:127.0.0.1 --head --verbose http://test | grep -q \"Referrer-Policy: no-referrer\"")
+
+    webserver.succeed("curl --fail --resolve test:80:127.0.0.1 --head --verbose http://test/some | grep -q \"X-Powered-By: nixos\"")
+    webserver.succeed("curl --fail --resolve test:80:127.0.0.1 --head --verbose http://test/some | grep -q \"Referrer-Policy: no-referrer\"")
+  '';
+}
diff --git a/nixos/tests/nixops/default.nix b/nixos/tests/nixops/default.nix
index f7a26f2461c4c..6501d13a2ed36 100644
--- a/nixos/tests/nixops/default.nix
+++ b/nixos/tests/nixops/default.nix
@@ -1,6 +1,4 @@
-{ pkgs
-, testers
-, ... }:
+{ pkgs, ... }:
 let
   inherit (pkgs) lib;
 
@@ -21,7 +19,7 @@ let
     passthru.override = args': testsForPackage (args // args');
   };
 
-  testLegacyNetwork = { nixopsPkg, ... }: testers.nixosTest ({
+  testLegacyNetwork = { nixopsPkg, ... }: pkgs.testers.nixosTest ({
     name = "nixops-legacy-network";
     nodes = {
       deployer = { config, lib, nodes, pkgs, ... }: {
diff --git a/nixos/tests/ntpd-rs.nix b/nixos/tests/ntpd-rs.nix
index 2901be5235208..6f3c80e87f072 100644
--- a/nixos/tests/ntpd-rs.nix
+++ b/nixos/tests/ntpd-rs.nix
@@ -41,9 +41,11 @@ import ./make-test-python.nix ({ lib, ... }:
 
   testScript = { nodes, ... }: ''
     start_all()
-    server.wait_for_unit('multi-user.target')
-    client.wait_for_unit('multi-user.target')
-    server.succeed('systemctl is-active ntpd-rs.service')
-    client.succeed('systemctl is-active ntpd-rs.service')
+
+    for machine in (server, client):
+      machine.wait_for_unit('multi-user.target')
+      machine.succeed('systemctl is-active ntpd-rs.service')
+      machine.succeed('systemctl is-active ntpd-rs-metrics.service')
+      machine.succeed('curl http://localhost:9975/metrics | grep ntp_uptime_seconds')
   '';
 })
diff --git a/nixos/tests/opensmtpd-rspamd.nix b/nixos/tests/opensmtpd-rspamd.nix
index 19969a7b47ddd..e413a2050bd61 100644
--- a/nixos/tests/opensmtpd-rspamd.nix
+++ b/nixos/tests/opensmtpd-rspamd.nix
@@ -119,6 +119,7 @@ import ./make-test-python.nix {
   testScript = ''
     start_all()
 
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
     smtp1.wait_for_unit("opensmtpd")
     smtp2.wait_for_unit("opensmtpd")
diff --git a/nixos/tests/opensmtpd.nix b/nixos/tests/opensmtpd.nix
index 17c1a569ba0d9..d32f82ed33b8c 100644
--- a/nixos/tests/opensmtpd.nix
+++ b/nixos/tests/opensmtpd.nix
@@ -104,6 +104,7 @@ import ./make-test-python.nix {
   testScript = ''
     start_all()
 
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
     smtp1.wait_for_unit("opensmtpd")
     smtp2.wait_for_unit("opensmtpd")
diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix
index 799497477993b..8074fd2ed4838 100644
--- a/nixos/tests/openssh.nix
+++ b/nixos/tests/openssh.nix
@@ -34,6 +34,19 @@ in {
         ];
       };
 
+    server-lazy-socket = {
+      virtualisation.vlans = [ 1 2 ];
+      services.openssh = {
+        enable = true;
+        startWhenNeeded = true;
+        ports = [ 2222 ];
+        listenAddresses = [ { addr = "0.0.0.0"; } ];
+      };
+      users.users.root.openssh.authorizedKeys.keys = [
+        snakeOilPublicKey
+      ];
+    };
+
     server-localhost-only =
       { ... }:
 
@@ -96,7 +109,9 @@ in {
       };
 
     client =
-      { ... }: { };
+      { ... }: {
+        virtualisation.vlans = [ 1 2 ];
+      };
 
   };
 
@@ -109,6 +124,7 @@ in {
 
     server_lazy.wait_for_unit("sshd.socket", timeout=30)
     server_localhost_only_lazy.wait_for_unit("sshd.socket", timeout=30)
+    server_lazy_socket.wait_for_unit("sshd.socket", timeout=30)
 
     with subtest("manual-authkey"):
         client.succeed("mkdir -m 700 /root/.ssh")
@@ -145,6 +161,16 @@ in {
             timeout=30
         )
 
+    with subtest("socket activation on a non-standard port"):
+        client.succeed(
+            "cat ${snakeOilPrivateKey} > privkey.snakeoil"
+        )
+        client.succeed("chmod 600 privkey.snakeoil")
+        client.succeed(
+            "ssh -p 2222 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil root@192.168.2.4 true",
+            timeout=30
+        )
+
     with subtest("configured-authkey"):
         client.succeed(
             "cat ${snakeOilPrivateKey} > privkey.snakeoil"
diff --git a/nixos/tests/owncast.nix b/nixos/tests/owncast.nix
index debb34f5009dc..73aac4e704751 100644
--- a/nixos/tests/owncast.nix
+++ b/nixos/tests/owncast.nix
@@ -31,6 +31,8 @@ import ./make-test-python.nix ({ pkgs, ... }: {
   testScript = ''
     start_all()
 
+    client.systemctl("start network-online.target")
+    server.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
     server.wait_for_unit("network-online.target")
     server.wait_for_unit("owncast.service")
diff --git a/nixos/tests/podman/default.nix b/nixos/tests/podman/default.nix
index 0e1f420f2a7de..3eea45832f0a6 100644
--- a/nixos/tests/podman/default.nix
+++ b/nixos/tests/podman/default.nix
@@ -24,8 +24,6 @@ import ../make-test-python.nix (
         virtualisation.podman.enable = true;
 
         virtualisation.podman.defaultNetwork.settings.dns_enabled = true;
-
-        networking.firewall.allowedUDPPorts = [ 53 ];
       };
       docker = { pkgs, ... }: {
         virtualisation.podman.enable = true;
diff --git a/nixos/tests/postgis.nix b/nixos/tests/postgis.nix
index 09c738b938ba8..dacf4e576c071 100644
--- a/nixos/tests/postgis.nix
+++ b/nixos/tests/postgis.nix
@@ -24,6 +24,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     master.wait_for_unit("postgresql")
     master.sleep(10)  # Hopefully this is long enough!!
     master.succeed("sudo -u postgres psql -c 'CREATE EXTENSION postgis;'")
+    master.succeed("sudo -u postgres psql -c 'CREATE EXTENSION postgis_raster;'")
     master.succeed("sudo -u postgres psql -c 'CREATE EXTENSION postgis_topology;'")
   '';
 })
diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix
index 53e6626c0e324..5872b02b609e1 100644
--- a/nixos/tests/prometheus-exporters.nix
+++ b/nixos/tests/prometheus-exporters.nix
@@ -1392,9 +1392,11 @@ let
     snmp = {
       exporterConfig = {
         enable = true;
-        configuration.default = {
-          version = 2;
-          auth.community = "public";
+        configuration = {
+          auths.public_v2 = {
+            community = "public";
+            version = 2;
+          };
         };
       };
       exporterTest = ''
diff --git a/nixos/tests/qemu-vm-restrictnetwork.nix b/nixos/tests/qemu-vm-restrictnetwork.nix
index 49a105ef10767..49aefcc099bda 100644
--- a/nixos/tests/qemu-vm-restrictnetwork.nix
+++ b/nixos/tests/qemu-vm-restrictnetwork.nix
@@ -21,6 +21,8 @@ import ./make-test-python.nix ({
 
     else:
       start_all()
+      unrestricted.systemctl("start network-online.target")
+      restricted.systemctl("start network-online.target")
       unrestricted.wait_for_unit("network-online.target")
       restricted.wait_for_unit("network-online.target")
 
diff --git a/nixos/tests/rss2email.nix b/nixos/tests/rss2email.nix
index f32326feb50fb..60b27b95fabe4 100644
--- a/nixos/tests/rss2email.nix
+++ b/nixos/tests/rss2email.nix
@@ -55,6 +55,7 @@ import ./make-test-python.nix {
   testScript = ''
     start_all()
 
+    server.systemctl("start network-online.target")
     server.wait_for_unit("network-online.target")
     server.wait_for_unit("opensmtpd")
     server.wait_for_unit("dovecot2")
diff --git a/nixos/tests/ssh-audit.nix b/nixos/tests/ssh-audit.nix
index bd6255b8044d9..25772aba3ea08 100644
--- a/nixos/tests/ssh-audit.nix
+++ b/nixos/tests/ssh-audit.nix
@@ -70,6 +70,7 @@ import ./make-test-python.nix (
       ${serverName}.succeed("${pkgs.ssh-audit}/bin/ssh-audit 127.0.0.1")
 
       # Wait for client to be able to connect to the server
+      ${clientName}.systemctl("start network-online.target")
       ${clientName}.wait_for_unit("network-online.target")
 
       # Set up trusted private key
diff --git a/nixos/tests/suwayomi-server.nix b/nixos/tests/suwayomi-server.nix
new file mode 100644
index 0000000000000..36072028380b8
--- /dev/null
+++ b/nixos/tests/suwayomi-server.nix
@@ -0,0 +1,46 @@
+{ system ? builtins.currentSystem
+, pkgs
+, lib ? pkgs.lib
+}:
+let
+  inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
+  inherit (lib) recursiveUpdate;
+
+  baseTestConfig = {
+    meta.maintainers = with lib.maintainers; [ ratcornu ];
+    nodes.machine = { pkgs, ... }: {
+      services.suwayomi-server = {
+        enable = true;
+        settings.server.port = 1234;
+      };
+    };
+    testScript = ''
+      machine.wait_for_unit("suwayomi-server.service")
+      machine.wait_for_open_port(1234)
+      machine.succeed("curl --fail http://localhost:1234/")
+    '';
+  };
+in
+
+{
+  without-auth = makeTest (recursiveUpdate baseTestConfig {
+    name = "suwayomi-server-without-auth";
+  });
+
+  with-auth = makeTest (recursiveUpdate baseTestConfig {
+    name = "suwayomi-server-with-auth";
+
+    nodes.machine = { pkgs, ... }: {
+      services.suwayomi-server = {
+        enable = true;
+
+        settings.server = {
+          port = 1234;
+          basicAuthEnabled = true;
+          basicAuthUsername = "alice";
+          basicAuthPasswordFile = pkgs.writeText "snakeoil-pass.txt" "pass";
+        };
+      };
+    };
+  });
+}
diff --git a/nixos/tests/sysinit-reactivation.nix b/nixos/tests/sysinit-reactivation.nix
new file mode 100644
index 0000000000000..1a0caecb610a3
--- /dev/null
+++ b/nixos/tests/sysinit-reactivation.nix
@@ -0,0 +1,107 @@
+# This runs to two scenarios but in one tests:
+# - A post-sysinit service needs to be restarted AFTER tmpfiles was restarted.
+# - A service needs to be restarted BEFORE tmpfiles is restarted
+
+{ lib, ... }:
+
+let
+  makeGeneration = generation: {
+    "${generation}".configuration = {
+      systemd.services.pre-sysinit-before-tmpfiles.environment.USER =
+        lib.mkForce "${generation}-tmpfiles-user";
+
+      systemd.services.pre-sysinit-after-tmpfiles.environment = {
+        NEEDED_PATH = lib.mkForce "/run/${generation}-needed-by-pre-sysinit-after-tmpfiles";
+        PATH_TO_CREATE = lib.mkForce "/run/${generation}-needed-by-post-sysinit";
+      };
+
+      systemd.services.post-sysinit.environment = {
+        NEEDED_PATH = lib.mkForce "/run/${generation}-needed-by-post-sysinit";
+        PATH_TO_CREATE = lib.mkForce "/run/${generation}-created-by-post-sysinit";
+      };
+
+      systemd.tmpfiles.settings.test = lib.mkForce {
+        "/run/${generation}-needed-by-pre-sysinit-after-tmpfiles".f.user =
+          "${generation}-tmpfiles-user";
+      };
+    };
+  };
+in
+
+{
+
+  name = "sysinit-reactivation";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { config, lib, pkgs, ... }: {
+    systemd.services.pre-sysinit-before-tmpfiles = {
+      wantedBy = [ "sysinit.target" ];
+      requiredBy = [ "sysinit-reactivation.target" ];
+      before = [ "systemd-tmpfiles-setup.service" "systemd-tmpfiles-resetup.service" ];
+      unitConfig.DefaultDependencies = false;
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+      environment.USER = "tmpfiles-user";
+      script = "${pkgs.shadow}/bin/useradd $USER";
+    };
+
+    systemd.services.pre-sysinit-after-tmpfiles = {
+      wantedBy = [ "sysinit.target" ];
+      requiredBy = [ "sysinit-reactivation.target" ];
+      after = [ "systemd-tmpfiles-setup.service" "systemd-tmpfiles-resetup.service" ];
+      unitConfig.DefaultDependencies = false;
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+      environment = {
+        NEEDED_PATH = "/run/needed-by-pre-sysinit-after-tmpfiles";
+        PATH_TO_CREATE = "/run/needed-by-post-sysinit";
+      };
+      script = ''
+        if [[ -e $NEEDED_PATH ]]; then
+          touch $PATH_TO_CREATE
+        fi
+      '';
+    };
+
+    systemd.services.post-sysinit = {
+      wantedBy = [ "default.target" ];
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+      environment = {
+        NEEDED_PATH = "/run/needed-by-post-sysinit";
+        PATH_TO_CREATE = "/run/created-by-post-sysinit";
+      };
+      script = ''
+        if [[ -e $NEEDED_PATH ]]; then
+          touch $PATH_TO_CREATE
+        fi
+      '';
+    };
+
+    systemd.tmpfiles.settings.test = {
+      "/run/needed-by-pre-sysinit-after-tmpfiles".f.user =
+        "tmpfiles-user";
+    };
+
+    specialisation = lib.mkMerge [
+      (makeGeneration "second")
+      (makeGeneration "third")
+    ];
+  };
+
+  testScript = { nodes, ... }: ''
+    def switch(generation):
+      toplevel = "${nodes.machine.system.build.toplevel}";
+      machine.succeed(f"{toplevel}/specialisation/{generation}/bin/switch-to-configuration switch")
+
+    machine.wait_for_unit("default.target")
+    machine.succeed("test -e /run/created-by-post-sysinit")
+
+    switch("second")
+    machine.succeed("test -e /run/second-created-by-post-sysinit")
+
+    switch("third")
+    machine.succeed("test -e /run/third-created-by-post-sysinit")
+  '';
+}
diff --git a/nixos/tests/systemd-networkd-dhcpserver.nix b/nixos/tests/systemd-networkd-dhcpserver.nix
index cf0ccb7442118..665d8b5a05291 100644
--- a/nixos/tests/systemd-networkd-dhcpserver.nix
+++ b/nixos/tests/systemd-networkd-dhcpserver.nix
@@ -101,6 +101,9 @@ import ./make-test-python.nix ({pkgs, ...}: {
   };
   testScript = { ... }: ''
     start_all()
+
+    router.systemctl("start network-online.target")
+    client.systemctl("start network-online.target")
     router.wait_for_unit("systemd-networkd-wait-online.service")
     client.wait_for_unit("systemd-networkd-wait-online.service")
     client.wait_until_succeeds("ping -c 5 10.0.2.1")
diff --git a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
index 54f371e6c070f..1e55341657bdb 100644
--- a/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
+++ b/nixos/tests/systemd-networkd-ipv6-prefix-delegation.nix
@@ -263,9 +263,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
           };
         };
       };
-
-      # make the network-online target a requirement, we wait for it in our test script
-      systemd.targets.network-online.wantedBy = [ "multi-user.target" ];
     };
 
     # This is the client behind the router. We should be receiving router
@@ -278,9 +275,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
         useNetworkd = true;
         useDHCP = false;
       };
-
-      # make the network-online target a requirement, we wait for it in our test script
-      systemd.targets.network-online.wantedBy = [ "multi-user.target" ];
     };
   };
 
@@ -294,6 +288,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     # Since we only care about IPv6 that should not involve waiting for legacy
     # IP leases.
     client.start()
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
 
     # the static address on the router should not be reachable
@@ -312,6 +307,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
     isp.wait_for_unit("multi-user.target")
 
     # wait until the uplink interface has a good status
+    router.systemctl("start network-online.target")
     router.wait_for_unit("network-online.target")
     router.wait_until_succeeds("ping -6 -c1 2001:DB8::1")
 
diff --git a/nixos/tests/systemd-nspawn.nix b/nixos/tests/systemd-nspawn.nix
index 1a4251ef069e8..b86762233d183 100644
--- a/nixos/tests/systemd-nspawn.nix
+++ b/nixos/tests/systemd-nspawn.nix
@@ -38,6 +38,7 @@ in {
     start_all()
 
     server.wait_for_unit("nginx.service")
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
     client.succeed("machinectl pull-raw --verify=signature http://server/testimage.raw")
     client.succeed(
diff --git a/nixos/tests/systemd-sysusers-immutable.nix b/nixos/tests/systemd-sysusers-immutable.nix
new file mode 100644
index 0000000000000..42cbf84d175e4
--- /dev/null
+++ b/nixos/tests/systemd-sysusers-immutable.nix
@@ -0,0 +1,64 @@
+{ lib, ... }:
+
+let
+  rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
+  normaloPassword = "$y$j9T$3aiOV/8CADAK22OK2QT3/0$67OKd50Z4qTaZ8c/eRWHLIM.o3ujtC1.n9ysmJfv639";
+  newNormaloPassword = "mellow";
+in
+
+{
+
+  name = "activation-sysusers-immutable";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = {
+    systemd.sysusers.enable = true;
+    users.mutableUsers = false;
+
+    # Override the empty root password set by the test instrumentation
+    users.users.root.hashedPasswordFile = lib.mkForce null;
+    users.users.root.initialHashedPassword = rootPassword;
+    users.users.normalo = {
+      isNormalUser = true;
+      initialHashedPassword = normaloPassword;
+    };
+
+    specialisation.new-generation.configuration = {
+      users.users.new-normalo = {
+        isNormalUser = true;
+        initialPassword = newNormaloPassword;
+      };
+    };
+  };
+
+  testScript = ''
+    with subtest("Users are not created with systemd-sysusers"):
+      machine.fail("systemctl status systemd-sysusers.service")
+      machine.fail("ls /etc/sysusers.d")
+
+    with subtest("Correct mode on the password files"):
+      assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
+      assert machine.succeed("stat -c '%a' /etc/group") == "644\n"
+      assert machine.succeed("stat -c '%a' /etc/shadow") == "0\n"
+      assert machine.succeed("stat -c '%a' /etc/gshadow") == "0\n"
+
+    with subtest("root user has correct password"):
+      print(machine.succeed("getent passwd root"))
+      assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
+
+    with subtest("normalo user is created"):
+      print(machine.succeed("getent passwd normalo"))
+      assert machine.succeed("stat -c '%U' /home/normalo") == "normalo\n"
+      assert "${normaloPassword}" in machine.succeed("getent shadow normalo"), "normalo user password is not correct"
+
+
+    machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
+
+
+    with subtest("new-normalo user is created after switching to new generation"):
+      print(machine.succeed("getent passwd new-normalo"))
+      print(machine.succeed("getent shadow new-normalo"))
+      assert machine.succeed("stat -c '%U' /home/new-normalo") == "new-normalo\n"
+  '';
+}
diff --git a/nixos/tests/systemd-sysusers-mutable.nix b/nixos/tests/systemd-sysusers-mutable.nix
new file mode 100644
index 0000000000000..e69cfe23a59a1
--- /dev/null
+++ b/nixos/tests/systemd-sysusers-mutable.nix
@@ -0,0 +1,71 @@
+{ lib, ... }:
+
+let
+  rootPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
+  normaloPassword = "hello";
+  newNormaloPassword = "$y$j9T$p6OI0WN7.rSfZBOijjRdR.$xUOA2MTcB48ac.9Oc5fz8cxwLv1mMqabnn333iOzSA6";
+in
+
+{
+
+  name = "activation-sysusers-mutable";
+
+  meta.maintainers = with lib.maintainers; [ nikstur ];
+
+  nodes.machine = { pkgs, ... }: {
+    systemd.sysusers.enable = true;
+    users.mutableUsers = true;
+
+    # Prerequisites
+    system.etc.overlay.enable = true;
+    boot.initrd.systemd.enable = true;
+    boot.kernelPackages = pkgs.linuxPackages_latest;
+
+    # Override the empty root password set by the test instrumentation
+    users.users.root.hashedPasswordFile = lib.mkForce null;
+    users.users.root.initialHashedPassword = rootPassword;
+    users.users.normalo = {
+      isNormalUser = true;
+      initialPassword = normaloPassword;
+    };
+
+    specialisation.new-generation.configuration = {
+      users.users.new-normalo = {
+        isNormalUser = true;
+        initialHashedPassword = newNormaloPassword;
+      };
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("systemd-sysusers.service")
+
+    with subtest("systemd-sysusers.service contains the credentials"):
+      sysusers_service = machine.succeed("systemctl cat systemd-sysusers.service")
+      print(sysusers_service)
+      assert "SetCredential=passwd.plaintext-password.normalo:${normaloPassword}" in sysusers_service
+
+    with subtest("Correct mode on the password files"):
+      assert machine.succeed("stat -c '%a' /etc/passwd") == "644\n"
+      assert machine.succeed("stat -c '%a' /etc/group") == "644\n"
+      assert machine.succeed("stat -c '%a' /etc/shadow") == "0\n"
+      assert machine.succeed("stat -c '%a' /etc/gshadow") == "0\n"
+
+    with subtest("root user has correct password"):
+      print(machine.succeed("getent passwd root"))
+      assert "${rootPassword}" in machine.succeed("getent shadow root"), "root user password is not correct"
+
+    with subtest("normalo user is created"):
+      print(machine.succeed("getent passwd normalo"))
+      assert machine.succeed("stat -c '%U' /home/normalo") == "normalo\n"
+
+
+    machine.succeed("/run/current-system/specialisation/new-generation/bin/switch-to-configuration switch")
+
+
+    with subtest("new-normalo user is created after switching to new generation"):
+      print(machine.succeed("getent passwd new-normalo"))
+      assert machine.succeed("stat -c '%U' /home/new-normalo") == "new-normalo\n"
+      assert "${newNormaloPassword}" in machine.succeed("getent shadow new-normalo"), "new-normalo user password is not correct"
+  '';
+}
diff --git a/nixos/tests/tayga.nix b/nixos/tests/tayga.nix
index 44974f6efea83..4aade67d74d0d 100644
--- a/nixos/tests/tayga.nix
+++ b/nixos/tests/tayga.nix
@@ -206,6 +206,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
   testScript = ''
     # start client and server
     for machine in client, server:
+      machine.systemctl("start network-online.target")
       machine.wait_for_unit("network-online.target")
       machine.log(machine.execute("ip addr")[1])
       machine.log(machine.execute("ip route")[1])
@@ -214,6 +215,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
     # test systemd-networkd and nixos-scripts based router
     for router in router_systemd, router_nixos:
       router.start()
+      router.systemctl("start network-online.target")
       router.wait_for_unit("network-online.target")
       router.wait_for_unit("tayga.service")
       router.log(machine.execute("ip addr")[1])
diff --git a/nixos/tests/terminal-emulators.nix b/nixos/tests/terminal-emulators.nix
index efaac03e19837..3c1188ca88c99 100644
--- a/nixos/tests/terminal-emulators.nix
+++ b/nixos/tests/terminal-emulators.nix
@@ -61,6 +61,8 @@ let tests = {
 
       konsole.pkg = p: p.plasma5Packages.konsole;
 
+      lomiri-terminal-app.pkg = p: p.lomiri.lomiri-terminal-app;
+
       lxterminal.pkg = p: p.lxterminal;
 
       mate-terminal.pkg = p: p.mate.mate-terminal;
diff --git a/nixos/tests/trafficserver.nix b/nixos/tests/trafficserver.nix
index e4557c6c50e54..94d0e4dd926e9 100644
--- a/nixos/tests/trafficserver.nix
+++ b/nixos/tests/trafficserver.nix
@@ -104,6 +104,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
     ats.wait_for_open_port(80)
     httpbin.wait_for_unit("httpbin")
     httpbin.wait_for_open_port(80)
+    client.systemctl("start network-online.target")
     client.wait_for_unit("network-online.target")
 
     with subtest("Traffic Server is running"):
diff --git a/nixos/tests/ulogd/ulogd.py b/nixos/tests/ulogd/ulogd.py
index d20daa4d733a2..76a8d0c6e24a3 100644
--- a/nixos/tests/ulogd/ulogd.py
+++ b/nixos/tests/ulogd/ulogd.py
@@ -1,5 +1,6 @@
 start_all()
 machine.wait_for_unit("ulogd.service")
+machine.systemctl("start network-online.target")
 machine.wait_for_unit("network-online.target")
 
 with subtest("Ulogd is running"):
diff --git a/nixos/tests/upnp.nix b/nixos/tests/upnp.nix
index 5e135267403bd..93bc08f752ce3 100644
--- a/nixos/tests/upnp.nix
+++ b/nixos/tests/upnp.nix
@@ -81,11 +81,13 @@ in
       start_all()
 
       # Wait for network and miniupnpd.
+      router.systemctl("start network-online.target")
       router.wait_for_unit("network-online.target")
       # $router.wait_for_unit("nat")
       router.wait_for_unit("${if useNftables then "nftables" else "firewall"}.service")
       router.wait_for_unit("miniupnpd")
 
+      client1.systemctl("start network-online.target")
       client1.wait_for_unit("network-online.target")
 
       client1.succeed("upnpc -a ${internalClient1Address} 9000 9000 TCP")
diff --git a/nixos/tests/uptermd.nix b/nixos/tests/uptermd.nix
index 429e3c9dd5ff3..469aa5047c27c 100644
--- a/nixos/tests/uptermd.nix
+++ b/nixos/tests/uptermd.nix
@@ -28,6 +28,7 @@ in
     start_all()
 
     server.wait_for_unit("uptermd.service")
+    server.systemctl("start network-online.target")
     server.wait_for_unit("network-online.target")
 
     # wait for upterm port to be reachable
diff --git a/nixos/tests/watchdogd.nix b/nixos/tests/watchdogd.nix
new file mode 100644
index 0000000000000..663e97cbae104
--- /dev/null
+++ b/nixos/tests/watchdogd.nix
@@ -0,0 +1,22 @@
+import ./make-test-python.nix ({ lib, ... }: {
+  name = "watchdogd";
+  meta.maintainers = with lib.maintainers; [ vifino ];
+
+  nodes.machine = { pkgs, ... }: {
+    virtualisation.qemu.options = [
+      "-device i6300esb" # virtual watchdog timer
+    ];
+    boot.kernelModules = [ "i6300esb" ];
+    services.watchdogd.enable = true;
+    services.watchdogd.settings = {
+      supervisor.enabled = true;
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("watchdogd.service")
+
+    assert "i6300ESB" in machine.succeed("watchdogctl status")
+    machine.succeed("watchdogctl test")
+  '';
+})
diff --git a/nixos/tests/web-apps/netbox-upgrade.nix b/nixos/tests/web-apps/netbox-upgrade.nix
index b5403eb678bcb..4c554e7ae613b 100644
--- a/nixos/tests/web-apps/netbox-upgrade.nix
+++ b/nixos/tests/web-apps/netbox-upgrade.nix
@@ -1,6 +1,6 @@
 import ../make-test-python.nix ({ lib, pkgs, ... }: let
-  oldNetbox = pkgs.netbox_3_5;
-  newNetbox = pkgs.netbox_3_6;
+  oldNetbox = pkgs.netbox_3_6;
+  newNetbox = pkgs.netbox_3_7;
 in {
   name = "netbox-upgrade";
 
diff --git a/nixos/tests/web-servers/stargazer.nix b/nixos/tests/web-servers/stargazer.nix
index 6365d6a4fff10..f56d1b8c94545 100644
--- a/nixos/tests/web-servers/stargazer.nix
+++ b/nixos/tests/web-servers/stargazer.nix
@@ -1,4 +1,41 @@
 { pkgs, lib, ... }:
+let
+  test_script = pkgs.stdenv.mkDerivation rec {
+    pname = "stargazer-test-script";
+    inherit (pkgs.stargazer) version src;
+    buildInputs = with pkgs; [ (python3.withPackages (ps: with ps; [ cryptography ])) ];
+    dontBuild = true;
+    doCheck = false;
+    installPhase = ''
+      mkdir -p $out/bin
+      cp scripts/gemini-diagnostics $out/bin/test
+    '';
+  };
+  test_env = pkgs.stdenv.mkDerivation rec {
+    pname = "stargazer-test-env";
+    inherit (pkgs.stargazer) version src;
+    buildPhase = ''
+      cc test_data/cgi-bin/loop.c -o test_data/cgi-bin/loop
+    '';
+    doCheck = false;
+    installPhase = ''
+      mkdir -p $out
+      cp -r * $out/
+    '';
+  };
+  scgi_server = pkgs.stdenv.mkDerivation rec {
+    pname = "stargazer-test-scgi-server";
+    inherit (pkgs.stargazer) version src;
+    buildInputs = with pkgs; [ python3 ];
+    dontConfigure = true;
+    dontBuild = true;
+    doCheck = false;
+    installPhase = ''
+      mkdir -p $out/bin
+      cp scripts/scgi-server $out/bin/scgi-server
+    '';
+  };
+in
 {
   name = "stargazer";
   meta = with lib.maintainers; { maintainers = [ gaykitty ]; };
@@ -7,25 +44,84 @@
     geminiserver = { pkgs, ... }: {
       services.stargazer = {
         enable = true;
+        connectionLogging = false;
+        requestTimeout = 1;
         routes = [
           {
             route = "localhost";
-            root = toString (pkgs.writeTextDir "index.gmi" ''
-              # Hello NixOS!
-            '');
+            root = "${test_env}/test_data/test_site";
+          }
+          {
+            route = "localhost=/en.gmi";
+            root = "${test_env}/test_data/test_site";
+            lang = "en";
+            charset = "ascii";
+          }
+          {
+            route = "localhost~/(.*).gemini";
+            root = "${test_env}/test_data/test_site";
+            rewrite = "\\1.gmi";
+            lang = "en";
+            charset = "ascii";
+          }
+          {
+            route = "localhost=/plain.txt";
+            root = "${test_env}/test_data/test_site";
+            lang = "en";
+            charset = "ascii";
+            cert-path = "/var/lib/gemini/certs/localhost.crt";
+            key-path = "/var/lib/gemini/certs/localhost.key";
+          }
+          {
+            route = "localhost:/cgi-bin";
+            root = "${test_env}/test_data";
+            cgi = true;
+            cgi-timeout = 5;
+          }
+          {
+            route = "localhost:/scgi";
+            scgi = true;
+            scgi-address = "127.0.0.1:1099";
+          }
+          {
+            route = "localhost=/root";
+            redirect = "..";
+            permanent = true;
+          }
+          {
+            route = "localhost=/priv.gmi";
+            root = "${test_env}/test_data/test_site";
+            client-cert = "${test_env}/test_data/client_cert/good.crt";
+          }
+          {
+            route = "example.com~(.*)";
+            redirect = "gemini://localhost";
+            rewrite = "\\1";
+          }
+          {
+            route = "localhost:/no-exist";
+            root = "./does_not_exist";
           }
         ];
       };
+      systemd.services.scgi_server = {
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
+        serviceConfig = {
+          ExecStart = "${scgi_server}/bin/scgi-server";
+        };
+      };
     };
   };
 
   testScript = { nodes, ... }: ''
+    geminiserver.wait_for_unit("scgi_server")
+    geminiserver.wait_for_open_port(1099)
     geminiserver.wait_for_unit("stargazer")
     geminiserver.wait_for_open_port(1965)
 
-    with subtest("check is serving over gemini"):
-      response = geminiserver.succeed("${pkgs.gemget}/bin/gemget --header -o - gemini://localhost:1965")
+    with subtest("stargazer test suite"):
+      response = geminiserver.succeed("sh -c 'cd ${test_env}; ${test_script}/bin/test'")
       print(response)
-      assert "Hello NixOS!" in response
   '';
 }
diff --git a/nixos/tests/web-servers/ttyd.nix b/nixos/tests/web-servers/ttyd.nix
new file mode 100644
index 0000000000000..d161673684b31
--- /dev/null
+++ b/nixos/tests/web-servers/ttyd.nix
@@ -0,0 +1,19 @@
+import ../make-test-python.nix ({ lib, pkgs, ... }: {
+  name = "ttyd";
+  meta.maintainers = with lib.maintainers; [ stunkymonkey ];
+
+  nodes.machine = { pkgs, ... }: {
+    services.ttyd = {
+      enable = true;
+      username = "foo";
+      passwordFile = pkgs.writeText "password" "bar";
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("ttyd.service")
+    machine.wait_for_open_port(7681)
+    response = machine.succeed("curl -vvv -u foo:bar -s -H 'Host: ttyd' http://127.0.0.1:7681/")
+    assert '<title>ttyd - Terminal</title>' in response, "Page didn't load successfully"
+  '';
+})
diff --git a/nixos/tests/zrepl.nix b/nixos/tests/zrepl.nix
index b16c7eddc7aec..bdf11122c73f6 100644
--- a/nixos/tests/zrepl.nix
+++ b/nixos/tests/zrepl.nix
@@ -42,6 +42,7 @@ import ./make-test-python.nix (
       start_all()
 
       with subtest("Wait for zrepl and network ready"):
+          host.systemctl("start network-online.target")
           host.wait_for_unit("network-online.target")
           host.wait_for_unit("zrepl.service")