about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorannalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com>2024-03-02 04:08:10 +0000
committerannalee <150648636+a-n-n-a-l-e-e@users.noreply.github.com>2024-03-02 04:08:10 +0000
commita04ddbe327635af96d4b5a95087331a9e4d5fdb4 (patch)
tree5018a7a328a537460050e4023be034308644372d /nixos
parentee9c2b7c6a141a054a8d451b777d0682b5af1751 (diff)
parentaa94fc78b0a49ed2a4a69b6f5082a1b286dd392d (diff)
Merge remote-tracking branch 'upstream/master' into sn-remove
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-2405.section.md6
-rw-r--r--nixos/lib/make-disk-image.nix7
-rw-r--r--nixos/modules/i18n/input-method/fcitx5.nix13
-rw-r--r--nixos/modules/misc/nixpkgs.nix6
-rw-r--r--nixos/modules/misc/nixpkgs/test.nix6
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/security/pam.nix4
-rw-r--r--nixos/modules/services/home-automation/matter-server.nix125
-rw-r--r--nixos/modules/services/misc/transfer-sh.nix102
-rw-r--r--nixos/modules/services/networking/tailscale.nix9
-rw-r--r--nixos/modules/system/boot/systemd.nix2
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix20
-rw-r--r--nixos/tests/all-tests.nix2
-rw-r--r--nixos/tests/matter-server.nix45
-rw-r--r--nixos/tests/qemu-vm-external-disk-image.nix3
-rw-r--r--nixos/tests/transfer-sh.nix20
-rw-r--r--nixos/tests/zfs.nix18
17 files changed, 359 insertions, 31 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md
index 8b89143a199bc..e5898909e12ab 100644
--- a/nixos/doc/manual/release-notes/rl-2405.section.md
+++ b/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -78,9 +78,15 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - [hebbot](https://github.com/haecker-felix/hebbot), a Matrix bot to generate "This Week in X" like blog posts. Available as [services.hebbot](#opt-services.hebbot.enable).
 
+- [Python Matter Server](https://github.com/home-assistant-libs/python-matter-server), a
+  Matter Controller Server exposing websocket connections for use with other services, notably Home Assistant.
+  Available as [services.matter-server](#opt-services.matter-server.enable)
+
 - [Anki Sync Server](https://docs.ankiweb.net/sync-server.html), the official sync server built into recent versions of Anki. Available as [services.anki-sync-server](#opt-services.anki-sync-server.enable).
 The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been marked deprecated and will be dropped after 24.05 due to lack of maintenance of the anki-sync-server softwares.
 
+- [transfer-sh](https://github.com/dutchcoders/transfer.sh), a tool that supports easy and fast file sharing from the command-line. Available as [services.transfer-sh](#opt-services.transfer-sh.enable).
+
 - [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
 
 - [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix
index da94ef16654c9..9bdbf4e0713de 100644
--- a/nixos/lib/make-disk-image.nix
+++ b/nixos/lib/make-disk-image.nix
@@ -609,6 +609,13 @@ let format' = format; in let
         ''}
 
         # Set up core system link, bootloader (sd-boot, GRUB, uboot, etc.), etc.
+
+        # NOTE: systemd-boot-builder.py calls nix-env --list-generations which
+        # clobbers $HOME/.nix-defexpr/channels/nixos This would cause a  folder
+        # /homeless-shelter to show up in the final image which  in turn breaks
+        # nix builds in the target image if sandboxing is turned off (through
+        # __noChroot for example).
+        export HOME=$TMPDIR
         NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root $mountPoint -- /nix/var/nix/profiles/system/bin/switch-to-configuration boot
 
         # The above scripts will generate a random machine-id and we don't want to bake a single ID into all our images
diff --git a/nixos/modules/i18n/input-method/fcitx5.nix b/nixos/modules/i18n/input-method/fcitx5.nix
index 530727f3f2928..2e87705c6dc2d 100644
--- a/nixos/modules/i18n/input-method/fcitx5.nix
+++ b/nixos/modules/i18n/input-method/fcitx5.nix
@@ -5,7 +5,10 @@ with lib;
 let
   im = config.i18n.inputMethod;
   cfg = im.fcitx5;
-  fcitx5Package = pkgs.fcitx5-with-addons.override { inherit (cfg) addons; };
+  fcitx5Package =
+    if cfg.plasma6Support
+    then pkgs.qt6Packages.fcitx5-with-addons.override { inherit (cfg) addons; }
+    else pkgs.libsForQt5.fcitx5-with-addons.override { inherit (cfg) addons; };
   settingsFormat = pkgs.formats.ini { };
 in
 {
@@ -27,6 +30,14 @@ in
           See [Using Fcitx 5 on Wayland](https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland).
         '';
       };
+      plasma6Support = mkOption {
+        type = types.bool;
+        default = false;
+        description = lib.mdDoc ''
+          Use qt6 versions of fcitx5 packages.
+          Required for configuring fcitx5 in KDE System Settings.
+        '';
+      };
       quickPhrase = mkOption {
         type = with types; attrsOf str;
         default = { };
diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index da321a9234493..10f800cd741a0 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -208,7 +208,11 @@ in
       example = { system = "x86_64-linux"; };
       # Make sure that the final value has all fields for sake of other modules
       # referring to this.
-      apply = lib.systems.elaborate;
+      apply = inputBuildPlatform:
+        let elaborated = lib.systems.elaborate inputBuildPlatform;
+        in if lib.systems.equals elaborated cfg.hostPlatform
+          then cfg.hostPlatform  # make identical, so that `==` equality works; see https://github.com/NixOS/nixpkgs/issues/278001
+          else elaborated;
       defaultText = literalExpression
         ''config.nixpkgs.hostPlatform'';
       description = lib.mdDoc ''
diff --git a/nixos/modules/misc/nixpkgs/test.nix b/nixos/modules/misc/nixpkgs/test.nix
index 0536cfc9624a2..be9a88a077887 100644
--- a/nixos/modules/misc/nixpkgs/test.nix
+++ b/nixos/modules/misc/nixpkgs/test.nix
@@ -12,6 +12,10 @@ let
     nixpkgs.hostPlatform = "aarch64-linux";
     nixpkgs.buildPlatform = "aarch64-darwin";
   };
+  withSameHostAndBuild = eval {
+    nixpkgs.hostPlatform = "aarch64-linux";
+    nixpkgs.buildPlatform = "aarch64-linux";
+  };
   ambiguous = {
     _file = "ambiguous.nix";
     nixpkgs.hostPlatform = "aarch64-linux";
@@ -81,6 +85,8 @@ lib.recurseIntoAttrs {
     assert withHost._module.args.pkgs.stdenv.buildPlatform.system == "aarch64-linux";
     assert withHostAndBuild._module.args.pkgs.stdenv.hostPlatform.system == "aarch64-linux";
     assert withHostAndBuild._module.args.pkgs.stdenv.buildPlatform.system == "aarch64-darwin";
+    assert withSameHostAndBuild.config.nixpkgs.buildPlatform == withSameHostAndBuild.config.nixpkgs.hostPlatform;
+    assert withSameHostAndBuild._module.args.pkgs.stdenv.buildPlatform == withSameHostAndBuild._module.args.pkgs.stdenv.hostPlatform;
     assert builtins.trace (lib.head (getErrors ambiguous))
       getErrors ambiguous ==
         [''
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 90268d3efb471..627427262da63 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -585,6 +585,7 @@
   ./services/home-automation/govee2mqtt.nix
   ./services/home-automation/home-assistant.nix
   ./services/home-automation/homeassistant-satellite.nix
+  ./services/home-automation/matter-server.nix
   ./services/home-automation/zigbee2mqtt.nix
   ./services/home-automation/zwave-js.nix
   ./services/logging/SystemdJournal2Gelf.nix
@@ -786,6 +787,7 @@
   ./services/misc/tiddlywiki.nix
   ./services/misc/tp-auto-kbbl.nix
   ./services/misc/tuxclocker.nix
+  ./services/misc/transfer-sh.nix
   ./services/misc/tzupdate.nix
   ./services/misc/uhub.nix
   ./services/misc/weechat.nix
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index b87e22b23980c..560e5eff5c39a 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -1465,9 +1465,9 @@ in
         '';
       }
       {
-        assertion = config.security.pam.zfs.enable -> (config.boot.zfs.enabled || config.boot.zfs.enableUnstable);
+        assertion = config.security.pam.zfs.enable -> config.boot.zfs.enabled;
         message = ''
-          `security.pam.zfs.enable` requires enabling ZFS (`boot.zfs.enabled` or `boot.zfs.enableUnstable`).
+          `security.pam.zfs.enable` requires enabling ZFS (`boot.zfs.enabled`).
         '';
       }
       {
diff --git a/nixos/modules/services/home-automation/matter-server.nix b/nixos/modules/services/home-automation/matter-server.nix
new file mode 100644
index 0000000000000..864ef9e200837
--- /dev/null
+++ b/nixos/modules/services/home-automation/matter-server.nix
@@ -0,0 +1,125 @@
+{ lib
+, pkgs
+, config
+, ...
+}:
+
+with lib;
+
+let
+  cfg = config.services.matter-server;
+  storageDir = "matter-server";
+  storagePath = "/var/lib/${storageDir}";
+  vendorId = "4939"; # home-assistant vendor ID
+in
+
+{
+  meta.maintainers = with lib.maintainers; [ leonm1 ];
+
+  options.services.matter-server = with types; {
+    enable = mkEnableOption (lib.mdDoc "Matter-server");
+
+    package = mkPackageOptionMD pkgs "python-matter-server" { };
+
+    port = mkOption {
+      type = types.port;
+      default = 5580;
+      description = "Port to expose the matter-server service on.";
+    };
+
+    logLevel = mkOption {
+      type = types.enum [ "critical" "error" "warning" "info" "debug" ];
+      default = "info";
+      description = "Verbosity of logs from the matter-server";
+    };
+
+    extraArgs = mkOption {
+      type = listOf str;
+      default = [];
+      description = ''
+        Extra arguments to pass to the matter-server executable.
+        See https://github.com/home-assistant-libs/python-matter-server?tab=readme-ov-file#running-the-development-server for options.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.matter-server = {
+      after = [ "network-online.target" ];
+      before = [ "home-assistant.service" ];
+      wants = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      description = "Matter Server";
+      environment.HOME = storagePath;
+      serviceConfig = {
+        ExecStart = (concatStringsSep " " [
+          "${cfg.package}/bin/matter-server"
+          "--port" (toString cfg.port)
+          "--vendorid" vendorId
+          "--storage-path" storagePath
+          "--log-level" "${cfg.logLevel}"
+          "${escapeShellArgs cfg.extraArgs}"
+        ]);
+        # Start with a clean root filesystem, and allowlist what the container
+        # is permitted to access.
+        TemporaryFileSystem = "/";
+        # Allowlist /nix/store (to allow the binary to find its dependencies)
+        # and dbus.
+        ReadOnlyPaths = "/nix/store /run/dbus";
+        # Let systemd manage `/var/lib/matter-server` for us inside the
+        # ephemeral TemporaryFileSystem.
+        StateDirectory = storageDir;
+        # `python-matter-server` writes to /data even when a storage-path is
+        # specified. This bind-mount points /data at the systemd-managed
+        # /var/lib/matter-server, so all files get dropped into the state
+        # directory.
+        BindPaths = "${storagePath}:/data";
+
+        # Hardening bits
+        AmbientCapabilities = "";
+        CapabilityBoundingSet = "";
+        DevicePolicy = "closed";
+        DynamicUser = true;
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        PrivateUsers = true;
+        ProcSubset = "pid";
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        RestrictAddressFamilies = [
+          "AF_INET"
+          "AF_INET6"
+          "AF_NETLINK"
+        ];
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        RestrictSUIDSGID = true;
+        SystemCallFilter = concatStringsSep " " [
+          "~" # Blocklist
+          "@clock"
+          "@cpu-emulation"
+          "@debug"
+          "@module"
+          "@mount"
+          "@obsolete"
+          "@privileged"
+          "@raw-io"
+          "@reboot"
+          "@resources"
+          "@swap"
+        ];
+        UMask = "0077";
+      };
+    };
+  };
+}
+
diff --git a/nixos/modules/services/misc/transfer-sh.nix b/nixos/modules/services/misc/transfer-sh.nix
new file mode 100644
index 0000000000000..899d9dfc3c108
--- /dev/null
+++ b/nixos/modules/services/misc/transfer-sh.nix
@@ -0,0 +1,102 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.transfer-sh;
+  inherit (lib)
+    mkDefault mkEnableOption mkPackageOption mkIf mkOption
+    types mapAttrs isBool getExe boolToString mdDoc optionalAttrs;
+in
+{
+  options.services.transfer-sh = {
+    enable = mkEnableOption (mdDoc "Easy and fast file sharing from the command-line");
+
+    package = mkPackageOption pkgs "transfer-sh" { };
+
+    settings = mkOption {
+      type = types.submodule { freeformType = with types; attrsOf (oneOf [ bool int str ]); };
+      default = { };
+      example = {
+        LISTENER = ":8080";
+        BASEDIR = "/var/lib/transfer.sh";
+        TLS_LISTENER_ONLY = false;
+      };
+      description = mdDoc ''
+        Additional configuration for transfer-sh, see
+        <https://github.com/dutchcoders/transfer.sh#usage-1>
+        for supported values.
+
+        For secrets use secretFile option instead.
+      '';
+    };
+
+    provider = mkOption {
+      type = types.enum [ "local" "s3" "storj" "gdrive" ];
+      default = "local";
+      description = mdDoc "Storage providers to use";
+    };
+
+    secretFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      example = "/run/secrets/transfer-sh.env";
+      description = mdDoc ''
+        Path to file containing environment variables.
+        Useful for passing down secrets.
+        Some variables that can be considered secrets are:
+         - AWS_ACCESS_KEY
+         - AWS_ACCESS_KEY
+         - TLS_PRIVATE_KEY
+         - HTTP_AUTH_HTPASSWD
+      '';
+    };
+  };
+
+  config =
+    let
+      localProvider = (cfg.provider == "local");
+      stateDirectory = "/var/lib/transfer.sh";
+    in
+    mkIf cfg.enable
+      {
+        services.transfer-sh.settings = {
+          LISTENER = mkDefault ":8080";
+        } // optionalAttrs localProvider {
+          BASEDIR = mkDefault stateDirectory;
+        };
+
+        systemd.services.transfer-sh = {
+          after = [ "network.target" ];
+          wantedBy = [ "multi-user.target" ];
+          environment = mapAttrs (_: v: if isBool v then boolToString v else toString v) cfg.settings;
+          serviceConfig = {
+            CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+            DevicePolicy = "closed";
+            DynamicUser = true;
+            ExecStart = "${getExe cfg.package} --provider ${cfg.provider}";
+            LockPersonality = true;
+            MemoryDenyWriteExecute = true;
+            PrivateDevices = true;
+            PrivateUsers = true;
+            ProtectClock = true;
+            ProtectControlGroups = true;
+            ProtectHostname = true;
+            ProtectKernelLogs = true;
+            ProtectKernelModules = true;
+            ProtectKernelTunables = true;
+            ProtectProc = "invisible";
+            RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+            RestrictNamespaces = true;
+            RestrictRealtime = true;
+            SystemCallArchitectures = [ "native" ];
+            SystemCallFilter = [ "@system-service" ];
+            StateDirectory = baseNameOf stateDirectory;
+          } // optionalAttrs (cfg.secretFile != null) {
+            EnvironmentFile = cfg.secretFile;
+          } // optionalAttrs localProvider {
+            ReadWritePaths = cfg.settings.BASEDIR;
+          };
+        };
+      };
+
+  meta.maintainers = with lib.maintainers; [ ocfox ];
+}
diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix
index f11fe57d6ce5e..972299a4697a0 100644
--- a/nixos/modules/services/networking/tailscale.nix
+++ b/nixos/modules/services/networking/tailscale.nix
@@ -66,6 +66,13 @@ in {
       default = [];
       example = ["--ssh"];
     };
+
+    extraDaemonFlags = mkOption {
+      description = lib.mdDoc "Extra flags to pass to {command}`tailscaled`.";
+      type = types.listOf types.str;
+      default = [];
+      example = ["--no-logs-no-support"];
+    };
   };
 
   config = mkIf cfg.enable {
@@ -80,7 +87,7 @@ in {
       ] ++ lib.optional config.networking.resolvconf.enable config.networking.resolvconf.package;
       serviceConfig.Environment = [
         "PORT=${toString cfg.port}"
-        ''"FLAGS=--tun ${lib.escapeShellArg cfg.interfaceName}"''
+        ''"FLAGS=--tun ${lib.escapeShellArg cfg.interfaceName} ${lib.concatStringsSep " " cfg.extraDaemonFlags}"''
       ] ++ (lib.optionals (cfg.permitCertUid != null) [
         "TS_PERMIT_CERT_UID=${cfg.permitCertUid}"
       ]);
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index e29fa49ea23be..49090423e078c 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -97,6 +97,7 @@ let
 
       # Maintaining state across reboots.
       "systemd-random-seed.service"
+      "systemd-boot-random-seed.service"
       "systemd-backlight@.service"
       "systemd-rfkill.service"
       "systemd-rfkill.socket"
@@ -667,7 +668,6 @@ in
 
     # Don't bother with certain units in containers.
     systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";
-    systemd.services.systemd-random-seed.unitConfig.ConditionVirtualization = "!container";
 
     # Increase numeric PID range (set directly instead of copying a one-line file from systemd)
     # https://github.com/systemd/systemd/pull/12226
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 58aca3fdbd4fc..d11424c11c810 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -211,6 +211,7 @@ in
 
   imports = [
     (mkRemovedOptionModule [ "boot" "zfs" "enableLegacyCrypto" ] "The corresponding package was removed from nixpkgs.")
+    (mkRemovedOptionModule [ "boot" "zfs" "enableUnstable" ] "Instead set `boot.zfs.package = pkgs.zfs_unstable;`")
   ];
 
   ###### interface
@@ -219,9 +220,9 @@ in
     boot.zfs = {
       package = mkOption {
         type = types.package;
-        default = if cfgZfs.enableUnstable then pkgs.zfsUnstable else pkgs.zfs;
-        defaultText = literalExpression "if zfsUnstable is enabled then pkgs.zfsUnstable else pkgs.zfs";
-        description = lib.mdDoc "Configured ZFS userland tools package, use `pkgs.zfsUnstable` if you want to track the latest staging ZFS branch.";
+        default = pkgs.zfs;
+        defaultText = literalExpression "pkgs.zfs";
+        description = lib.mdDoc "Configured ZFS userland tools package, use `pkgs.zfs_unstable` if you want to track the latest staging ZFS branch.";
       };
 
       modulePackage = mkOption {
@@ -239,19 +240,6 @@ in
         description = lib.mdDoc "True if ZFS filesystem support is enabled";
       };
 
-      enableUnstable = mkOption {
-        type = types.bool;
-        default = false;
-        description = lib.mdDoc ''
-          Use the unstable zfs package. This might be an option, if the latest
-          kernel is not yet supported by a published release of ZFS. Enabling
-          this option will install a development version of ZFS on Linux. The
-          version will have already passed an extensive test suite, but it is
-          more likely to hit an undiscovered bug compared to running a released
-          version of ZFS on Linux.
-          '';
-      };
-
       allowHibernation = mkOption {
         type = types.bool;
         default = false;
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 231767ca2b977..9795023bcea98 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -512,6 +512,7 @@ in {
   mastodon = discoverTests (import ./web-apps/mastodon { inherit handleTestOn; });
   pixelfed = discoverTests (import ./web-apps/pixelfed { inherit handleTestOn; });
   mate = handleTest ./mate.nix {};
+  matter-server = handleTest ./matter-server.nix {};
   matomo = handleTest ./matomo.nix {};
   matrix-appservice-irc = handleTest ./matrix/appservice-irc.nix {};
   matrix-conduit = handleTest ./matrix/conduit.nix {};
@@ -916,6 +917,7 @@ in {
   tor = handleTest ./tor.nix {};
   traefik = handleTestOn ["aarch64-linux" "x86_64-linux"] ./traefik.nix {};
   trafficserver = handleTest ./trafficserver.nix {};
+  transfer-sh = handleTest ./transfer-sh.nix {};
   transmission = handleTest ./transmission.nix { transmission = pkgs.transmission; };
   transmission_4 = handleTest ./transmission.nix { transmission = pkgs.transmission_4; };
   # tracee requires bpf
diff --git a/nixos/tests/matter-server.nix b/nixos/tests/matter-server.nix
new file mode 100644
index 0000000000000..c646e9840d194
--- /dev/null
+++ b/nixos/tests/matter-server.nix
@@ -0,0 +1,45 @@
+import ./make-test-python.nix ({ pkgs, lib, ...} :
+
+let
+  chipVersion = pkgs.python311Packages.home-assistant-chip-core.version;
+in
+
+{
+  name = "matter-server";
+  meta.maintainers = with lib.maintainers; [ leonm1 ];
+
+  nodes = {
+    machine = { config, ... }: {
+      services.matter-server = {
+        enable = true;
+        port = 1234;
+      };
+    };
+  };
+
+  testScript = /* python */ ''
+    start_all()
+
+    machine.wait_for_unit("matter-server.service")
+    machine.wait_for_open_port(1234)
+
+    with subtest("Check websocket server initialized"):
+        output = machine.succeed("echo \"\" | ${pkgs.websocat}/bin/websocat ws://localhost:1234/ws")
+        machine.log(output)
+
+    assert '"sdk_version": "${chipVersion}"' in output, (
+      'CHIP version \"${chipVersion}\" not present in websocket message'
+    )
+
+    assert '"fabric_id": 1' in output, (
+      "fabric_id not propagated to server"
+    )
+
+    with subtest("Check storage directory is created"):
+        machine.succeed("ls /var/lib/matter-server/chip.json")
+
+    with subtest("Check systemd hardening"):
+        _, output = machine.execute("systemd-analyze security matter-server.service | grep -v '✓'")
+        machine.log(output)
+  '';
+})
diff --git a/nixos/tests/qemu-vm-external-disk-image.nix b/nixos/tests/qemu-vm-external-disk-image.nix
index a229fc5e39633..c481159511a02 100644
--- a/nixos/tests/qemu-vm-external-disk-image.nix
+++ b/nixos/tests/qemu-vm-external-disk-image.nix
@@ -69,5 +69,8 @@ in
     os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
 
     machine.succeed("findmnt --kernel --source ${rootFsDevice} --target /")
+
+    # Make sure systemd boot didn't clobber this
+    machine.succeed("[ ! -e /homeless-shelter ]")
   '';
 }
diff --git a/nixos/tests/transfer-sh.nix b/nixos/tests/transfer-sh.nix
new file mode 100644
index 0000000000000..f4ab7d28858e1
--- /dev/null
+++ b/nixos/tests/transfer-sh.nix
@@ -0,0 +1,20 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+  name = "transfer-sh";
+
+  meta = {
+    maintainers = with lib.maintainers; [ ocfox ];
+  };
+
+  nodes.machine = { pkgs, ... }: {
+    services.transfer-sh = {
+      enable = true;
+      settings.LISTENER = ":1234";
+    };
+  };
+
+  testScript = ''
+    machine.wait_for_unit("transfer-sh.service")
+    machine.wait_for_open_port(1234)
+    machine.succeed("curl --fail http://localhost:1234/")
+  '';
+})
diff --git a/nixos/tests/zfs.nix b/nixos/tests/zfs.nix
index 0b411b0b9d8a5..851fced2c5e1e 100644
--- a/nixos/tests/zfs.nix
+++ b/nixos/tests/zfs.nix
@@ -7,14 +7,14 @@ with import ../lib/testing-python.nix { inherit system pkgs; };
 
 let
 
-  makeZfsTest = name:
+  makeZfsTest =
     { kernelPackages
     , enableSystemdStage1 ? false
     , zfsPackage
     , extraTest ? ""
     }:
     makeTest {
-      name = "zfs-" + name;
+      name = zfsPackage.kernelModuleAttribute;
       meta = with pkgs.lib.maintainers; {
         maintainers = [ elvishjerricco ];
       };
@@ -192,23 +192,23 @@ let
 in {
 
   # maintainer: @raitobezarius
-  series_2_1 = makeZfsTest "2.1-series" {
+  series_2_1 = makeZfsTest {
     zfsPackage = pkgs.zfs_2_1;
     kernelPackages = pkgs.linuxPackages;
   };
 
-  stable = makeZfsTest "stable" {
-    zfsPackage = pkgs.zfsStable;
+  series_2_2 = makeZfsTest {
+    zfsPackage = pkgs.zfs_2_2;
     kernelPackages = pkgs.linuxPackages;
   };
 
-  unstable = makeZfsTest "unstable" rec {
-    zfsPackage = pkgs.zfsUnstable;
+  unstable = makeZfsTest rec {
+    zfsPackage = pkgs.zfs_unstable;
     kernelPackages = zfsPackage.latestCompatibleLinuxPackages;
   };
 
-  unstableWithSystemdStage1 = makeZfsTest "unstable" rec {
-    zfsPackage = pkgs.zfsUnstable;
+  unstableWithSystemdStage1 = makeZfsTest rec {
+    zfsPackage = pkgs.zfs_unstable;
     kernelPackages = zfsPackage.latestCompatibleLinuxPackages;
     enableSystemdStage1 = true;
   };