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/all-tests.nix5
-rw-r--r--nixos/tests/discourse.nix8
-rw-r--r--nixos/tests/gitea.nix8
-rwxr-xr-xnixos/tests/google-oslogin/server.py10
-rw-r--r--nixos/tests/home-assistant.nix107
-rw-r--r--nixos/tests/isso.nix2
-rw-r--r--nixos/tests/keepassxc.nix8
-rw-r--r--nixos/tests/miriway.nix6
-rw-r--r--nixos/tests/nextcloud/with-postgresql-and-redis.nix13
-rw-r--r--nixos/tests/podman/default.nix117
-rw-r--r--nixos/tests/soapui.nix2
-rw-r--r--nixos/tests/systemd-credentials-tpm2.nix124
-rw-r--r--nixos/tests/systemd-initrd-vconsole.nix33
-rw-r--r--nixos/tests/tuxguitar.nix2
14 files changed, 328 insertions, 117 deletions
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index ac15ecdad6b86..785a5621f57eb 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -228,6 +228,7 @@ in {
   fluentd = handleTest ./fluentd.nix {};
   fluidd = handleTest ./fluidd.nix {};
   fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {};
+  forgejo = handleTest ./gitea.nix { giteaPackage = pkgs.forgejo; };
   freenet = handleTest ./freenet.nix {};
   freeswitch = handleTest ./freeswitch.nix {};
   freshrss-sqlite = handleTest ./freshrss-sqlite.nix {};
@@ -241,7 +242,7 @@ in {
   geth = handleTest ./geth.nix {};
   ghostunnel = handleTest ./ghostunnel.nix {};
   gitdaemon = handleTest ./gitdaemon.nix {};
-  gitea = handleTest ./gitea.nix {};
+  gitea = handleTest ./gitea.nix { giteaPackage = pkgs.gitea; };
   gitlab = handleTest ./gitlab.nix {};
   gitolite = handleTest ./gitolite.nix {};
   gitolite-fcgiwrap = handleTest ./gitolite-fcgiwrap.nix {};
@@ -647,6 +648,7 @@ in {
   systemd-confinement = handleTest ./systemd-confinement.nix {};
   systemd-coredump = handleTest ./systemd-coredump.nix {};
   systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {};
+  systemd-credentials-tpm2 = handleTest ./systemd-credentials-tpm2.nix {};
   systemd-escaping = handleTest ./systemd-escaping.nix {};
   systemd-initrd-btrfs-raid = handleTest ./systemd-initrd-btrfs-raid.nix {};
   systemd-initrd-luks-fido2 = handleTest ./systemd-initrd-luks-fido2.nix {};
@@ -657,6 +659,7 @@ in {
   systemd-initrd-shutdown = handleTest ./systemd-shutdown.nix { systemdStage1 = true; };
   systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {};
   systemd-initrd-swraid = handleTest ./systemd-initrd-swraid.nix {};
+  systemd-initrd-vconsole = handleTest ./systemd-initrd-vconsole.nix {};
   systemd-journal = handleTest ./systemd-journal.nix {};
   systemd-machinectl = handleTest ./systemd-machinectl.nix {};
   systemd-networkd = handleTest ./systemd-networkd.nix {};
diff --git a/nixos/tests/discourse.nix b/nixos/tests/discourse.nix
index 35ca083c6c4e0..c79ba41c2eb9c 100644
--- a/nixos/tests/discourse.nix
+++ b/nixos/tests/discourse.nix
@@ -40,7 +40,7 @@ import ./make-test-python.nix (
 
         networking.extraHosts = ''
           127.0.0.1 ${discourseDomain}
-          ${nodes.client.config.networking.primaryIPAddress} ${clientDomain}
+          ${nodes.client.networking.primaryIPAddress} ${clientDomain}
         '';
 
         services.postfix = {
@@ -90,7 +90,7 @@ import ./make-test-python.nix (
 
         networking.extraHosts = ''
           127.0.0.1 ${clientDomain}
-          ${nodes.discourse.config.networking.primaryIPAddress} ${discourseDomain}
+          ${nodes.discourse.networking.primaryIPAddress} ${discourseDomain}
         '';
 
         services.dovecot2 = {
@@ -178,8 +178,8 @@ import ./make-test-python.nix (
         discourse.wait_until_succeeds("curl -sS -f https://${discourseDomain}")
         discourse.succeed(
             "curl -sS -f https://${discourseDomain}/session/csrf -c cookie -b cookie -H 'Accept: application/json' | jq -r '\"X-CSRF-Token: \" + .csrf' > csrf_token",
-            "curl -sS -f https://${discourseDomain}/session -c cookie -b cookie -H @csrf_token -H 'Accept: application/json' -d 'login=${nodes.discourse.config.services.discourse.admin.username}' -d \"password=${adminPassword}\" | jq -e '.user.username == \"${nodes.discourse.config.services.discourse.admin.username}\"'",
-            "curl -sS -f https://${discourseDomain}/login -v -H 'Accept: application/json' -c cookie -b cookie 2>&1 | grep ${nodes.discourse.config.services.discourse.admin.username}",
+            "curl -sS -f https://${discourseDomain}/session -c cookie -b cookie -H @csrf_token -H 'Accept: application/json' -d 'login=${nodes.discourse.services.discourse.admin.username}' -d \"password=${adminPassword}\" | jq -e '.user.username == \"${nodes.discourse.services.discourse.admin.username}\"'",
+            "curl -sS -f https://${discourseDomain}/login -v -H 'Accept: application/json' -c cookie -b cookie 2>&1 | grep ${nodes.discourse.services.discourse.admin.username}",
         )
 
         client.wait_for_unit("postfix.service")
diff --git a/nixos/tests/gitea.nix b/nixos/tests/gitea.nix
index 68a2566c11911..d856ecca9a132 100644
--- a/nixos/tests/gitea.nix
+++ b/nixos/tests/gitea.nix
@@ -1,5 +1,6 @@
 { system ? builtins.currentSystem,
   config ? {},
+  giteaPackage,
   pkgs ? import ../.. { inherit system config; }
 }:
 
@@ -9,8 +10,8 @@ with pkgs.lib;
 let
   supportedDbTypes = [ "mysql" "postgres" "sqlite3" ];
   makeGiteaTest = type: nameValuePair type (makeTest {
-    name = "gitea-${type}";
-    meta.maintainers = with maintainers; [ aanderse kolaente ma27 ];
+    name = "${giteaPackage.pname}-${type}";
+    meta.maintainers = with maintainers; [ aanderse indeednotjames kolaente ma27 ];
 
     nodes = {
       server = { config, pkgs, ... }: {
@@ -18,9 +19,10 @@ let
         services.gitea = {
           enable = true;
           database = { inherit type; };
+          package = giteaPackage;
           settings.service.DISABLE_REGISTRATION = true;
         };
-        environment.systemPackages = [ pkgs.gitea pkgs.jq ];
+        environment.systemPackages = [ giteaPackage pkgs.jq ];
         services.openssh.enable = true;
       };
       client1 = { config, pkgs, ... }: {
diff --git a/nixos/tests/google-oslogin/server.py b/nixos/tests/google-oslogin/server.py
index 5ea9bbd2c96ba..622cd86b26195 100755
--- a/nixos/tests/google-oslogin/server.py
+++ b/nixos/tests/google-oslogin/server.py
@@ -103,6 +103,16 @@ class ReqHandler(BaseHTTPRequestHandler):
             self._send_json_ok(gen_mockuser(username=username, uid=uid, gid=uid, home_directory=f"/home/{username}", snakeoil_pubkey=SNAKEOIL_PUBLIC_KEY))
             return
 
+        # we need to provide something at the groups endpoint.
+        # the nss module does segfault if we don't.
+        elif pu.path == "/computeMetadata/v1/oslogin/groups":
+            self._send_json_ok({
+                "posixGroups": [
+                    {"name" : "demo", "gid" : 4294967295}
+                ],
+            })
+            return
+
         # authorize endpoint
         elif pu.path == "/computeMetadata/v1/oslogin/authorize":
             # is user allowed to login?
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 8d58de75eabc3..8585cb3585fef 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -22,22 +22,23 @@ in {
       enable = true;
       inherit configDir;
 
-      # tests loading components by overriding the package
+      # provide dependencies through package overrides
       package = (pkgs.home-assistant.override {
         extraPackages = ps: with ps; [
           colorama
         ];
-        extraComponents = [ "zha" ];
-      }).overrideAttrs (oldAttrs: {
-        doInstallCheck = false;
+        extraComponents = [
+          # test char-tty device allow propagation into the service
+          "zha"
+         ];
       });
 
-      # tests loading components from the module
+      # provide component dependencies explicitly from the module
       extraComponents = [
-        "wake_on_lan"
+        "mqtt"
       ];
 
-      # test extra package passing from the module
+      # provide package for postgresql support
       extraPackages = python3Packages: with python3Packages; [
         psycopg2
       ];
@@ -111,36 +112,38 @@ in {
   };
 
   testScript = { nodes, ... }: let
-    system = nodes.hass.config.system.build.toplevel;
+    system = nodes.hass.system.build.toplevel;
   in
   ''
-    import re
     import json
 
     start_all()
 
-    # Parse the package path out of the systemd unit, as we cannot
-    # access the final package, that is overridden inside the module,
-    # by any other means.
-    pattern = re.compile(r"path=(?P<path>[\/a-z0-9-.]+)\/bin\/hass")
-    response = hass.execute("systemctl show -p ExecStart home-assistant.service")[1]
-    match = pattern.search(response)
-    assert match
-    package = match.group('path')
 
-
-    def get_journal_cursor(host) -> str:
-        exit, out = host.execute("journalctl -u home-assistant.service -n1 -o json-pretty --output-fields=__CURSOR")
+    def get_journal_cursor() -> str:
+        exit, out = hass.execute("journalctl -u home-assistant.service -n1 -o json-pretty --output-fields=__CURSOR")
         assert exit == 0
         return json.loads(out)["__CURSOR"]
 
 
-    def wait_for_homeassistant(host, cursor):
-        host.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u home-assistant.service | grep -q 'Home Assistant initialized in'")
+    def get_journal_since(cursor) -> str:
+        exit, out = hass.execute(f"journalctl --after-cursor='{cursor}' -u home-assistant.service")
+        assert exit == 0
+        return out
+
+
+    def get_unit_property(property) -> str:
+        exit, out = hass.execute(f"systemctl show --property={property} home-assistant.service")
+        assert exit == 0
+        return out
+
+
+    def wait_for_homeassistant(cursor):
+        hass.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u home-assistant.service | grep -q 'Home Assistant initialized in'")
 
 
     hass.wait_for_unit("home-assistant.service")
-    cursor = get_journal_cursor(hass)
+    cursor = get_journal_cursor()
 
     with subtest("Check that YAML configuration file is in place"):
         hass.succeed("test -L ${configDir}/configuration.yaml")
@@ -148,19 +151,22 @@ in {
     with subtest("Check the lovelace config is copied because lovelaceConfigWritable = true"):
         hass.succeed("test -f ${configDir}/ui-lovelace.yaml")
 
-    with subtest("Check extraComponents and extraPackages are considered from the package"):
-        hass.succeed(f"grep -q 'colorama' {package}/extra_packages")
-        hass.succeed(f"grep -q 'zha' {package}/extra_components")
-
-    with subtest("Check extraComponents and extraPackages are considered from the module"):
-        hass.succeed(f"grep -q 'psycopg2' {package}/extra_packages")
-        hass.succeed(f"grep -q 'wake_on_lan' {package}/extra_components")
-
     with subtest("Check that Home Assistant's web interface and API can be reached"):
-        wait_for_homeassistant(hass, cursor)
+        wait_for_homeassistant(cursor)
         hass.wait_for_open_port(8123)
         hass.succeed("curl --fail http://localhost:8123/lovelace")
 
+    with subtest("Check that optional dependencies are in the PYTHONPATH"):
+        env = get_unit_property("Environment")
+        python_path = env.split("PYTHONPATH=")[1].split()[0]
+        for package in ["colorama", "paho-mqtt", "psycopg2"]:
+            assert package in python_path, f"{package} not in PYTHONPATH"
+
+    with subtest("Check that declaratively configured components get setup"):
+        journal = get_journal_since(cursor)
+        for domain in ["emulated_hue", "wake_on_lan"]:
+            assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
+
     with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
         hass.wait_for_open_port(80)
         hass.succeed("curl --fail http://localhost:80/description.xml")
@@ -169,25 +175,28 @@ in {
         hass.succeed("systemctl show -p DeviceAllow home-assistant.service | grep -q char-ttyUSB")
 
     with subtest("Check service reloads when configuration changes"):
-      # store the old pid of the process
-      pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
-      cursor = get_journal_cursor(hass)
-      hass.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
-      new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
-      assert pid == new_pid, "The PID of the process should not change between process reloads"
-      wait_for_homeassistant(hass, cursor)
-
-    with subtest("check service restarts when package changes"):
-      pid = new_pid
-      cursor = get_journal_cursor(hass)
-      hass.succeed("${system}/specialisation/newFeature/bin/switch-to-configuration test")
-      new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
-      assert pid != new_pid, "The PID of the process shoudl change when the HA binary changes"
-      wait_for_homeassistant(hass, cursor)
+        pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
+        cursor = get_journal_cursor()
+        hass.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
+        new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
+        assert pid == new_pid, "The PID of the process should not change between process reloads"
+        wait_for_homeassistant(cursor)
+
+    with subtest("Check service restarts when dependencies change"):
+        pid = new_pid
+        cursor = get_journal_cursor()
+        hass.succeed("${system}/specialisation/newFeature/bin/switch-to-configuration test")
+        new_pid = hass.succeed("systemctl show --property=MainPID home-assistant.service")
+        assert pid != new_pid, "The PID of the process should change when its PYTHONPATH changess"
+        wait_for_homeassistant(cursor)
+
+    with subtest("Check that new components get setup after restart"):
+        journal = get_journal_since(cursor)
+        for domain in ["esphome"]:
+            assert f"Setup of domain {domain} took" in journal, f"{domain} setup missing"
 
     with subtest("Check that no errors were logged"):
-        output_log = hass.succeed("cat ${configDir}/home-assistant.log")
-        assert "ERROR" not in output_log
+        hass.fail("journalctl -u home-assistant -o cat | grep -q ERROR")
 
     with subtest("Check systemd unit hardening"):
         hass.log(hass.succeed("systemctl cat home-assistant.service"))
diff --git a/nixos/tests/isso.nix b/nixos/tests/isso.nix
index 575e1c52eccf6..4ec8b5ec3593d 100644
--- a/nixos/tests/isso.nix
+++ b/nixos/tests/isso.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, ... }: {
   name = "isso";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ asbachb ];
+    maintainers = [ ];
   };
 
   nodes.machine = { config, pkgs, ... }: {
diff --git a/nixos/tests/keepassxc.nix b/nixos/tests/keepassxc.nix
index debb469032a62..a4f452412cdf8 100644
--- a/nixos/tests/keepassxc.nix
+++ b/nixos/tests/keepassxc.nix
@@ -4,6 +4,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
   name = "keepassxc";
   meta = with pkgs.lib.maintainers; {
     maintainers = [ turion ];
+    timeout = 1800;
   };
 
   nodes.machine = { ... }:
@@ -55,9 +56,12 @@ import ./make-test-python.nix ({ pkgs, ...} :
         machine.sleep(5)
         # Regression #163482: keepassxc did not crash
         machine.succeed("ps -e | grep keepassxc")
-        machine.wait_for_text("foo.kdbx")
+        machine.wait_for_text("Open database")
         machine.send_key("ret")
-        machine.sleep(1)
+
+        # Wait for the enter password screen to appear.
+        machine.wait_for_text("/home/alice/foo.kdbx")
+
         # Click on "Browse" button to select keyfile
         machine.send_key("tab")
         machine.send_chars("/home/alice/foo.keyfile")
diff --git a/nixos/tests/miriway.nix b/nixos/tests/miriway.nix
index c4c50646f0153..d0d9f16d40f95 100644
--- a/nixos/tests/miriway.nix
+++ b/nixos/tests/miriway.nix
@@ -3,7 +3,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
 
   meta = {
     maintainers = with lib.maintainers; [ OPNA2608 ];
-    # FIXME On ARM Miriway inside the VM doesn't receive keyboard inputs, why?
+    # Natively running Mir has problems with capturing the first registered libinput device.
+    # In our VM  runners on ARM and on some hardware configs (my RPi4, distro-independent), this misses the keyboard.
+    # It can be worked around by dis- and reconnecting the affected hardware, but we can't do this in these tests.
+    # https://github.com/MirServer/mir/issues/2837
     broken = pkgs.stdenv.hostPlatform.isAarch;
   };
 
@@ -30,6 +33,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
       enable = true;
       config = ''
         add-wayland-extensions=all
+        enable-x11=
 
         ctrl-alt=t:foot --maximized
         ctrl-alt=a:env WINIT_UNIX_BACKEND=x11 WAYLAND_DISPLAY=invalid alacritty --option window.startup_mode=maximized
diff --git a/nixos/tests/nextcloud/with-postgresql-and-redis.nix b/nixos/tests/nextcloud/with-postgresql-and-redis.nix
index 1ef848cfb1217..d28c1bdfd6e1e 100644
--- a/nixos/tests/nextcloud/with-postgresql-and-redis.nix
+++ b/nixos/tests/nextcloud/with-postgresql-and-redis.nix
@@ -13,7 +13,7 @@ in {
     # The only thing the client needs to do is download a file.
     client = { ... }: {};
 
-    nextcloud = { config, pkgs, ... }: {
+    nextcloud = { config, pkgs, lib, ... }: {
       networking.firewall.allowedTCPPorts = [ 80 ];
 
       services.nextcloud = {
@@ -34,6 +34,15 @@ in {
           adminpassFile = toString (pkgs.writeText "admin-pass-file" ''
             ${adminpass}
           '');
+          trustedProxies = [ "::1" ];
+        };
+        notify_push = {
+          enable = true;
+          logLevel = "debug";
+        };
+        extraAppsEnable = true;
+        extraApps = {
+          inherit (pkgs."nextcloud${lib.versions.major config.services.nextcloud.package.version}Packages".apps) notify_push;
         };
       };
 
@@ -94,8 +103,10 @@ in {
         "${withRcloneEnv} ${copySharedFile}"
     )
     client.wait_for_unit("multi-user.target")
+    client.execute("${pkgs.nextcloud-notify_push.passthru.test_client}/bin/test_client http://nextcloud ${adminuser} ${adminpass} >&2 &")
     client.succeed(
         "${withRcloneEnv} ${diffSharedFile}"
     )
+    nextcloud.wait_until_succeeds("journalctl -u nextcloud-notify_push | grep -q \"Sending ping to ${adminuser}\"")
   '';
 })) args
diff --git a/nixos/tests/podman/default.nix b/nixos/tests/podman/default.nix
index c9b234d2b6092..69397197775f8 100644
--- a/nixos/tests/podman/default.nix
+++ b/nixos/tests/podman/default.nix
@@ -6,7 +6,10 @@ import ../make-test-python.nix (
     };
 
     nodes = {
-      podman = { pkgs, ... }: {
+      rootful = { pkgs, ... }: {
+        virtualisation.podman.enable = true;
+      };
+      rootless = { pkgs, ... }: {
         virtualisation.podman.enable = true;
 
         users.users.alice = {
@@ -49,101 +52,109 @@ import ../make-test-python.nix (
           return f"su {user} -l -c {cmd}"
 
 
-      podman.wait_for_unit("sockets.target")
+      rootful.wait_for_unit("sockets.target")
+      rootless.wait_for_unit("sockets.target")
       dns.wait_for_unit("sockets.target")
       docker.wait_for_unit("sockets.target")
       start_all()
 
       with subtest("Run container as root with runc"):
-          podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
-          podman.succeed(
+          rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
+          rootful.succeed(
               "podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
           )
-          podman.succeed("podman ps | grep sleeping")
-          podman.succeed("podman stop sleeping")
-          podman.succeed("podman rm sleeping")
+          rootful.succeed("podman ps | grep sleeping")
+          rootful.succeed("podman stop sleeping")
+          rootful.succeed("podman rm sleeping")
 
       with subtest("Run container as root with crun"):
-          podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
-          podman.succeed(
+          rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
+          rootful.succeed(
               "podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
           )
-          podman.succeed("podman ps | grep sleeping")
-          podman.succeed("podman stop sleeping")
-          podman.succeed("podman rm sleeping")
+          rootful.succeed("podman ps | grep sleeping")
+          rootful.succeed("podman stop sleeping")
+          rootful.succeed("podman rm sleeping")
 
       with subtest("Run container as root with the default backend"):
-          podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
-          podman.succeed(
+          rootful.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
+          rootful.succeed(
               "podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
           )
-          podman.succeed("podman ps | grep sleeping")
-          podman.succeed("podman stop sleeping")
-          podman.succeed("podman rm sleeping")
+          rootful.succeed("podman ps | grep sleeping")
+          rootful.succeed("podman stop sleeping")
+          rootful.succeed("podman rm sleeping")
 
       # start systemd session for rootless
-      podman.succeed("loginctl enable-linger alice")
-      podman.succeed(su_cmd("whoami"))
-      podman.sleep(1)
+      rootless.succeed("loginctl enable-linger alice")
+      rootless.succeed(su_cmd("whoami"))
+      rootless.sleep(1)
 
       with subtest("Run container rootless with runc"):
-          podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
-          podman.succeed(
+          rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
+          rootless.succeed(
               su_cmd(
                   "podman run --runtime=runc -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
               )
           )
-          podman.succeed(su_cmd("podman ps | grep sleeping"))
-          podman.succeed(su_cmd("podman stop sleeping"))
-          podman.succeed(su_cmd("podman rm sleeping"))
+          rootless.succeed(su_cmd("podman ps | grep sleeping"))
+          rootless.succeed(su_cmd("podman stop sleeping"))
+          rootless.succeed(su_cmd("podman rm sleeping"))
 
       with subtest("Run container rootless with crun"):
-          podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
-          podman.succeed(
+          rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
+          rootless.succeed(
               su_cmd(
                   "podman run --runtime=crun -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
               )
           )
-          podman.succeed(su_cmd("podman ps | grep sleeping"))
-          podman.succeed(su_cmd("podman stop sleeping"))
-          podman.succeed(su_cmd("podman rm sleeping"))
+          rootless.succeed(su_cmd("podman ps | grep sleeping"))
+          rootless.succeed(su_cmd("podman stop sleeping"))
+          rootless.succeed(su_cmd("podman rm sleeping"))
 
       with subtest("Run container rootless with the default backend"):
-          podman.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
-          podman.succeed(
+          rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
+          rootless.succeed(
               su_cmd(
                   "podman run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
               )
           )
-          podman.succeed(su_cmd("podman ps | grep sleeping"))
-          podman.succeed(su_cmd("podman stop sleeping"))
-          podman.succeed(su_cmd("podman rm sleeping"))
+          rootless.succeed(su_cmd("podman ps | grep sleeping"))
+          rootless.succeed(su_cmd("podman stop sleeping"))
+          rootless.succeed(su_cmd("podman rm sleeping"))
+
+      with subtest("rootlessport"):
+          rootless.succeed(su_cmd("tar cv --files-from /dev/null | podman import - scratchimg"))
+          rootless.succeed(
+              su_cmd(
+                  "podman run -d -p 9000:8888 --name=rootlessport -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Testing</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8888"
+              )
+          )
+          rootless.succeed(su_cmd("podman ps | grep rootlessport"))
+          rootless.wait_until_succeeds(su_cmd("${pkgs.curl}/bin/curl localhost:9000 | grep Testing"))
+          rootless.succeed(su_cmd("podman stop rootlessport"))
+          rootless.succeed(su_cmd("podman rm rootlessport"))
 
       with subtest("Run container with init"):
-          podman.succeed(
+          rootful.succeed(
               "tar cv -C ${pkgs.pkgsStatic.busybox} . | podman import - busybox"
           )
-          pid = podman.succeed("podman run --rm busybox readlink /proc/self").strip()
+          pid = rootful.succeed("podman run --rm busybox readlink /proc/self").strip()
           assert pid == "1"
-          pid = podman.succeed("podman run --rm --init busybox readlink /proc/self").strip()
+          pid = rootful.succeed("podman run --rm --init busybox readlink /proc/self").strip()
           assert pid == "2"
 
       with subtest("aardvark-dns"):
-        dns.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
-        dns.succeed(
-          "podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Hi</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8000"
-        )
-        dns.succeed("podman ps | grep webserver")
-        dns.succeed("""
-          for i in `seq 0 120`; do
-            podman run --rm --name=client -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg ${pkgs.curl}/bin/curl http://webserver:8000 >/dev/console \
-              && exit 0
-            sleep 0.5
-          done
-          exit 1
-        """)
-        dns.succeed("podman stop webserver")
-        dns.succeed("podman rm webserver")
+          dns.succeed("tar cv --files-from /dev/null | podman import - scratchimg")
+          dns.succeed(
+              "podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${pkgs.writeTextDir "index.html" "<h1>Testing</h1>"} scratchimg ${pkgs.python3}/bin/python -m http.server 8000"
+          )
+          dns.succeed("podman ps | grep webserver")
+          dns.wait_until_succeeds(
+              "podman run --rm --name=client -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg ${pkgs.curl}/bin/curl http://webserver:8000 | grep Testing"
+          )
+          dns.succeed("podman stop webserver")
+          dns.succeed("podman rm webserver")
 
       with subtest("A podman member can use the docker cli"):
           docker.succeed(su_cmd("docker version"))
diff --git a/nixos/tests/soapui.nix b/nixos/tests/soapui.nix
index e4ce3888fd437..3a2d11a167562 100644
--- a/nixos/tests/soapui.nix
+++ b/nixos/tests/soapui.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, ... }: {
   name = "soapui";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ asbachb ];
+    maintainers = [ ];
   };
 
   nodes.machine = { config, pkgs, ... }: {
diff --git a/nixos/tests/systemd-credentials-tpm2.nix b/nixos/tests/systemd-credentials-tpm2.nix
new file mode 100644
index 0000000000000..d2dc1fd7b615b
--- /dev/null
+++ b/nixos/tests/systemd-credentials-tpm2.nix
@@ -0,0 +1,124 @@
+import ./make-test-python.nix ({ lib, pkgs, system, ... }:
+
+let
+  tpmSocketPath = "/tmp/swtpm-sock";
+  tpmDeviceModels = {
+    x86_64-linux = "tpm-tis";
+    aarch64-linux = "tpm-tis-device";
+  };
+in
+
+{
+  name = "systemd-credentials-tpm2";
+
+  meta = {
+    maintainers = with pkgs.lib.maintainers; [ tmarkus ];
+  };
+
+  nodes.machine = { pkgs, ... }: {
+    virtualisation = {
+      qemu.options = [
+        "-chardev socket,id=chrtpm,path=${tpmSocketPath}"
+        "-tpmdev emulator,id=tpm_dev_0,chardev=chrtpm"
+        "-device ${tpmDeviceModels.${system}},tpmdev=tpm_dev_0"
+      ];
+    };
+
+    boot.initrd.availableKernelModules = [ "tpm_tis" ];
+
+    environment.systemPackages = with pkgs; [ diffutils ];
+  };
+
+  testScript = ''
+    import subprocess
+    from tempfile import TemporaryDirectory
+
+    # From systemd-initrd-luks-tpm2.nix
+    class Tpm:
+        def __init__(self):
+            self.state_dir = TemporaryDirectory()
+            self.start()
+
+        def start(self):
+            self.proc = subprocess.Popen(["${pkgs.swtpm}/bin/swtpm",
+                "socket",
+                "--tpmstate", f"dir={self.state_dir.name}",
+                "--ctrl", "type=unixio,path=${tpmSocketPath}",
+                "--tpm2",
+                ])
+
+            # Check whether starting swtpm failed
+            try:
+                exit_code = self.proc.wait(timeout=0.2)
+                if exit_code is not None and exit_code != 0:
+                    raise Exception("failed to start swtpm")
+            except subprocess.TimeoutExpired:
+                pass
+
+        """Check whether the swtpm process exited due to an error"""
+        def check(self):
+            exit_code = self.proc.poll()
+            if exit_code is not None and exit_code != 0:
+                raise Exception("swtpm process died")
+
+    CRED_NAME = "testkey"
+    CRED_RAW_FILE = f"/root/{CRED_NAME}"
+    CRED_FILE = f"/root/{CRED_NAME}.cred"
+
+    def systemd_run(machine, cmd):
+        machine.log(f"Executing command (via systemd-run): \"{cmd}\"")
+
+        (status, out) = machine.execute( " ".join([
+            "systemd-run",
+            "--service-type=exec",
+            "--quiet",
+            "--wait",
+            "-E PATH=\"$PATH\"",
+            "-p StandardOutput=journal",
+            "-p StandardError=journal",
+            f"-p LoadCredentialEncrypted={CRED_NAME}:{CRED_FILE}",
+            f"$SHELL -c '{cmd}'"
+            ]) )
+
+        if status != 0:
+            raise Exception(f"systemd_run failed (status {status})")
+
+        machine.log("systemd-run finished successfully")
+
+    tpm = Tpm()
+
+    @polling_condition
+    def swtpm_running():
+        tpm.check()
+
+    machine.wait_for_unit("multi-user.target")
+
+    with subtest("Check whether TPM device exists"):
+        machine.succeed("test -e /dev/tpm0")
+        machine.succeed("test -e /dev/tpmrm0")
+
+    with subtest("Check whether systemd-creds detects TPM2 correctly"):
+        cmd = "systemd-creds has-tpm2"
+        machine.log(f"Running \"{cmd}\"")
+        (status, _) = machine.execute(cmd)
+
+        # Check exit code equals 0 or 1 (1 means firmware support is missing, which is OK here)
+        if status != 0 and status != 1:
+            raise Exception("systemd-creds failed to detect TPM2")
+
+    with subtest("Encrypt credential using systemd-creds"):
+        machine.succeed(f"dd if=/dev/urandom of={CRED_RAW_FILE} bs=1k count=16")
+        machine.succeed(f"systemd-creds --with-key=host+tpm2 encrypt --name=testkey {CRED_RAW_FILE} {CRED_FILE}")
+
+    with subtest("Write provided credential and check for equality"):
+        CRED_OUT_FILE = f"/root/{CRED_NAME}.out"
+        systemd_run(machine, f"systemd-creds cat testkey > {CRED_OUT_FILE}")
+        machine.succeed(f"cmp --silent -- {CRED_RAW_FILE} {CRED_OUT_FILE}")
+
+    with subtest("Check whether systemd service can see credential in systemd-creds list"):
+        systemd_run(machine, f"systemd-creds list | grep {CRED_NAME}")
+
+    with subtest("Check whether systemd service can access credential in $CREDENTIALS_DIRECTORY"):
+        systemd_run(machine, f"cmp --silent -- $CREDENTIALS_DIRECTORY/{CRED_NAME} {CRED_RAW_FILE}")
+  '';
+})
diff --git a/nixos/tests/systemd-initrd-vconsole.nix b/nixos/tests/systemd-initrd-vconsole.nix
new file mode 100644
index 0000000000000..b74df410c4224
--- /dev/null
+++ b/nixos/tests/systemd-initrd-vconsole.nix
@@ -0,0 +1,33 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }: {
+  name = "systemd-initrd-vconsole";
+
+  nodes.machine = { pkgs, ... }: {
+    boot.kernelParams = [ "rd.systemd.unit=rescue.target" ];
+
+    boot.initrd.systemd = {
+      enable = true;
+      emergencyAccess = true;
+    };
+
+    console = {
+      earlySetup = true;
+      keyMap = "colemak";
+    };
+  };
+
+  testScript = ''
+    # Boot into rescue shell in initrd
+    machine.start()
+    machine.wait_for_console_text("Press Enter for maintenance")
+    machine.send_console("\n")
+    machine.wait_for_console_text("Logging in with home")
+
+    # Check keymap
+    machine.send_console("(printf '%s to receive text: \\n' Ready && read text && echo \"$text\") </dev/tty1\n")
+    machine.wait_for_console_text("Ready to receive text:")
+    for key in "asdfjkl;\n":
+      machine.send_key(key)
+    machine.wait_for_console_text("arstneio")
+    machine.send_console("systemctl poweroff\n")
+  '';
+})
diff --git a/nixos/tests/tuxguitar.nix b/nixos/tests/tuxguitar.nix
index 037f489e54483..00833024bfeac 100644
--- a/nixos/tests/tuxguitar.nix
+++ b/nixos/tests/tuxguitar.nix
@@ -1,7 +1,7 @@
 import ./make-test-python.nix ({ pkgs, ... }: {
   name = "tuxguitar";
   meta = with pkgs.lib.maintainers; {
-    maintainers = [ asbachb ];
+    maintainers = [ ];
   };
 
   nodes.machine = { config, pkgs, ... }: {