summary refs log tree commit diff
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2022-03-13 18:01:01 +0000
committerGitHub <noreply@github.com>2022-03-13 18:01:01 +0000
commit38910351b753e23a1731fd95fa99765d3a21dcc5 (patch)
tree15e8593de114ff77b686aae0c64e715c2d7a35ae
parent72b55bcbef7f62f171abf4f3babf13586c68d184 (diff)
parent2a72d02169a111961ea40e1f29e4b73dd85731b4 (diff)
downloadnixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar.gz
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar.bz2
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar.lz
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar.xz
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.tar.zst
nixpkgs-38910351b753e23a1731fd95fa99765d3a21dcc5.zip
Merge master into staging-next
-rw-r--r--nixos/doc/manual/development/unit-handling.section.md6
-rw-r--r--nixos/doc/manual/from_md/development/unit-handling.section.xml10
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2205.section.xml11
-rw-r--r--nixos/doc/manual/release-notes/rl-2205.section.md2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/programs/captive-browser.nix20
-rw-r--r--nixos/modules/services/audio/squeezelite.nix38
-rw-r--r--nixos/modules/services/misc/jellyfin.nix3
-rw-r--r--nixos/modules/services/system/earlyoom.nix155
-rw-r--r--nixos/modules/services/system/systembus-notify.nix27
-rw-r--r--nixos/modules/system/activation/switch-to-configuration.pl259
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py21
-rw-r--r--nixos/tests/switch-test.nix147
-rw-r--r--pkgs/applications/audio/squeezelite/default.nix78
-rw-r--r--pkgs/applications/editors/sigil/default.nix4
-rw-r--r--pkgs/applications/graphics/nsxiv/default.nix4
-rw-r--r--pkgs/applications/misc/systembus-notify/default.nix44
-rw-r--r--pkgs/applications/networking/cluster/cloudfoundry-cli/default.nix6
-rw-r--r--pkgs/applications/networking/instant-messengers/qtox/default.nix4
-rw-r--r--pkgs/applications/video/go-chromecast/default.nix6
-rw-r--r--pkgs/applications/virtualization/docker-slim/default.nix4
-rw-r--r--pkgs/applications/window-managers/berry/default.nix2
-rw-r--r--pkgs/applications/window-managers/icewm/default.nix17
-rw-r--r--pkgs/applications/window-managers/labwc/default.nix11
-rw-r--r--pkgs/applications/window-managers/labwc/relax-the-version-constraint-for-wlroots.patch29
-rw-r--r--pkgs/development/libraries/cimg/default.nix4
-rw-r--r--pkgs/development/libraries/elpa/default.nix4
-rw-r--r--pkgs/development/libraries/zchunk/default.nix5
-rw-r--r--pkgs/development/python-modules/allure-behave/default.nix38
-rw-r--r--pkgs/development/python-modules/wled/default.nix4
-rw-r--r--pkgs/development/tools/analysis/actionlint/default.nix6
-rw-r--r--pkgs/development/tools/analysis/flow/default.nix4
-rw-r--r--pkgs/development/tools/buildkit/default.nix4
-rw-r--r--pkgs/development/tools/cloud-nuke/default.nix4
-rw-r--r--pkgs/development/tools/ocaml/dune/3.nix4
-rw-r--r--pkgs/development/tools/wllvm/default.nix5
-rw-r--r--pkgs/servers/sql/postgresql/ext/rum.nix31
-rw-r--r--pkgs/servers/sql/postgresql/packages.nix2
-rw-r--r--pkgs/shells/tcsh/default.nix15
-rw-r--r--pkgs/tools/misc/nncp/default.nix4
-rw-r--r--pkgs/tools/networking/minio-client/default.nix6
-rw-r--r--pkgs/tools/networking/ytcc/default.nix4
-rw-r--r--pkgs/tools/security/sops/default.nix6
-rw-r--r--pkgs/tools/security/swtpm/default.nix41
-rw-r--r--pkgs/top-level/all-packages.nix4
-rw-r--r--pkgs/top-level/python-packages.nix2
46 files changed, 757 insertions, 349 deletions
diff --git a/nixos/doc/manual/development/unit-handling.section.md b/nixos/doc/manual/development/unit-handling.section.md
index bd4fe9e670f..a7ccb3dbd04 100644
--- a/nixos/doc/manual/development/unit-handling.section.md
+++ b/nixos/doc/manual/development/unit-handling.section.md
@@ -17,7 +17,8 @@ checks:
   them and comparing their contents. If they are different but only
   `X-Reload-Triggers` in the `[Unit]` section is changed, **reload** the unit.
   The NixOS module system allows setting these triggers with the option
-  [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services). If the
+  [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services). There are
+  some additional keys in the `[Unit]` section that are ignored as well. If the
   unit files differ in any way, the following actions are performed:
 
   - `.path` and `.slice` units are ignored. There is no need to restart them
@@ -33,6 +34,9 @@ checks:
   - The rest of the units (mostly `.service` units) are then **reload**ed if
     `X-ReloadIfChanged` in the `[Service]` section is set to `true` (exposed
     via [systemd.services.\<name\>.reloadIfChanged](#opt-systemd.services)).
+    A little exception is done for units that were deactivated in the meantime,
+    for example because they require a unit that got stopped before. These
+    are **start**ed instead of reloaded.
 
   - If the reload flag is not set, some more flags decide if the unit is
     skipped. These flags are `X-RestartIfChanged` in the `[Service]` section
diff --git a/nixos/doc/manual/from_md/development/unit-handling.section.xml b/nixos/doc/manual/from_md/development/unit-handling.section.xml
index 57c4754c001..4c980e1213a 100644
--- a/nixos/doc/manual/from_md/development/unit-handling.section.xml
+++ b/nixos/doc/manual/from_md/development/unit-handling.section.xml
@@ -38,8 +38,9 @@
         <emphasis role="strong">reload</emphasis> the unit. The NixOS
         module system allows setting these triggers with the option
         <link linkend="opt-systemd.services">systemd.services.&lt;name&gt;.reloadTriggers</link>.
-        If the unit files differ in any way, the following actions are
-        performed:
+        There are some additional keys in the <literal>[Unit]</literal>
+        section that are ignored as well. If the unit files differ in
+        any way, the following actions are performed:
       </para>
       <itemizedlist>
         <listitem>
@@ -71,6 +72,11 @@
             <literal>[Service]</literal> section is set to
             <literal>true</literal> (exposed via
             <link linkend="opt-systemd.services">systemd.services.&lt;name&gt;.reloadIfChanged</link>).
+            A little exception is done for units that were deactivated
+            in the meantime, for example because they require a unit
+            that got stopped before. These are
+            <emphasis role="strong">start</emphasis>ed instead of
+            reloaded.
           </para>
         </listitem>
         <listitem>
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
index bdf51211378..d3a944533ab 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
@@ -251,6 +251,17 @@
       </listitem>
       <listitem>
         <para>
+          <link xlink:href="https://github.com/rfjakob/systembus-notify">systembus-notify</link>,
+          allow system level notifications to reach the users. Available
+          as
+          <link xlink:href="opt-services.systembus-notify.enable">services.systembus-notify</link>.
+          Please keep in mind that this service should only be enabled
+          on machines with fully trusted users, as any local user is
+          able to DoS user sessions by spamming notifications.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           <link xlink:href="https://github.com/audreyt/ethercalc">ethercalc</link>,
           an online collaborative spreadsheet. Available as
           <link xlink:href="options.html#opt-services.ethercalc.enable">services.ethercalc</link>.
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md
index b8d6078a21d..fe30cbc3cf5 100644
--- a/nixos/doc/manual/release-notes/rl-2205.section.md
+++ b/nixos/doc/manual/release-notes/rl-2205.section.md
@@ -72,6 +72,8 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - [prosody-filer](https://github.com/ThomasLeister/prosody-filer), a server for handling XMPP HTTP Upload requests. Available at [services.prosody-filer](#opt-services.prosody-filer.enable).
 
+- [systembus-notify](https://github.com/rfjakob/systembus-notify), allow system level notifications to reach the users. Available as [services.systembus-notify](opt-services.systembus-notify.enable). Please keep in mind that this service should only be enabled on machines with fully trusted users, as any local user is able to DoS user sessions by spamming notifications.
+
 - [ethercalc](https://github.com/audreyt/ethercalc), an online collaborative
   spreadsheet. Available as [services.ethercalc](options.html#opt-services.ethercalc.enable).
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index ff95d6500b9..13703968167 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -987,6 +987,7 @@
   ./services/system/nscd.nix
   ./services/system/saslauthd.nix
   ./services/system/self-deploy.nix
+  ./services/system/systembus-notify.nix
   ./services/system/uptimed.nix
   ./services/torrent/deluge.nix
   ./services/torrent/flexget.nix
diff --git a/nixos/modules/programs/captive-browser.nix b/nixos/modules/programs/captive-browser.nix
index dc054504ea4..aad554c2bd6 100644
--- a/nixos/modules/programs/captive-browser.nix
+++ b/nixos/modules/programs/captive-browser.nix
@@ -1,8 +1,12 @@
 { config, lib, pkgs, ... }:
 
-with lib;
 let
   cfg = config.programs.captive-browser;
+
+  inherit (lib)
+    concatStringsSep escapeShellArgs optionalString
+    literalExpression mkEnableOption mkIf mkOption mkOptionDefault types;
+
   browserDefault = chromium: concatStringsSep " " [
     ''env XDG_CONFIG_HOME="$PREV_CONFIG_HOME"''
     ''${chromium}/bin/chromium''
@@ -15,6 +19,15 @@ let
     ''-no-default-browser-check''
     ''http://cache.nixos.org/''
   ];
+
+  desktopItem = pkgs.makeDesktopItem {
+    name = "captive-browser";
+    desktopName = "Captive Portal Browser";
+    exec = "/run/wrappers/bin/captive-browser";
+    icon = "nix-snowflake";
+    categories = [ "Network" ];
+  };
+
 in
 {
   ###### interface
@@ -84,6 +97,11 @@ in
   ###### implementation
 
   config = mkIf cfg.enable {
+    environment.systemPackages = [
+      (pkgs.runCommandNoCC "captive-browser-desktop-item" { } ''
+        install -Dm444 -t $out/share/applications ${desktopItem}/share/applications/*.desktop
+      '')
+    ];
 
     programs.captive-browser.dhcp-dns =
       let
diff --git a/nixos/modules/services/audio/squeezelite.nix b/nixos/modules/services/audio/squeezelite.nix
index 05506f5bcc7..36295e21c60 100644
--- a/nixos/modules/services/audio/squeezelite.nix
+++ b/nixos/modules/services/audio/squeezelite.nix
@@ -1,50 +1,46 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
+  inherit (lib) mkEnableOption mkIf mkOption optionalString types;
+
   dataDir = "/var/lib/squeezelite";
   cfg = config.services.squeezelite;
+  pkg = if cfg.pulseAudio then pkgs.squeezelite-pulse else pkgs.squeezelite;
+  bin = "${pkg}/bin/${pkg.pname}";
 
-in {
+in
+{
 
   ###### interface
 
-  options = {
-
-    services.squeezelite= {
+  options.services.squeezelite = {
+    enable = mkEnableOption "Squeezelite, a software Squeezebox emulator";
 
-      enable = mkEnableOption "Squeezelite, a software Squeezebox emulator";
-
-      extraArguments = mkOption {
-        default = "";
-        type = types.str;
-        description = ''
-          Additional command line arguments to pass to Squeezelite.
-        '';
-      };
+    pulseAudio = mkEnableOption "pulseaudio support";
 
+    extraArguments = mkOption {
+      default = "";
+      type = types.str;
+      description = ''
+        Additional command line arguments to pass to Squeezelite.
+      '';
     };
-
   };
 
 
   ###### implementation
 
   config = mkIf cfg.enable {
-
-    systemd.services.squeezelite= {
+    systemd.services.squeezelite = {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" "sound.target" ];
       description = "Software Squeezebox emulator";
       serviceConfig = {
         DynamicUser = true;
-        ExecStart = "${pkgs.squeezelite}/bin/squeezelite -N ${dataDir}/player-name ${cfg.extraArguments}";
+        ExecStart = "${bin} -N ${dataDir}/player-name ${cfg.extraArguments}";
         StateDirectory = builtins.baseNameOf dataDir;
         SupplementaryGroups = "audio";
       };
     };
-
   };
-
 }
diff --git a/nixos/modules/services/misc/jellyfin.nix b/nixos/modules/services/misc/jellyfin.nix
index 64b74ddd708..04cf82f8a46 100644
--- a/nixos/modules/services/misc/jellyfin.nix
+++ b/nixos/modules/services/misc/jellyfin.nix
@@ -70,7 +70,8 @@ in
         LockPersonality = true;
 
         PrivateTmp = true;
-        PrivateDevices = true;
+        # Disabled to allow Jellyfin to access hw accel devices endpoints
+        # PrivateDevices = true;
         PrivateUsers = true;
 
         # Disabled as it does not allow Jellyfin to interface with CUDA devices
diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix
index b355df056bc..ddd5bcebcdd 100644
--- a/nixos/modules/services/system/earlyoom.nix
+++ b/nixos/modules/services/system/earlyoom.nix
@@ -1,81 +1,73 @@
 { config, lib, pkgs, ... }:
 
-with lib;
-
 let
-  ecfg = config.services.earlyoom;
+  cfg = config.services.earlyoom;
+
+  inherit (lib)
+    mkDefault mkEnableOption mkIf mkOption types
+    mkRemovedOptionModule
+    concatStringsSep optional;
+
 in
 {
-  options = {
-    services.earlyoom = {
+  options.services.earlyoom = {
+    enable = mkEnableOption "Early out of memory killing";
 
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enable early out of memory killing.
-        '';
-      };
+    freeMemThreshold = mkOption {
+      type = types.ints.between 1 100;
+      default = 10;
+      description = ''
+        Minimum of availabe memory (in percent).
+        If the free memory falls below this threshold and the analog is true for
+        <option>services.earlyoom.freeSwapThreshold</option>
+        the killing begins.
+      '';
+    };
 
-      freeMemThreshold = mkOption {
-        type = types.int;
-        default = 10;
-        description = ''
-          Minimum of availabe memory (in percent).
-          If the free memory falls below this threshold and the analog is true for
-          <option>services.earlyoom.freeSwapThreshold</option>
-          the killing begins.
-        '';
-      };
+    freeSwapThreshold = mkOption {
+      type = types.ints.between 1 100;
+      default = 10;
+      description = ''
+        Minimum of availabe swap space (in percent).
+        If the available swap space falls below this threshold and the analog
+        is true for <option>services.earlyoom.freeMemThreshold</option>
+        the killing begins.
+      '';
+    };
 
-      freeSwapThreshold = mkOption {
-        type = types.int;
-        default = 10;
-        description = ''
-          Minimum of availabe swap space (in percent).
-          If the available swap space falls below this threshold and the analog
-          is true for <option>services.earlyoom.freeMemThreshold</option>
-          the killing begins.
-        '';
-      };
+    # TODO: remove or warn after 1.7 (https://github.com/rfjakob/earlyoom/commit/7ebc4554)
+    ignoreOOMScoreAdjust = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Ignore oom_score_adjust values of processes.
+      '';
+    };
 
-      # TODO: remove or warn after 1.7 (https://github.com/rfjakob/earlyoom/commit/7ebc4554)
-      ignoreOOMScoreAdjust = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Ignore oom_score_adjust values of processes.
-        '';
-      };
+    enableDebugInfo = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable debugging messages.
+      '';
+    };
 
-      enableDebugInfo = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Enable debugging messages.
-        '';
-      };
+    enableNotifications = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Send notifications about killed processes via the system d-bus.
 
-      notificationsCommand = mkOption {
-        type = types.nullOr types.str;
-        default = null;
-        description = ''
-          This option is deprecated and ignored by earlyoom since 1.6.
-          Use <option>services.earlyoom.enableNotifications</option> instead.
-        '';
-      };
+        WARNING: enabling this option (while convenient) should *not* be done on a
+        machine where you do not trust the other users as it allows any other
+        local user to DoS your session by spamming notifications.
 
-      enableNotifications = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Send notifications about killed processes via the system d-bus.
-          To actually see the notifications in your GUI session, you need to have
-          <literal>systembus-notify</literal> running as your user.
+        To actually see the notifications in your GUI session, you need to have
+        <literal>systembus-notify</literal> running as your user which this
+        option handles.
 
-          See <link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> for details.
-        '';
-      };
+        See <link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> for details.
+      '';
     };
   };
 
@@ -83,37 +75,30 @@ in
     (mkRemovedOptionModule [ "services" "earlyoom" "useKernelOOMKiller" ] ''
       This option is deprecated and ignored by earlyoom since 1.2.
     '')
+    (mkRemovedOptionModule [ "services" "earlyoom" "notificationsCommand" ] ''
+      This option is deprecated and ignored by earlyoom since 1.6.
+    '')
   ];
 
-  config = mkIf ecfg.enable {
-    assertions = [
-      { assertion = ecfg.freeMemThreshold > 0 && ecfg.freeMemThreshold <= 100;
-        message = "Needs to be a positive percentage"; }
-      { assertion = ecfg.freeSwapThreshold > 0 && ecfg.freeSwapThreshold <= 100;
-        message = "Needs to be a positive percentage"; }
-    ];
-
-    # TODO: reimplement this option as -N after 1.7 (https://github.com/rfjakob/earlyoom/commit/afe03606)
-    warnings = optional (ecfg.notificationsCommand != null)
-      "`services.earlyoom.notificationsCommand` is deprecated and ignored by earlyoom since 1.6.";
+  config = mkIf cfg.enable {
+    services.systembus-notify.enable = mkDefault cfg.enableNotifications;
 
     systemd.services.earlyoom = {
       description = "Early OOM Daemon for Linux";
       wantedBy = [ "multi-user.target" ];
-      path = optional ecfg.enableNotifications pkgs.dbus;
+      path = optional cfg.enableNotifications pkgs.dbus;
       serviceConfig = {
-        StandardOutput = "null";
         StandardError = "journal";
         ExecStart = concatStringsSep " " ([
           "${pkgs.earlyoom}/bin/earlyoom"
-          "-m ${toString ecfg.freeMemThreshold}"
-          "-s ${toString ecfg.freeSwapThreshold}"
-        ] ++ optional ecfg.ignoreOOMScoreAdjust "-i"
-          ++ optional ecfg.enableDebugInfo "-d"
-          ++ optional ecfg.enableNotifications "-n");
+          "-m ${toString cfg.freeMemThreshold}"
+          "-s ${toString cfg.freeSwapThreshold}"
+        ]
+        ++ optional cfg.ignoreOOMScoreAdjust "-i"
+        ++ optional cfg.enableDebugInfo "-d"
+        ++ optional cfg.enableNotifications "-n"
+        );
       };
     };
-
-    environment.systemPackages = optional ecfg.enableNotifications pkgs.systembus-notify;
   };
 }
diff --git a/nixos/modules/services/system/systembus-notify.nix b/nixos/modules/services/system/systembus-notify.nix
new file mode 100644
index 00000000000..e918bc552ec
--- /dev/null
+++ b/nixos/modules/services/system/systembus-notify.nix
@@ -0,0 +1,27 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.systembus-notify;
+
+  inherit (lib) mkEnableOption mkIf;
+
+in
+{
+  options.services.systembus-notify = {
+    enable = mkEnableOption ''
+      System bus notification support
+
+      WARNING: enabling this option (while convenient) should *not* be done on a
+      machine where you do not trust the other users as it allows any other
+      local user to DoS your session by spamming notifications.
+    '';
+  };
+
+  config = mkIf cfg.enable {
+    systemd = {
+      packages = with pkgs; [ systembus-notify ];
+
+      user.services.systembus-notify.wantedBy = [ "graphical-session.target" ];
+    };
+  };
+}
diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl
index a1653d451fe..07ee281feec 100644
--- a/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixos/modules/system/activation/switch-to-configuration.pl
@@ -10,6 +10,8 @@ use Net::DBus;
 use Sys::Syslog qw(:standard :macros);
 use Cwd 'abs_path';
 
+## no critic(CodeLayout::ProhibitParensWithBuiltins)
+
 my $out = "@out@";
 
 my $curSystemd = abs_path("/run/current-system/sw/bin");
@@ -36,13 +38,13 @@ my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list";
 
 make_path("/run/nixos", { mode => oct(755) });
 
-my $action = shift @ARGV;
+my $action = shift(@ARGV);
 
 if ("@localeArchive@" ne "") {
     $ENV{LOCALE_ARCHIVE} = "@localeArchive@";
 }
 
-if (!defined $action || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) {
+if (!defined($action) || ($action ne "switch" && $action ne "boot" && $action ne "test" && $action ne "dry-activate")) {
     print STDERR <<EOF;
 Usage: $0 [switch|boot|test]
 
@@ -51,27 +53,27 @@ boot:         make the configuration the boot default
 test:         activate the configuration, but don\'t make it the boot default
 dry-activate: show what would be done if this configuration were activated
 EOF
-    exit 1;
+    exit(1);
 }
 
 $ENV{NIXOS_ACTION} = $action;
 
 # This is a NixOS installation if it has /etc/NIXOS or a proper
 # /etc/os-release.
-die "This is not a NixOS installation!\n" unless
+die("This is not a NixOS installation!\n") unless
     -f "/etc/NIXOS" || (read_file("/etc/os-release", err_mode => 'quiet') // "") =~ /ID="?nixos"?/s;
 
 openlog("nixos", "", LOG_USER);
 
 # Install or update the bootloader.
 if ($action eq "switch" || $action eq "boot") {
-    system("@installBootLoader@ $out") == 0 or exit 1;
+    system('@installBootLoader@', $out) == 0 or exit 1;
 }
 
 # Just in case the new configuration hangs the system, do a sync now.
 system("@coreutils@/bin/sync", "-f", "/nix/store") unless ($ENV{"NIXOS_NO_SYNC"} // "") eq "1";
 
-exit 0 if $action eq "boot";
+exit(0) if $action eq "boot";
 
 # Check if we can activate the new configuration.
 my $oldVersion = read_file("/run/current-system/init-interface-version", err_mode => 'quiet') // "";
@@ -83,7 +85,7 @@ Warning: the new NixOS configuration has an ‘init’ that is
 incompatible with the current configuration.  The new configuration
 won\'t take effect until you reboot the system.
 EOF
-    exit 100;
+    exit(100);
 }
 
 # Ignore SIGHUP so that we're not killed if we're running on (say)
@@ -104,14 +106,27 @@ sub getActiveUnits {
     return $res;
 }
 
+# Returns whether a systemd unit is active
+sub unit_is_active {
+    my ($unit_name) = @_;
+
+    my $mgr = Net::DBus->system->get_service('org.freedesktop.systemd1')->get_object('/org/freedesktop/systemd1');
+    my $units = $mgr->ListUnitsByNames([$unit_name]);
+    if (scalar(@{$units}) == 0) {
+        return 0;
+    }
+    my $active_state = $units->[0]->[3]; ## no critic (ValuesAndExpressions::ProhibitMagicNumbers)
+    return $active_state eq 'active' || $active_state eq 'activating';
+}
+
 sub parseFstab {
     my ($filename) = @_;
     my ($fss, $swaps);
     foreach my $line (read_file($filename, err_mode => 'quiet')) {
-        chomp $line;
+        chomp($line);
         $line =~ s/^\s*#.*//;
         next if $line =~ /^\s*$/;
-        my @xs = split / /, $line;
+        my @xs = split(/ /, $line);
         if ($xs[2] eq "swap") {
             $swaps->{$xs[0]} = { options => $xs[3] // "" };
         } else {
@@ -133,17 +148,16 @@ sub parseFstab {
 sub parseSystemdIni {
     my ($unitContents, $path) = @_;
     # Tie the ini file to a hash for easier access
-    my %fileContents;
-    tie %fileContents, "Config::IniFiles", (-file => $path, -allowempty => 1, -allowcontinue => 1);
+    tie(my %fileContents, 'Config::IniFiles', (-file => $path, -allowempty => 1, -allowcontinue => 1)); ## no critic(Miscellanea::ProhibitTies)
 
     # Copy over all sections
-    foreach my $sectionName (keys %fileContents) {
+    foreach my $sectionName (keys(%fileContents)) {
         if ($sectionName eq "Install") {
             # Skip the [Install] section because it has no relevant keys for us
             next;
         }
         # Copy over all keys
-        foreach my $iniKey (keys %{$fileContents{$sectionName}}) {
+        foreach my $iniKey (keys(%{$fileContents{$sectionName}})) {
             # Ensure the value is an array so it's easier to work with
             my $iniValue = $fileContents{$sectionName}{$iniKey};
             my @iniValues;
@@ -181,7 +195,7 @@ sub parse_unit {
     # Replace \ with \\ so glob() still works with units that have a \ in them
     # Valid characters in unit names are ASCII letters, digits, ":", "-", "_", ".", and "\"
     $unit_path =~ s/\\/\\\\/gmsx;
-    foreach (glob "${unit_path}{,.d/*.conf}") {
+    foreach (glob("${unit_path}{,.d/*.conf}")) {
         parseSystemdIni(\%unit_data, "$_")
     }
     return %unit_data;
@@ -194,7 +208,7 @@ sub parseSystemdBool {
 
     my @values = @{$unitConfig->{$sectionName}{$boolName} // []};
     # Return default if value is not set
-    if (scalar @values lt 1 || not defined $values[-1]) {
+    if (scalar(@values) lt 1 || not defined($values[-1])) {
         return $default;
     }
     # If value is defined multiple times, use the last definition
@@ -211,7 +225,7 @@ sub recordUnit {
 # The opposite of recordUnit, removes a unit name from a file
 sub unrecord_unit {
     my ($fn, $unit) = @_;
-    edit_file { s/^$unit\n//msx } $fn if $action ne "dry-activate";
+    edit_file(sub { s/^$unit\n//msx }, $fn) if $action ne "dry-activate";
 }
 
 # Compare the contents of two unit files and return whether the unit
@@ -226,6 +240,16 @@ sub unrecord_unit {
 sub compare_units {
     my ($old_unit, $new_unit) = @_;
     my $ret = 0;
+    # Keys to ignore in the [Unit] section
+    my %unit_section_ignores = map { $_ => 1 } qw(
+        X-Reload-Triggers
+        Description Documentation
+        OnFailure OnSuccess OnFailureJobMode
+        IgnoreOnIsolate StopWhenUnneeded
+        RefuseManualStart RefuseManualStop
+        AllowIsolate CollectMode
+        SourcePath
+    );
 
     my $comp_array = sub {
       my ($a, $b) = @_;
@@ -233,11 +257,23 @@ sub compare_units {
     };
 
     # Comparison hash for the sections
-    my %section_cmp = map { $_ => 1 } keys %{$new_unit};
+    my %section_cmp = map { $_ => 1 } keys(%{$new_unit});
     # Iterate over the sections
-    foreach my $section_name (keys %{$old_unit}) {
+    foreach my $section_name (keys(%{$old_unit})) {
         # Missing section in the new unit?
-        if (not exists $section_cmp{$section_name}) {
+        if (not exists($section_cmp{$section_name})) {
+            # If the [Unit] section was removed, make sure that only keys
+            # were in it that are ignored
+            if ($section_name eq 'Unit') {
+                foreach my $ini_key (keys(%{$old_unit->{'Unit'}})) {
+                    if (not defined($unit_section_ignores{$ini_key})) {
+                        return 1;
+                    }
+                }
+                next; # check the next section
+            } else {
+                return 1;
+            }
             if ($section_name eq 'Unit' and %{$old_unit->{'Unit'}} == 1 and defined(%{$old_unit->{'Unit'}}{'X-Reload-Triggers'})) {
                 # If a new [Unit] section was removed that only contained X-Reload-Triggers,
                 # do nothing.
@@ -248,15 +284,15 @@ sub compare_units {
         }
         delete $section_cmp{$section_name};
         # Comparison hash for the section contents
-        my %ini_cmp = map { $_ => 1 } keys %{$new_unit->{$section_name}};
+        my %ini_cmp = map { $_ => 1 } keys(%{$new_unit->{$section_name}});
         # Iterate over the keys of the section
-        foreach my $ini_key (keys %{$old_unit->{$section_name}}) {
+        foreach my $ini_key (keys(%{$old_unit->{$section_name}})) {
             delete $ini_cmp{$ini_key};
             my @old_value = @{$old_unit->{$section_name}{$ini_key}};
             # If the key is missing in the new unit, they are different...
             if (not $new_unit->{$section_name}{$ini_key}) {
-                # ... unless the key that is now missing was the reload trigger
-                if ($section_name eq 'Unit' and $ini_key eq 'X-Reload-Triggers') {
+                # ... unless the key that is now missing is one of the ignored keys
+                if ($section_name eq 'Unit' and defined($unit_section_ignores{$ini_key})) {
                     next;
                 }
                 return 1;
@@ -264,19 +300,30 @@ sub compare_units {
             my @new_value = @{$new_unit->{$section_name}{$ini_key}};
             # If the contents are different, the units are different
             if (not $comp_array->(\@old_value, \@new_value)) {
-                # Check if only the reload triggers changed
-                if ($section_name eq 'Unit' and $ini_key eq 'X-Reload-Triggers') {
-                    $ret = 2;
-                } else {
-                    return 1;
+                # Check if only the reload triggers changed or one of the ignored keys
+                if ($section_name eq 'Unit') {
+                    if ($ini_key eq 'X-Reload-Triggers') {
+                        $ret = 2;
+                        next;
+                    } elsif (defined($unit_section_ignores{$ini_key})) {
+                        next;
+                    }
                 }
+                return 1;
             }
         }
         # A key was introduced that was missing in the old unit
         if (%ini_cmp) {
-            if ($section_name eq 'Unit' and %ini_cmp == 1 and defined($ini_cmp{'X-Reload-Triggers'})) {
-                # If the newly introduced key was the reload triggers, reload the unit
-                $ret = 2;
+            if ($section_name eq 'Unit') {
+                foreach my $ini_key (keys(%ini_cmp)) {
+                    if ($ini_key eq 'X-Reload-Triggers') {
+                        $ret = 2;
+                    } elsif (defined($unit_section_ignores{$ini_key})) {
+                        next;
+                    } else {
+                        return 1;
+                    }
+                }
             } else {
                 return 1;
             }
@@ -284,10 +331,14 @@ sub compare_units {
     }
     # A section was introduced that was missing in the old unit
     if (%section_cmp) {
-        if (%section_cmp == 1 and defined($section_cmp{'Unit'}) and %{$new_unit->{'Unit'}} == 1 and defined(%{$new_unit->{'Unit'}}{'X-Reload-Triggers'})) {
-            # If a new [Unit] section was introduced that only contains X-Reload-Triggers,
-            # reload instead of restarting
-            $ret = 2;
+        if (%section_cmp == 1 and defined($section_cmp{'Unit'})) {
+            foreach my $ini_key (keys(%{$new_unit->{'Unit'}})) {
+                if (not defined($unit_section_ignores{$ini_key})) {
+                    return 1;
+                } elsif ($ini_key eq 'X-Reload-Triggers') {
+                    $ret = 2;
+                }
+            }
         } else {
             return 1;
         }
@@ -343,11 +394,11 @@ sub handleModifiedUnit {
                 my $socket_activated = 0;
                 if ($unit =~ /\.service$/) {
                     my @sockets = split(/ /, join(" ", @{$unitInfo{Service}{Sockets} // []}));
-                    if (scalar @sockets == 0) {
+                    if (scalar(@sockets) == 0) {
                         @sockets = ("$baseName.socket");
                     }
                     foreach my $socket (@sockets) {
-                        if (defined $activePrev->{$socket}) {
+                        if (defined($activePrev->{$socket})) {
                             # We can now be sure this is a socket-activate unit
 
                             $unitsToStop->{$socket} = 1;
@@ -355,7 +406,11 @@ sub handleModifiedUnit {
                             # exist in new configuration:
                             if (-e "$out/etc/systemd/system/$socket") {
                                 $unitsToStart->{$socket} = 1;
-                                recordUnit($startListFile, $socket);
+                                if ($unitsToStart eq $unitsToRestart) {
+                                    recordUnit($restartListFile, $socket);
+                                } else {
+                                    recordUnit($startListFile, $socket);
+                                }
                                 $socket_activated = 1;
                             }
                             # Remove from units to reload so we don't restart and reload
@@ -373,7 +428,11 @@ sub handleModifiedUnit {
                 # service gets restarted if we're interrupted.
                 if (!$socket_activated) {
                     $unitsToStart->{$unit} = 1;
-                    recordUnit($startListFile, $unit);
+                    if ($unitsToStart eq $unitsToRestart) {
+                        recordUnit($restartListFile, $unit);
+                    } else {
+                        recordUnit($startListFile, $unit);
+                    }
                 }
 
                 $unitsToStop->{$unit} = 1;
@@ -401,8 +460,8 @@ $unitsToRestart{$_} = 1 foreach
 $unitsToReload{$_} = 1 foreach
     split('\n', read_file($reloadListFile, err_mode => 'quiet') // "");
 
-my $activePrev = getActiveUnits;
-while (my ($unit, $state) = each %{$activePrev}) {
+my $activePrev = getActiveUnits();
+while (my ($unit, $state) = each(%{$activePrev})) {
     my $baseUnit = $unit;
 
     my $prevUnitFile = "/etc/systemd/system/$baseUnit";
@@ -462,9 +521,9 @@ while (my ($unit, $state) = each %{$activePrev}) {
             my %old_unit_info = parse_unit($prevUnitFile);
             my %new_unit_info = parse_unit($newUnitFile);
             my $diff = compare_units(\%old_unit_info, \%new_unit_info);
-            if ($diff eq 1) {
+            if ($diff == 1) {
                 handleModifiedUnit($unit, $baseName, $newUnitFile, \%new_unit_info, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
-            } elsif ($diff eq 2 and not $unitsToRestart{$unit}) {
+            } elsif ($diff == 2 and not $unitsToRestart{$unit}) {
                 $unitsToReload{$unit} = 1;
                 recordUnit($reloadListFile, $unit);
             }
@@ -475,11 +534,11 @@ while (my ($unit, $state) = each %{$activePrev}) {
 sub pathToUnitName {
     my ($path) = @_;
     # Use current version of systemctl binary before daemon is reexeced.
-    open my $cmd, "-|", "$curSystemd/systemd-escape", "--suffix=mount", "-p", $path
+    open(my $cmd, "-|", "$curSystemd/systemd-escape", "--suffix=mount", "-p", $path)
         or die "Unable to escape $path!\n";
-    my $escaped = join "", <$cmd>;
-    chomp $escaped;
-    close $cmd or die;
+    my $escaped = join("", <$cmd>);
+    chomp($escaped);
+    close($cmd) or die('Unable to close systemd-escape pipe');
     return $escaped;
 }
 
@@ -488,13 +547,13 @@ sub pathToUnitName {
 # automatically by starting local-fs.target.  FIXME: might be nicer if
 # we generated units for all mounts; then we could unify this with the
 # unit checking code above.
-my ($prevFss, $prevSwaps) = parseFstab "/etc/fstab";
-my ($newFss, $newSwaps) = parseFstab "$out/etc/fstab";
-foreach my $mountPoint (keys %$prevFss) {
+my ($prevFss, $prevSwaps) = parseFstab("/etc/fstab");
+my ($newFss, $newSwaps) = parseFstab("$out/etc/fstab");
+foreach my $mountPoint (keys(%$prevFss)) {
     my $prev = $prevFss->{$mountPoint};
     my $new = $newFss->{$mountPoint};
     my $unit = pathToUnitName($mountPoint);
-    if (!defined $new) {
+    if (!defined($new)) {
         # Filesystem entry disappeared, so unmount it.
         $unitsToStop{$unit} = 1;
     } elsif ($prev->{fsType} ne $new->{fsType} || $prev->{device} ne $new->{device}) {
@@ -510,10 +569,10 @@ foreach my $mountPoint (keys %$prevFss) {
 }
 
 # Also handles swap devices.
-foreach my $device (keys %$prevSwaps) {
+foreach my $device (keys(%$prevSwaps)) {
     my $prev = $prevSwaps->{$device};
     my $new = $newSwaps->{$device};
-    if (!defined $new) {
+    if (!defined($new)) {
         # Swap entry disappeared, so turn it off.  Can't use
         # "systemctl stop" here because systemd has lots of alias
         # units that prevent a stop from actually calling
@@ -544,8 +603,8 @@ if ($prevSystemdSystemConfig ne $newSystemdSystemConfig) {
 sub filterUnits {
     my ($units) = @_;
     my @res;
-    foreach my $unit (sort(keys %{$units})) {
-        push @res, $unit if !defined $unitsToFilter{$unit};
+    foreach my $unit (sort(keys(%{$units}))) {
+        push(@res, $unit) if !defined($unitsToFilter{$unit});
     }
     return @res;
 }
@@ -556,9 +615,9 @@ my @unitsToStopFiltered = filterUnits(\%unitsToStop);
 # Show dry-run actions.
 if ($action eq "dry-activate") {
     print STDERR "would stop the following units: ", join(", ", @unitsToStopFiltered), "\n"
-        if scalar @unitsToStopFiltered > 0;
-    print STDERR "would NOT stop the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n"
-        if scalar(keys %unitsToSkip) > 0;
+        if scalar(@unitsToStopFiltered) > 0;
+    print STDERR "would NOT stop the following changed units: ", join(", ", sort(keys(%unitsToSkip))), "\n"
+        if scalar(keys(%unitsToSkip)) > 0;
 
     print STDERR "would activate the configuration...\n";
     system("$out/dry-activate", "$out");
@@ -579,7 +638,7 @@ if ($action eq "dry-activate") {
         $baseName =~ s/\.[a-z]*$//;
 
         # Start units if they were not active previously
-        if (not defined $activePrev->{$unit}) {
+        if (not defined($activePrev->{$unit})) {
             $unitsToStart{$unit} = 1;
             next;
         }
@@ -599,28 +658,28 @@ if ($action eq "dry-activate") {
     unlink($dryReloadByActivationFile);
 
     print STDERR "would restart systemd\n" if $restartSystemd;
-    print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
-        if scalar(keys %unitsToReload) > 0;
-    print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
-        if scalar(keys %unitsToRestart) > 0;
+    print STDERR "would reload the following units: ", join(", ", sort(keys(%unitsToReload))), "\n"
+        if scalar(keys(%unitsToReload)) > 0;
+    print STDERR "would restart the following units: ", join(", ", sort(keys(%unitsToRestart))), "\n"
+        if scalar(keys(%unitsToRestart)) > 0;
     my @unitsToStartFiltered = filterUnits(\%unitsToStart);
     print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
-        if scalar @unitsToStartFiltered;
+        if scalar(@unitsToStartFiltered);
     exit 0;
 }
 
 
 syslog(LOG_NOTICE, "switching to system configuration $out");
 
-if (scalar (keys %unitsToStop) > 0) {
+if (scalar(keys(%unitsToStop)) > 0) {
     print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n"
-        if scalar @unitsToStopFiltered;
+        if scalar(@unitsToStopFiltered);
     # Use current version of systemctl binary before daemon is reexeced.
-    system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop));
+    system("$curSystemd/systemctl", "stop", "--", sort(keys(%unitsToStop)));
 }
 
-print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n"
-    if scalar(keys %unitsToSkip) > 0;
+print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys(%unitsToSkip))), "\n"
+    if scalar(keys(%unitsToSkip)) > 0;
 
 # Activate the new configuration (i.e., update /etc, make accounts,
 # and so on).
@@ -644,7 +703,7 @@ foreach (split('\n', read_file($restartByActivationFile, err_mode => 'quiet') //
     $baseName =~ s/\.[a-z]*$//;
 
     # Start units if they were not active previously
-    if (not defined $activePrev->{$unit}) {
+    if (not defined($activePrev->{$unit})) {
         $unitsToStart{$unit} = 1;
         recordUnit($startListFile, $unit);
         next;
@@ -681,7 +740,7 @@ system("@systemd@/bin/systemctl", "reset-failed");
 system("@systemd@/bin/systemctl", "daemon-reload") == 0 or $res = 3;
 
 # Reload user units
-open my $listActiveUsers, '-|', '@systemd@/bin/loginctl', 'list-users', '--no-legend';
+open(my $listActiveUsers, '-|', '@systemd@/bin/loginctl', 'list-users', '--no-legend');
 while (my $f = <$listActiveUsers>) {
     next unless $f =~ /^\s*(?<uid>\d+)\s+(?<user>\S+)/;
     my ($uid, $name) = ($+{uid}, $+{user});
@@ -693,25 +752,43 @@ while (my $f = <$listActiveUsers>) {
            "@systemd@/bin/systemctl --user start nixos-activation.service");
 }
 
-close $listActiveUsers;
+close($listActiveUsers);
 
 # Set the new tmpfiles
 print STDERR "setting up tmpfiles\n";
 system("@systemd@/bin/systemd-tmpfiles", "--create", "--remove", "--exclude-prefix=/dev") == 0 or $res = 3;
 
+# Before reloading we need to ensure that the units are still active. They may have been
+# deactivated because one of their requirements got stopped. If they are inactive
+# but should have been reloaded, the user probably expects them to be started.
+if (scalar(keys(%unitsToReload)) > 0) {
+    for my $unit (keys(%unitsToReload)) {
+        if (!unit_is_active($unit)) {
+            # Figure out if we need to start the unit
+            my %unit_info = parse_unit("$out/etc/systemd/system/$unit");
+            if (!(parseSystemdBool(\%unit_info, 'Unit', 'RefuseManualStart', 0) || parseSystemdBool(\%unit_info, 'Unit', 'X-OnlyManualStart', 0))) {
+                $unitsToStart{$unit} = 1;
+                recordUnit($startListFile, $unit);
+            }
+            # Don't reload the unit, reloading would fail
+            delete %unitsToReload{$unit};
+            unrecord_unit($reloadListFile, $unit);
+        }
+    }
+}
 # Reload units that need it. This includes remounting changed mount
 # units.
-if (scalar(keys %unitsToReload) > 0) {
-    print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n";
-    system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4;
+if (scalar(keys(%unitsToReload)) > 0) {
+    print STDERR "reloading the following units: ", join(", ", sort(keys(%unitsToReload))), "\n";
+    system("@systemd@/bin/systemctl", "reload", "--", sort(keys(%unitsToReload))) == 0 or $res = 4;
     unlink($reloadListFile);
 }
 
 # Restart changed services (those that have to be restarted rather
 # than stopped and started).
-if (scalar(keys %unitsToRestart) > 0) {
-    print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n";
-    system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4;
+if (scalar(keys(%unitsToRestart)) > 0) {
+    print STDERR "restarting the following units: ", join(", ", sort(keys(%unitsToRestart))), "\n";
+    system("@systemd@/bin/systemctl", "restart", "--", sort(keys(%unitsToRestart))) == 0 or $res = 4;
     unlink($restartListFile);
 }
 
@@ -723,17 +800,17 @@ if (scalar(keys %unitsToRestart) > 0) {
 # systemd.
 my @unitsToStartFiltered = filterUnits(\%unitsToStart);
 print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
-    if scalar @unitsToStartFiltered;
-system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4;
+    if scalar(@unitsToStartFiltered);
+system("@systemd@/bin/systemctl", "start", "--", sort(keys(%unitsToStart))) == 0 or $res = 4;
 unlink($startListFile);
 
 
 # Print failed and new units.
 my (@failed, @new);
-my $activeNew = getActiveUnits;
-while (my ($unit, $state) = each %{$activeNew}) {
+my $activeNew = getActiveUnits();
+while (my ($unit, $state) = each(%{$activeNew})) {
     if ($state->{state} eq "failed") {
-        push @failed, $unit;
+        push(@failed, $unit);
         next;
     }
 
@@ -743,7 +820,7 @@ while (my ($unit, $state) = each %{$activeNew}) {
         chomp($main_status);
 
         if ($main_status ne "0") {
-            push @failed, $unit;
+            push(@failed, $unit);
             next;
         }
     }
@@ -751,19 +828,19 @@ while (my ($unit, $state) = each %{$activeNew}) {
     # Ignore scopes since they are not managed by this script but rather
     # created and managed by third-party services via the systemd dbus API.
     # This only lists units that are not failed (including ones that are in auto-restart but have not failed previously)
-    if ($state->{state} ne "failed" && !defined $activePrev->{$unit} && $unit !~ /\.scope$/msx) {
-        push @new, $unit;
+    if ($state->{state} ne "failed" && !defined($activePrev->{$unit}) && $unit !~ /\.scope$/msx) {
+        push(@new, $unit);
     }
 }
 
-if (scalar @new > 0) {
+if (scalar(@new) > 0) {
     print STDERR "the following new units were started: ", join(", ", sort(@new)), "\n"
 }
 
-if (scalar @failed > 0) {
-    my @failed_sorted = sort @failed;
+if (scalar(@failed) > 0) {
+    my @failed_sorted = sort(@failed);
     print STDERR "warning: the following units failed: ", join(", ", @failed_sorted), "\n\n";
-    system "@systemd@/bin/systemctl status --no-pager --full '" . join("' '", @failed_sorted) . "' >&2";
+    system("@systemd@/bin/systemctl status --no-pager --full '" . join("' '", @failed_sorted) . "' >&2");
     $res = 4;
 }
 
@@ -773,4 +850,4 @@ if ($res == 0) {
     syslog(LOG_ERR, "switching to system configuration $out failed (status $res)");
 }
 
-exit $res;
+exit($res);
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index adc89306309..fa879437fd8 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -15,9 +15,12 @@ import re
 import datetime
 import glob
 import os.path
-from typing import Tuple, List, Optional
+from typing import NamedTuple, List, Optional
 
-SystemIdentifier = Tuple[Optional[str], int, Optional[str]]
+class SystemIdentifier(NamedTuple):
+    profile: Optional[str]
+    generation: int
+    specialisation: Optional[str]
 
 
 def copy_if_not_exists(source: str, dest: str) -> None:
@@ -151,7 +154,14 @@ def get_generations(profile: Optional[str] = None) -> List[SystemIdentifier]:
     gen_lines.pop()
 
     configurationLimit = @configurationLimit@
-    configurations: List[SystemIdentifier] = [ (profile, int(line.split()[0]), None) for line in gen_lines ]
+    configurations = [
+        SystemIdentifier(
+            profile=profile,
+            generation=int(line.split()[0]),
+            specialisation=None
+        )
+        for line in gen_lines
+    ]
     return configurations[-configurationLimit:]
 
 
@@ -160,7 +170,7 @@ def get_specialisations(profile: Optional[str], generation: int, _: Optional[str
             system_dir(profile, generation, None), "specialisation")
     if not os.path.exists(specialisations_dir):
         return []
-    return [(profile, generation, spec) for spec in os.listdir(specialisations_dir)]
+    return [SystemIdentifier(profile, generation, spec) for spec in os.listdir(specialisations_dir)]
 
 
 def remove_old_entries(gens: List[SystemIdentifier]) -> None:
@@ -271,7 +281,8 @@ def main() -> None:
             if os.readlink(system_dir(*gen)) == args.default_config:
                 write_loader_conf(*gen)
         except OSError as e:
-            print("ignoring generation '{}' in the list of boot entries because of the following error:\n{}".format(*gen, e), file=sys.stderr)
+            profile = f"profile '{gen.profile}'" if gen.profile else "default profile"
+            print("ignoring {} in the list of boot entries because of the following error:\n{}".format(profile, e), file=sys.stderr)
 
     for root, _, files in os.walk('@efiSysMountPoint@/efi/nixos/.extra-files', topdown=False):
         relative_root = root.removeprefix("@efiSysMountPoint@/efi/nixos/.extra-files").removeprefix("/")
diff --git a/nixos/tests/switch-test.nix b/nixos/tests/switch-test.nix
index 78eb71f0a28..93eee4babc2 100644
--- a/nixos/tests/switch-test.nix
+++ b/nixos/tests/switch-test.nix
@@ -64,6 +64,11 @@ in {
           };
         };
 
+        simpleServiceDifferentDescription.configuration = {
+          imports = [ simpleService.configuration ];
+          systemd.services.test.description = "Test unit";
+        };
+
         simpleServiceModified.configuration = {
           imports = [ simpleService.configuration ];
           systemd.services.test.serviceConfig.X-Test = true;
@@ -203,6 +208,39 @@ in {
           systemd.services."escaped\\x2ddash".serviceConfig.X-Test = "test";
         };
 
+        unitWithRequirement.configuration = {
+          systemd.services.required-service = {
+            wantedBy = [ "multi-user.target" ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+              ExecStart = "${pkgs.coreutils}/bin/true";
+              ExecReload = "${pkgs.coreutils}/bin/true";
+            };
+          };
+          systemd.services.test-service = {
+            wantedBy = [ "multi-user.target" ];
+            requires = [ "required-service.service" ];
+            serviceConfig = {
+              Type = "oneshot";
+              RemainAfterExit = true;
+              ExecStart = "${pkgs.coreutils}/bin/true";
+              ExecReload = "${pkgs.coreutils}/bin/true";
+            };
+          };
+        };
+
+        unitWithRequirementModified.configuration = {
+          imports = [ unitWithRequirement.configuration ];
+          systemd.services.required-service.serviceConfig.X-Test = "test";
+          systemd.services.test-service.reloadTriggers = [ "test" ];
+        };
+
+        unitWithRequirementModifiedNostart.configuration = {
+          imports = [ unitWithRequirement.configuration ];
+          systemd.services.test-service.unitConfig.RefuseManualStart = true;
+        };
+
         restart-and-reload-by-activation-script.configuration = {
           systemd.services = rec {
             simple-service = {
@@ -350,6 +388,31 @@ in {
           systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
         };
 
+        hybridSleepModified.configuration = {
+          systemd.targets.hybrid-sleep.unitConfig.X-Test = true;
+        };
+
+        target.configuration = {
+          systemd.targets.test-target.wantedBy = [ "multi-user.target" ];
+          # We use this service to figure out whether the target was modified.
+          # This is the only way because targets are filtered and therefore not
+          # printed when they are started/stopped.
+          systemd.services.test-service = {
+            bindsTo = [ "test-target.target" ];
+            serviceConfig.ExecStart = "${pkgs.coreutils}/bin/sleep infinity";
+          };
+        };
+
+        targetModified.configuration = {
+          imports = [ target.configuration ];
+          systemd.targets.test-target.unitConfig.X-Test = true;
+        };
+
+        targetModifiedStopOnReconfig.configuration = {
+          imports = [ target.configuration ];
+          systemd.targets.test-target.unitConfig.X-StopOnReconfiguration = true;
+        };
+
         path.configuration = {
           systemd.paths.test-watch = {
             wantedBy = [ "paths.target" ];
@@ -472,6 +535,15 @@ in {
         assert_lacks(out, "\nstarting the following units:")
         assert_lacks(out, "the following new units were started:")
 
+        # Only changing the description does nothing
+        out = switch_to_specialisation("${machine}", "simpleServiceDifferentDescription")
+        assert_lacks(out, "stopping the following units:")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_lacks(out, "the following new units were started:")
+
         # Restart the simple service
         out = switch_to_specialisation("${machine}", "simpleServiceModified")
         assert_contains(out, "stopping the following units: test.service\n")
@@ -535,6 +607,32 @@ in {
         assert_contains(out, "\nstarting the following units: escaped\\x2ddash.service\n")
         assert_lacks(out, "the following new units were started:")
 
+        # Ensure units that require changed units are properly reloaded
+        out = switch_to_specialisation("${machine}", "unitWithRequirement")
+        assert_contains(out, "stopping the following units: escaped\\x2ddash.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_contains(out, "the following new units were started: required-service.service, test-service.service\n")
+
+        out = switch_to_specialisation("${machine}", "unitWithRequirementModified")
+        assert_contains(out, "stopping the following units: required-service.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_contains(out, "\nstarting the following units: required-service.service, test-service.service\n")
+        assert_lacks(out, "the following new units were started:")
+
+        # Unless the unit asks to be not restarted
+        out = switch_to_specialisation("${machine}", "unitWithRequirementModifiedNostart")
+        assert_contains(out, "stopping the following units: required-service.service\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_contains(out, "\nstarting the following units: required-service.service\n")
+        assert_lacks(out, "the following new units were started:")
+
     with subtest("failing units"):
         # Let the simple service fail
         switch_to_specialisation("${machine}", "simpleServiceModified")
@@ -821,6 +919,55 @@ in {
         out = machine.succeed("systemctl show test-timer.timer")
         assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
 
+    with subtest("targets"):
+        # Modifying some special targets like hybrid-sleep.target does nothing
+        out = switch_to_specialisation("${machine}", "hybridSleepModified")
+        assert_contains(out, "stopping the following units: test-timer.timer\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_lacks(out, "the following new units were started:")
+
+        # Adding a new target starts it
+        out = switch_to_specialisation("${machine}", "target")
+        assert_lacks(out, "stopping the following units:")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_contains(out, "the following new units were started: test-target.target\n")
+
+        # Changing a target doesn't print anything because the unit is filtered
+        machine.systemctl("start test-service.service")
+        out = switch_to_specialisation("${machine}", "targetModified")
+        assert_lacks(out, "stopping the following units:")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_lacks(out, "the following new units were started:")
+        machine.succeed("systemctl is-active test-service.service")  # target was not restarted
+
+        # With X-StopOnReconfiguration, the target gets stopped and started
+        out = switch_to_specialisation("${machine}", "targetModifiedStopOnReconfig")
+        assert_lacks(out, "stopping the following units:")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_lacks(out, "the following new units were started:")
+        machine.fail("systemctl is-active test-service.servce")  # target was restarted
+
+        # Remove the target by switching to the old specialisation
+        out = switch_to_specialisation("${machine}", "timerModified")
+        assert_contains(out, "stopping the following units: test-target.target\n")
+        assert_lacks(out, "NOT restarting the following changed units:")
+        assert_lacks(out, "reloading the following units:")
+        assert_lacks(out, "\nrestarting the following units:")
+        assert_lacks(out, "\nstarting the following units:")
+        assert_contains(out, "the following new units were started: test-timer.timer\n")
+
     with subtest("paths"):
         out = switch_to_specialisation("${machine}", "path")
         assert_contains(out, "stopping the following units: test-timer.timer\n")
diff --git a/pkgs/applications/audio/squeezelite/default.nix b/pkgs/applications/audio/squeezelite/default.nix
index 31fe69b00de..5fc0d6f4200 100644
--- a/pkgs/applications/audio/squeezelite/default.nix
+++ b/pkgs/applications/audio/squeezelite/default.nix
@@ -1,39 +1,50 @@
-{ lib, stdenv, fetchFromGitHub
-, alsa-lib, flac, libmad, libvorbis, mpg123
+{ lib
+, stdenv
+, fetchFromGitHub
+, alsa-lib
+, flac
+, libmad
+, libpulseaudio
+, libvorbis
+, mpg123
+, audioBackend ? "alsa"
 , dsdSupport ? true
-, faad2Support ? true, faad2
-, ffmpegSupport ? true, ffmpeg
-, opusSupport ? true, opusfile
-, resampleSupport ? true, soxr
-, sslSupport ? true, openssl
+, faad2Support ? true
+, faad2
+, ffmpegSupport ? true
+, ffmpeg
+, opusSupport ? true
+, opusfile
+, resampleSupport ? true
+, soxr
+, sslSupport ? true
+, openssl
 }:
 
 let
-  concatStringsSep = lib.concatStringsSep;
-  optional = lib.optional;
-  opts = [ "-DLINKALL" ]
-    ++ optional dsdSupport "-DDSD"
-    ++ optional (!faad2Support) "-DNO_FAAD"
-    ++ optional ffmpegSupport "-DFFMPEG"
-    ++ optional opusSupport "-DOPUS"
-    ++ optional resampleSupport "-DRESAMPLE"
-    ++ optional sslSupport "-DUSE_SSL";
+  inherit (lib) optional optionalString;
 
-in stdenv.mkDerivation {
-  pname = "squeezelite";
+  pulseSupport = audioBackend == "pulse";
 
+  binName = "squeezelite${optionalString pulseSupport "-pulse"}";
+
+in
+stdenv.mkDerivation {
+  # the nixos module uses the pname as the binary name
+  pname = binName;
   # versions are specified in `squeezelite.h`
   # see https://github.com/ralph-irving/squeezelite/issues/29
-  version = "1.9.6.1196";
+  version = "1.9.9.1401";
 
   src = fetchFromGitHub {
-    owner  = "ralph-irving";
-    repo   = "squeezelite";
-    rev    = "2b508464dce2cbdb2a3089c58df2a6fbc36328c0";
-    sha256 = "024ypr1da2r079k3hgiifzd3d3wcfprhbl5zdm40zm0c7frzmr8i";
+    owner = "ralph-irving";
+    repo = "squeezelite";
+    rev = "894df3ea80f66a27a9ae5fab918acf62a6798b8b";
+    hash = "sha256-LIi+9vb0+56AGvVrLx4gQaUkUNjIi6PmqrLViLT1DSU=";
   };
 
-  buildInputs = [ alsa-lib flac libmad libvorbis mpg123 ]
+  buildInputs = [ flac libmad libvorbis mpg123 ]
+    ++ lib.singleton (if pulseSupport then libpulseaudio else alsa-lib)
     ++ optional faad2Support faad2
     ++ optional ffmpegSupport ffmpeg
     ++ optional opusSupport opusfile
@@ -47,15 +58,22 @@ in stdenv.mkDerivation {
       --replace "<opusfile.h>" "<opus/opusfile.h>"
   '';
 
-  preBuild = ''
-    export OPTS="${concatStringsSep " " opts}"
-  '';
+  EXECUTABLE = binName;
+
+  OPTS = [ "-DLINKALL" ]
+    ++ optional dsdSupport "-DDSD"
+    ++ optional (!faad2Support) "-DNO_FAAD"
+    ++ optional ffmpegSupport "-DFFMPEG"
+    ++ optional opusSupport "-DOPUS"
+    ++ optional pulseSupport "-DPULSEAUDIO"
+    ++ optional resampleSupport "-DRESAMPLE"
+    ++ optional sslSupport "-DUSE_SSL";
 
   installPhase = ''
     runHook preInstall
 
-    install -Dm755 -t $out/bin                   squeezelite
-    install -Dm644 -t $out/share/doc/squeezelite *.txt *.md
+    install -Dm555 -t $out/bin                   ${binName}
+    install -Dm444 -t $out/share/doc/squeezelite *.txt *.md
 
     runHook postInstall
   '';
@@ -63,7 +81,7 @@ in stdenv.mkDerivation {
   meta = with lib; {
     description = "Lightweight headless squeezebox client emulator";
     homepage = "https://github.com/ralph-irving/squeezelite";
-    license = with licenses; [ gpl3 ] ++ optional dsdSupport bsd2;
+    license = with licenses; [ gpl3Plus ] ++ optional dsdSupport bsd2;
     maintainers = with maintainers; [ samdoshi ];
     platforms = platforms.linux;
   };
diff --git a/pkgs/applications/editors/sigil/default.nix b/pkgs/applications/editors/sigil/default.nix
index 0da5a2c2550..b93fbd6110f 100644
--- a/pkgs/applications/editors/sigil/default.nix
+++ b/pkgs/applications/editors/sigil/default.nix
@@ -6,13 +6,13 @@
 
 mkDerivation rec {
   pname = "sigil";
-  version = "1.9.1";
+  version = "1.9.2";
 
   src = fetchFromGitHub {
     repo = "Sigil";
     owner = "Sigil-Ebook";
     rev = version;
-    sha256 = "sha256-PsHliyJu61QFTFZUgDtxguu18GBVTOGMW6pPYjHhvG0=";
+    sha256 = "sha256-LfP3qUzoHuYSpkTz1queVGTWOP9v9kbgbgvvtiMK6Eo=";
   };
 
   pythonPath = with python3Packages; [ lxml ];
diff --git a/pkgs/applications/graphics/nsxiv/default.nix b/pkgs/applications/graphics/nsxiv/default.nix
index 8c414c37247..c1ebbd57c0d 100644
--- a/pkgs/applications/graphics/nsxiv/default.nix
+++ b/pkgs/applications/graphics/nsxiv/default.nix
@@ -11,13 +11,13 @@
 
 stdenv.mkDerivation rec {
   pname = "nsxiv";
-  version = "28";
+  version = "29";
 
   src = fetchFromGitHub {
     owner = "nsxiv";
     repo = pname;
     rev = "v${version}";
-    hash = "sha256-12RmEAzZdeanrRtnan96loXT7qSjIMjcWf296XmNE+A=";
+    hash = "sha256-JUF2cF6QeAXk6G76uMu3reaMgxp2RcqHDbamkNufwqE=";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/misc/systembus-notify/default.nix b/pkgs/applications/misc/systembus-notify/default.nix
index 6e5405ce988..770cd858401 100644
--- a/pkgs/applications/misc/systembus-notify/default.nix
+++ b/pkgs/applications/misc/systembus-notify/default.nix
@@ -1,5 +1,30 @@
-{ lib, stdenv, fetchFromGitHub, systemd }:
+{ lib
+, stdenv
+, fetchFromGitHub
+, formats
+, systemd
+}:
 
+let
+  ini = formats.ini { };
+
+  unit = ini.generate "systembus-notify.service" {
+    Unit = {
+      Description = "system bus notification daemon";
+    };
+
+    Service = {
+      Type = "exec";
+      ExecStart = "@out@/bin/systembus-notify";
+      PrivateTmp = true;
+      ProtectHome = true;
+      ProtectSystem = "strict";
+      Restart = "on-failure";
+      Slice = "background.slice";
+    };
+  };
+
+in
 stdenv.mkDerivation rec {
   pname = "systembus-notify";
   version = "1.1";
@@ -8,23 +33,32 @@ stdenv.mkDerivation rec {
     owner = "rfjakob";
     repo = "systembus-notify";
     rev = "v${version}";
-    sha256 = "1pdn45rfpwhrf20hs87qmk2j8sr7ab8161f81019wnypnb1q2fsv";
+    sha256 = "sha256-WzuBw7LXW54CCMgFE9BSJ2skxaz4IA2BcBny63Ihtt0=";
   };
 
   buildInputs = [ systemd ];
 
   installPhase = ''
     runHook preInstall
-    install -Dm755 systembus-notify -t $out/bin
-    install -Dm644 systembus-notify.desktop -t $out/etc/xdg/autostart
+
+    install -Dm555 -t $out/bin systembus-notify
+    install -Dm444 -t $out/share/systembus-notify systembus-notify.desktop
+
+    install -d $out/lib/systemd/user
+    substitute ${unit} $out/lib/systemd/user/${unit.name} \
+      --subst-var out
+
     runHook postInstall
   '';
 
+  # requires a running dbus instance
+  doCheck = false;
+
   meta = with lib; {
     description = "System bus notification daemon";
     homepage = "https://github.com/rfjakob/systembus-notify";
     license = licenses.mit;
+    maintainers = with maintainers; [ peterhoeg ];
     platforms = platforms.linux;
-    maintainers = with maintainers; [];
   };
 }
diff --git a/pkgs/applications/networking/cluster/cloudfoundry-cli/default.nix b/pkgs/applications/networking/cluster/cloudfoundry-cli/default.nix
index a4b49adb1e2..4667b130e8d 100644
--- a/pkgs/applications/networking/cluster/cloudfoundry-cli/default.nix
+++ b/pkgs/applications/networking/cluster/cloudfoundry-cli/default.nix
@@ -2,15 +2,15 @@
 
 buildGoModule rec {
   pname = "cloudfoundry-cli";
-  version = "8.0.0";
+  version = "8.3.0";
 
   src = fetchFromGitHub {
     owner = "cloudfoundry";
     repo = "cli";
     rev = "v${version}";
-    sha256 = "00cwnfylra0msbb423ad21if98s6smzccsyidqsl4r2mrlkhahwm";
+    sha256 = "sha256-tC9U0yvuMEwO4mzWyUC+v+/H0EzgwTu02waTQrx19Bs=";
   };
-  vendorSha256 = "0fcgyyd11xfhn8i11bqnaw3h51bj1y8s37b4d8wzv31dr8zswqsc";
+  vendorSha256 = "sha256-aXq92SI4cgJrmo67SEfg8YKPEpO2UW2fcYnKq9TmAQg=";
 
   subPackages = [ "." ];
 
diff --git a/pkgs/applications/networking/instant-messengers/qtox/default.nix b/pkgs/applications/networking/instant-messengers/qtox/default.nix
index e315938c571..3f6d374c399 100644
--- a/pkgs/applications/networking/instant-messengers/qtox/default.nix
+++ b/pkgs/applications/networking/instant-messengers/qtox/default.nix
@@ -28,13 +28,13 @@
 
 mkDerivation rec {
   pname = "qtox";
-  version = "1.17.5";
+  version = "1.17.6";
 
   src = fetchFromGitHub {
     owner = "qTox";
     repo = "qTox";
     rev = "v${version}";
-    sha256 = "sha256-H3qFEw/TkzOxEXtZs0k89wWMnhrOkF7VapUKtCUhGns=";
+    sha256 = "sha256-naKWoodSMw0AEtACvkASFmw9t0H0d2pcqOW79NNTYF0=";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/video/go-chromecast/default.nix b/pkgs/applications/video/go-chromecast/default.nix
index 0ffb5170dc2..99ddd7b24b6 100644
--- a/pkgs/applications/video/go-chromecast/default.nix
+++ b/pkgs/applications/video/go-chromecast/default.nix
@@ -2,16 +2,16 @@
 
 buildGoModule rec {
   pname = "go-chromecast";
-  version = "0.2.11";
+  version = "0.2.12";
 
   src = fetchFromGitHub {
     owner = "vishen";
     repo = pname;
     rev = "v${version}";
-    sha256 = "sha256-BCOyeXo3uoR4ry/nFbF+//U62/hHnPK+tbG+8Rv6Rv0=";
+    sha256 = "sha256-h8qWwMaEhXnj6ZSrKAXBVbrMR0je41EoOtFeN9XlCuk=";
   };
 
-  vendorSha256 = "sha256-idxElk4Sy7SE9G1OMRw8YH4o8orBa80qhBXPA+ar620=";
+  vendorSha256 = "sha256-PpMLHuJR6irp+QHhzguwGtBy30HM7DR0tNGiwB07M5E=";
 
   ldflags = [ "-s" "-w" "-X main.version=${version}" "-X main.commit=${src.rev}" "-X main.date=unknown" ];
 
diff --git a/pkgs/applications/virtualization/docker-slim/default.nix b/pkgs/applications/virtualization/docker-slim/default.nix
index cd8a1f5041a..3bc0f225de6 100644
--- a/pkgs/applications/virtualization/docker-slim/default.nix
+++ b/pkgs/applications/virtualization/docker-slim/default.nix
@@ -6,7 +6,7 @@
 
 buildGoPackage rec {
   pname = "docker-slim";
-  version = "1.37.3";
+  version = "1.37.4";
 
   goPackagePath = "github.com/docker-slim/docker-slim";
 
@@ -14,7 +14,7 @@ buildGoPackage rec {
     owner = "docker-slim";
     repo = "docker-slim";
     rev = version;
-    sha256 = "sha256-jzwQ3nrhLDiQXcVkPiXrRAmpLQOD8ILBnoCEUiEbxzw=";
+    sha256 = "sha256-iz1V+wcrJf0grOe81kwbXPBqnvXpHnh7IMDdugaUOH0=";
   };
 
   subPackages = [ "cmd/docker-slim" "cmd/docker-slim-sensor" ];
diff --git a/pkgs/applications/window-managers/berry/default.nix b/pkgs/applications/window-managers/berry/default.nix
index 82127c2733e..f6ba52013f6 100644
--- a/pkgs/applications/window-managers/berry/default.nix
+++ b/pkgs/applications/window-managers/berry/default.nix
@@ -55,6 +55,7 @@ stdenv.mkDerivation rec {
   ];
 
   meta = with lib; {
+    homepage = "https://berrywm.org/";
     description = "A healthy, bite-sized window manager";
     longDescription = ''
       berry is a healthy, bite-sized window manager written in C for unix
@@ -69,7 +70,6 @@ stdenv.mkDerivation rec {
       - Intuitively place new windows in unoccupied spaces.
       - Virtual desktops.
     '';
-    homepage = "https://berrywm.org/";
     license = licenses.mit;
     maintainers = [ maintainers.AndersonTorres ];
     platforms = platforms.linux;
diff --git a/pkgs/applications/window-managers/icewm/default.nix b/pkgs/applications/window-managers/icewm/default.nix
index deac4bed607..75cb96f27f4 100644
--- a/pkgs/applications/window-managers/icewm/default.nix
+++ b/pkgs/applications/window-managers/icewm/default.nix
@@ -40,13 +40,13 @@
 
 stdenv.mkDerivation rec {
   pname = "icewm";
-  version = "2.9.4";
+  version = "2.9.6";
 
   src = fetchFromGitHub {
-    owner  = "ice-wm";
+    owner = "ice-wm";
     repo = pname;
     rev = version;
-    hash = "sha256-ne2lqo9CAhGgC8dd9R03zhFXy9nPBQR0NcfAY0DeVj4=";
+    hash = "sha256-qC8gEVJ/cmsEbF8jMzv7zyvVcjlbXhgHU3ixe7RLcnA=";
   };
 
   nativeBuildInputs = [
@@ -55,6 +55,7 @@ stdenv.mkDerivation rec {
     perl
     pkg-config
   ];
+
   buildInputs = [
     expat
     fontconfig
@@ -108,11 +109,11 @@ stdenv.mkDerivation rec {
       system. Application windows can be managed by keyboard and mouse. Windows
       can be iconified to the taskbar, to the tray, to the desktop or be made
       hidden. They are controllable by a quick switch window (Alt+Tab) and in a
-      window list. A handful of configurable focus models are
-      menu-selectable. Setups with multiple monitors are supported by RandR and
-      Xinerama. IceWM is very configurable, themeable and well documented. It
-      includes an optional external background wallpaper manager with
-      transparency support, a simple session manager and a system tray.
+      window list. A handful of configurable focus models are menu-selectable.
+      Setups with multiple monitors are supported by RandR and Xinerama. IceWM
+      is very configurable, themeable and well documented. It includes an
+      optional external background wallpaper manager with transparency support,
+      a simple session manager and a system tray.
     '';
     license = licenses.lgpl2Only;
     maintainers = [ maintainers.AndersonTorres ];
diff --git a/pkgs/applications/window-managers/labwc/default.nix b/pkgs/applications/window-managers/labwc/default.nix
index 580fd29faa0..f58b71ef03a 100644
--- a/pkgs/applications/window-managers/labwc/default.nix
+++ b/pkgs/applications/window-managers/labwc/default.nix
@@ -21,20 +21,15 @@
 
 stdenv.mkDerivation rec {
   pname = "labwc";
-  version = "0.4.0";
+  version = "0.5.0";
 
   src = fetchFromGitHub {
     owner = "labwc";
     repo = pname;
     rev = version;
-    hash = "sha256-O9jVDR7UROt5u8inUsZjbzB3dQTosiLYqXkeOyGrbaM=";
+    hash = "sha256-G0EQuXSHftl4JLXKIro+tmhbApwAhlzcjPEL7DP6LHk=";
   };
 
-  patches = [
-    # Required to fix the build with wlroots 0.15.1:
-    ./relax-the-version-constraint-for-wlroots.patch
-  ];
-
   nativeBuildInputs = [
     meson
     ninja
@@ -64,6 +59,6 @@ stdenv.mkDerivation rec {
     description = "A Wayland stacking compositor, similar to Openbox";
     license = licenses.gpl2Plus;
     maintainers = with maintainers; [ AndersonTorres ];
-    platforms = platforms.unix;
+    inherit (wayland.meta) platforms;
   };
 }
diff --git a/pkgs/applications/window-managers/labwc/relax-the-version-constraint-for-wlroots.patch b/pkgs/applications/window-managers/labwc/relax-the-version-constraint-for-wlroots.patch
deleted file mode 100644
index 9a790f28516..00000000000
--- a/pkgs/applications/window-managers/labwc/relax-the-version-constraint-for-wlroots.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 21d8bfcf7899f5ec50b29f523ace4c19cbfbe919 Mon Sep 17 00:00:00 2001
-From: Michael Weiss <dev.primeos@gmail.com>
-Date: Fri, 4 Feb 2022 21:17:05 +0100
-Subject: [PATCH] build: Relax the version constraint for wlroots to accept
- patch releases
-
-Patch releases only contain backwards compatible changes (mainly bug
-fixes) so we want to allow them. This fixes the build with the recently
-released wlroots 0.15.1 and uses the same version constraints as other
-projects that depend on wlroots (e.g., Sway).
----
- meson.build | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/meson.build b/meson.build
-index f950b8e..1905dda 100644
---- a/meson.build
-+++ b/meson.build
-@@ -37,7 +37,7 @@ if git.found()
- endif
- add_project_arguments('-DLABWC_VERSION=@0@'.format(version), language: 'c')
-
--wlroots_version = ['=0.15.0']
-+wlroots_version = ['>=0.15.0', '<0.16.0']
- wlroots_proj = subproject(
-   'wlroots',
-   default_options: ['default_library=static', 'examples=false'],
---
-2.34.1
diff --git a/pkgs/development/libraries/cimg/default.nix b/pkgs/development/libraries/cimg/default.nix
index 47e9ffa925a..4a482c9da45 100644
--- a/pkgs/development/libraries/cimg/default.nix
+++ b/pkgs/development/libraries/cimg/default.nix
@@ -5,13 +5,13 @@
 
 stdenv.mkDerivation rec {
   pname = "cimg";
-  version = "3.0.0";
+  version = "3.0.2";
 
   src = fetchFromGitHub {
     owner = "dtschump";
     repo = "CImg";
     rev = "v.${version}";
-    hash = "sha256-dC4VuWTz0uyFxLjBQ+2ggndHaCErcoI7tJMfkqbWmeg=";
+    hash = "sha256-OWpztnyVXCg+uoAb6e/2eUK2ebBalDlz6Qcjf17IeMk=";
   };
 
   outputs = [ "out" "doc" ];
diff --git a/pkgs/development/libraries/elpa/default.nix b/pkgs/development/libraries/elpa/default.nix
index 76152996a1d..2a71b82af3c 100644
--- a/pkgs/development/libraries/elpa/default.nix
+++ b/pkgs/development/libraries/elpa/default.nix
@@ -18,13 +18,13 @@ assert blas.isILP64 == scalapack.isILP64;
 
 stdenv.mkDerivation rec {
   pname = "elpa";
-  version = "2021.11.001";
+  version = "2021.11.002";
 
   passthru = { inherit (blas) isILP64; };
 
   src = fetchurl {
     url = "https://elpa.mpcdf.mpg.de/software/tarball-archive/Releases/${version}/elpa-${version}.tar.gz";
-    sha256 = "0bw0nwzwvjfmijfwznmrghypd3q237a3h5g5fcdncilrqnk1sdpv";
+    sha256 = "sha256-V28cru14g7gTlmQP2g9QQYOGbPbL1Lxx0Tg7oiCPH5c=";
   };
 
   patches = [
diff --git a/pkgs/development/libraries/zchunk/default.nix b/pkgs/development/libraries/zchunk/default.nix
index c2ddda7a6c5..c639eb7b30e 100644
--- a/pkgs/development/libraries/zchunk/default.nix
+++ b/pkgs/development/libraries/zchunk/default.nix
@@ -11,13 +11,13 @@
 
 stdenv.mkDerivation rec {
   pname = "zchunk";
-  version = "1.1.16";
+  version = "1.2.0";
 
   src = fetchFromGitHub {
     owner = "zchunk";
     repo = pname;
     rev = version;
-    hash = "sha256-+8FkivLTZXdu0+1wu+7T98y6rQzIHbG9l15Abrbln1o=";
+    hash = "sha256-7H1WF5VkpA65xCdEa0Sw4r4jj+kGhDVCMr5AeE+3Ii4=";
   };
 
   nativeBuildInputs = [
@@ -47,5 +47,6 @@ stdenv.mkDerivation rec {
     license = licenses.bsd2;
     maintainers = with maintainers; [ AndersonTorres ];
     platforms = platforms.unix;
+    broken = stdenv.isDarwin; # does not find argp-standalone
   };
 }
diff --git a/pkgs/development/python-modules/allure-behave/default.nix b/pkgs/development/python-modules/allure-behave/default.nix
new file mode 100644
index 00000000000..e7cd81d5b5d
--- /dev/null
+++ b/pkgs/development/python-modules/allure-behave/default.nix
@@ -0,0 +1,38 @@
+{ lib
+, fetchPypi
+, buildPythonPackage
+, pythonOlder
+, behave
+, allure-python-commons
+, setuptools-scm
+}:
+
+buildPythonPackage rec {
+  pname = "allure-behave";
+  version = "2.9.45";
+
+  disabled = pythonOlder "3.4";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "sha256-aK0SgQIXpuUoSTz8jg5IPKQM2Xvk2EfkSGigsy/GFNo=";
+  };
+
+  nativeBuildInputs = [
+    setuptools-scm
+  ];
+
+  pythonImportsCheck = [ "allure_behave" ];
+
+  propagatedBuildInputs = [
+    allure-python-commons
+    behave
+  ];
+
+  meta = with lib; {
+    description = "Allure behave integration.";
+    homepage = "https://github.com/allure-framework/allure-python";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ happysalada ];
+  };
+}
diff --git a/pkgs/development/python-modules/wled/default.nix b/pkgs/development/python-modules/wled/default.nix
index 3b88afa7e65..3bd0d5b55b9 100644
--- a/pkgs/development/python-modules/wled/default.nix
+++ b/pkgs/development/python-modules/wled/default.nix
@@ -15,7 +15,7 @@
 
 buildPythonPackage rec {
   pname = "wled";
-  version = "0.13.0";
+  version = "0.13.1";
   format = "pyproject";
 
   disabled = pythonOlder "3.8";
@@ -24,7 +24,7 @@ buildPythonPackage rec {
     owner = "frenck";
     repo = "python-wled";
     rev = "v${version}";
-    sha256 = "sha256-n+TIzlnyPeSywTQr7wlGNezsbQ2+S/WYt1H95+Id2Rw=";
+    sha256 = "sha256-QQPrAfk+BX8mjqn9ISim9hLEZR2nbgxbkwCv+91yeRY=";
   };
 
   nativeBuildInputs = [
diff --git a/pkgs/development/tools/analysis/actionlint/default.nix b/pkgs/development/tools/analysis/actionlint/default.nix
index 602f6815fb9..68112b01cfb 100644
--- a/pkgs/development/tools/analysis/actionlint/default.nix
+++ b/pkgs/development/tools/analysis/actionlint/default.nix
@@ -2,7 +2,7 @@
 
 buildGoModule rec {
   pname = "actionlint";
-  version = "1.6.9";
+  version = "1.6.10";
 
   subPackages = [ "cmd/actionlint" ];
 
@@ -10,10 +10,10 @@ buildGoModule rec {
     owner = "rhysd";
     repo = "actionlint";
     rev = "v${version}";
-    sha256 = "sha256-UDa/qFtRTED6d+lPbjNknX9qFZ3QZ9jiD0ByvLsGARk=";
+    sha256 = "sha256-RFsNJiCeSAeEWOUnfBpeIZKoS2mlXazYMQd1M6yFLGU=";
   };
 
-  vendorSha256 = "sha256-0tytdTZxnWYl8AxaquF0ArY3dy51j8H2kzw69qcSHzk=";
+  vendorSha256 = "sha256-CxNER8aQftMG14M+x6bPwcXgUZRkUDYZtFg1cPxxg+I=";
 
   nativeBuildInputs = [ ronn installShellFiles ];
 
diff --git a/pkgs/development/tools/analysis/flow/default.nix b/pkgs/development/tools/analysis/flow/default.nix
index 36c85285704..6ef9806bf37 100644
--- a/pkgs/development/tools/analysis/flow/default.nix
+++ b/pkgs/development/tools/analysis/flow/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "flow";
-  version = "0.172.0";
+  version = "0.173.0";
 
   src = fetchFromGitHub {
     owner = "facebook";
     repo = "flow";
     rev = "v${version}";
-    sha256 = "sha256-N3mP1dhul7Ljn278CJmge4IrVllQJsc73A3/7mTSU70=";
+    sha256 = "sha256-F0t85/sq9p+eNEf2XAGxw+ZWeRgUbkhrKFdGASijuAs=";
   };
 
   installPhase = ''
diff --git a/pkgs/development/tools/buildkit/default.nix b/pkgs/development/tools/buildkit/default.nix
index b9ae4e4dd88..df644935cf1 100644
--- a/pkgs/development/tools/buildkit/default.nix
+++ b/pkgs/development/tools/buildkit/default.nix
@@ -2,13 +2,13 @@
 
 buildGoModule rec {
   pname = "buildkit";
-  version = "0.9.3";
+  version = "0.10.0";
 
   src = fetchFromGitHub {
     owner = "moby";
     repo = "buildkit";
     rev = "v${version}";
-    sha256 = "sha256-xjuHMjJjA4sx2Hrr6tPpvKtSmhGZ3AZka733DLxmYfk=";
+    sha256 = "sha256-Pdnu0zG1LteAob0YUuG/XDh2pfBj5UO2GrkWFlMZeGY=";
   };
 
   vendorSha256 = null;
diff --git a/pkgs/development/tools/cloud-nuke/default.nix b/pkgs/development/tools/cloud-nuke/default.nix
index 4fa198f32c0..f1f44a57775 100644
--- a/pkgs/development/tools/cloud-nuke/default.nix
+++ b/pkgs/development/tools/cloud-nuke/default.nix
@@ -2,13 +2,13 @@
 
 buildGoModule rec {
   pname = "cloud-nuke";
-  version = "0.10.0";
+  version = "0.11.0";
 
   src = fetchFromGitHub {
     owner = "gruntwork-io";
     repo = pname;
     rev = "v${version}";
-    sha256 = "sha256-y1YpPYTejeZjz4nJmyAPT8rYaEguaJpBfAAfF38dpA4=";
+    sha256 = "sha256-G1RQEKb3vK8lg0jakCtIMgQXmWqfsq0QWHwU8TAbBbE=";
   };
 
   vendorSha256 = "sha256-McCbogZvgm9pnVjay9O2CxAh+653JnDMcU4CHD0PTPI=";
diff --git a/pkgs/development/tools/ocaml/dune/3.nix b/pkgs/development/tools/ocaml/dune/3.nix
index 59ea9c43512..f6f45944a81 100644
--- a/pkgs/development/tools/ocaml/dune/3.nix
+++ b/pkgs/development/tools/ocaml/dune/3.nix
@@ -6,11 +6,11 @@ else
 
 stdenv.mkDerivation rec {
   pname = "dune";
-  version = "3.0.2";
+  version = "3.0.3";
 
   src = fetchurl {
     url = "https://github.com/ocaml/dune/releases/download/${version}/fiber-${version}.tbz";
-    sha256 = "sha256-o108qIeWMOX0VU/wWdc5bg/UDCT2CCcw/Xx3nFiDbes=";
+    sha256 = "sha256-1QRJmhZY8Nmcrvv/1zhvLjHUbOynMWcVf+RobEHlcy8=";
   };
 
   nativeBuildInputs = [ ocaml findlib ];
diff --git a/pkgs/development/tools/wllvm/default.nix b/pkgs/development/tools/wllvm/default.nix
index 85dbc4f731a..0234c936dc1 100644
--- a/pkgs/development/tools/wllvm/default.nix
+++ b/pkgs/development/tools/wllvm/default.nix
@@ -1,13 +1,12 @@
 { lib, python3Packages }:
 
 python3Packages.buildPythonApplication rec {
-  version = "1.2.8";
+  version = "1.3.1";
   pname = "wllvm";
-  name = "${pname}-${version}";
 
   src = python3Packages.fetchPypi {
     inherit pname version;
-    sha256 = "1d88fzg4ba4r3hwrinnv6agiyj3xxdy4yryb8wz2ml51nc6bi591";
+    sha256 = "sha256-PgV6V18FyezIZpqMQEbyv98MaVM7h7T7/Kvg3yMMwzE=";
   };
 
   meta = with lib; {
diff --git a/pkgs/servers/sql/postgresql/ext/rum.nix b/pkgs/servers/sql/postgresql/ext/rum.nix
new file mode 100644
index 00000000000..ce7dcbd7a48
--- /dev/null
+++ b/pkgs/servers/sql/postgresql/ext/rum.nix
@@ -0,0 +1,31 @@
+{ lib, stdenv, fetchFromGitHub, postgresql }:
+
+stdenv.mkDerivation rec {
+  pname = "rum";
+  version = "1.3.9";
+
+  src = fetchFromGitHub {
+    owner = "postgrespro";
+    repo = "rum";
+    rev = version;
+    sha256 = "sha256-xdCj9hzBg7VtAIHpIFpeeaK6U4aRrCsoQrPKdABSl+Y=";
+  };
+
+  buildInputs = [ postgresql ];
+
+  makeFlags = [ "USE_PGXS=1" ];
+
+  installPhase = ''
+    install -D -t $out/lib *.so
+    install -D -t $out/share/postgresql/extension *.control
+    install -D -t $out/share/postgresql/extension *.sql
+  '';
+
+  meta = with lib; {
+    description = "Full text search index method for PostgreSQL";
+    homepage = "https://github.com/postgrespro/rum";
+    license = licenses.postgresql;
+    platforms = postgresql.meta.platforms;
+    maintainers = with maintainers; [ DeeUnderscore ];
+  };
+}
diff --git a/pkgs/servers/sql/postgresql/packages.nix b/pkgs/servers/sql/postgresql/packages.nix
index f3df8a99ca2..fec106f32ac 100644
--- a/pkgs/servers/sql/postgresql/packages.nix
+++ b/pkgs/servers/sql/postgresql/packages.nix
@@ -61,4 +61,6 @@ self: super: {
     pg_safeupdate = super.callPackage ./ext/pg_safeupdate.nix { };
 
     repmgr = super.callPackage ./ext/repmgr.nix { };
+
+    rum = super.callPackage ./ext/rum.nix { };
 }
diff --git a/pkgs/shells/tcsh/default.nix b/pkgs/shells/tcsh/default.nix
index 1befd289757..2c8548fb1fd 100644
--- a/pkgs/shells/tcsh/default.nix
+++ b/pkgs/shells/tcsh/default.nix
@@ -7,20 +7,21 @@
 
 stdenv.mkDerivation rec {
   pname = "tcsh";
-  version = "6.23.02";
+  version = "6.24.00";
 
   src = fetchurl {
     urls = [
-      "https://astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
       "https://astron.com/pub/tcsh/${pname}-${version}.tar.gz"
-      "http://ftp.funet.fi/pub/mirrors/ftp.astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
+      "https://astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
       "http://ftp.funet.fi/pub/mirrors/ftp.astron.com/pub/tcsh/${pname}-${version}.tar.gz"
-      "ftp://ftp.funet.fi/pub/unix/shells/tcsh/old/${pname}-${version}.tar.gz"
-      "ftp://ftp.funet.fi/pub/unix/shells/tcsh/${pname}-${version}.tar.gz"
-      "ftp://ftp.astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
+      "http://ftp.funet.fi/pub/mirrors/ftp.astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
+
       "ftp://ftp.astron.com/pub/tcsh/${pname}-${version}.tar.gz"
+      "ftp://ftp.astron.com/pub/tcsh/old/${pname}-${version}.tar.gz"
+      "ftp://ftp.funet.fi/pub/unix/shells/tcsh/${pname}-${version}.tar.gz"
+      "ftp://ftp.funet.fi/pub/unix/shells/tcsh/old/${pname}-${version}.tar.gz"
     ];
-    hash = "sha256-wD+AQFE2cxswkdpzWoHN2EgAhRAySrMl8jWv9wnkRus=";
+    hash = "sha256-YL4sUEvY8fpuQksZVkldfnztUqKslNtf0n9La/yPdPA=";
   };
 
   buildInputs = [
diff --git a/pkgs/tools/misc/nncp/default.nix b/pkgs/tools/misc/nncp/default.nix
index 3fda2a6cdad..a3b010b13fb 100644
--- a/pkgs/tools/misc/nncp/default.nix
+++ b/pkgs/tools/misc/nncp/default.nix
@@ -3,12 +3,12 @@
 
 stdenv.mkDerivation rec {
   pname = "nncp";
-  version = "8.7.1";
+  version = "8.7.2";
   outputs = [ "out" "doc" "info" ];
 
   src = fetchurl {
     url = "http://www.nncpgo.org/download/${pname}-${version}.tar.xz";
-    hash = "sha256-zrTRl69ajZ6Tt0nVwPULU+Z0ajGK9Hs2S/XLMj1sTr0=";
+    hash = "sha256-oO7JsPMwWd4z8TCEWZgF0PShyMN56SW6z+jclNHdwj0=";
   };
 
   nativeBuildInputs = [ go redo-apenwarr ];
diff --git a/pkgs/tools/networking/minio-client/default.nix b/pkgs/tools/networking/minio-client/default.nix
index 4fbdec621b4..eb73a33e01f 100644
--- a/pkgs/tools/networking/minio-client/default.nix
+++ b/pkgs/tools/networking/minio-client/default.nix
@@ -2,16 +2,16 @@
 
 buildGoModule rec {
   pname = "minio-client";
-  version = "2022-03-03T21-12-24Z";
+  version = "2022-03-09T02-08-36Z";
 
   src = fetchFromGitHub {
     owner = "minio";
     repo = "mc";
     rev = "RELEASE.${version}";
-    sha256 = "sha256-z+t8aMyGlqXcooCzJgn0xxOhuS+p3/qMTBJByDJPd40=";
+    sha256 = "sha256-OaV0Xb3nNeZJLayGperQah0JQ7BlGFPWa1//Kt5+EiU=";
   };
 
-  vendorSha256 = "sha256-mk0ga3o6LeZ4uwV3vlP6qyFXLiORwNQLhXoCxSmvXsU=";
+  vendorSha256 = "sha256-Wdw9mZ3UupoJ4yDwS4f3mOmCn+7TvHmx4aRu+96pHM4=";
 
   subPackages = [ "." ];
 
diff --git a/pkgs/tools/networking/ytcc/default.nix b/pkgs/tools/networking/ytcc/default.nix
index 46b6e649b5c..028c50a352c 100644
--- a/pkgs/tools/networking/ytcc/default.nix
+++ b/pkgs/tools/networking/ytcc/default.nix
@@ -2,13 +2,13 @@
 
 python3Packages.buildPythonApplication rec {
   pname = "ytcc";
-  version = "2.5.4";
+  version = "2.5.5";
 
   src = fetchFromGitHub {
     owner = "woefe";
     repo = "ytcc";
     rev = "v${version}";
-    sha256 = "sha256-nYHfmksZnIZGMSSFDhW7ajvv1F5h3aJo8IXw6yYOEw0=";
+    sha256 = "sha256-DjyVcjU2dVku5ademm6DygMnzWHB7iMqPfU56BBjAwU=";
   };
 
   nativeBuildInputs = [ gettext installShellFiles ];
diff --git a/pkgs/tools/security/sops/default.nix b/pkgs/tools/security/sops/default.nix
index 1cf89143925..9752d78a183 100644
--- a/pkgs/tools/security/sops/default.nix
+++ b/pkgs/tools/security/sops/default.nix
@@ -2,16 +2,16 @@
 
 buildGoModule rec {
   pname = "sops";
-  version = "3.7.1";
+  version = "3.7.2";
 
   src = fetchFromGitHub {
     rev = "v${version}";
     owner = "mozilla";
     repo = pname;
-    sha256 = "0z3jcyl245yjszzjf2h6l1dwa092vxzvfmnivmwi6jvpsdcv33h1";
+    sha256 = "sha256-NMuYMvaBSxKHvpqFkMfnMDvcXxTstqzracuSTT1VB1A=";
   };
 
-  vendorSha256 = "1mnwgsbpi56ql0lbpn7dkaps96x9b1lmhlk5cd6d40da7xj616n7";
+  vendorSha256 = "sha256-00/7O9EcGojUExJPtYWndb16VqrNby/5GsVs8Ak/Isc=";
 
   doCheck = false;
 
diff --git a/pkgs/tools/security/swtpm/default.nix b/pkgs/tools/security/swtpm/default.nix
index 648165d8262..39128084352 100644
--- a/pkgs/tools/security/swtpm/default.nix
+++ b/pkgs/tools/security/swtpm/default.nix
@@ -16,35 +16,40 @@
 
 stdenv.mkDerivation rec {
   pname = "swtpm";
-  version = "0.7.1";
+  version = "0.7.2";
 
   src = fetchFromGitHub {
     owner = "stefanberger";
     repo = "swtpm";
     rev = "v${version}";
-    sha256 = "sha256-LJQF8PlRkhCJ8rjZzDetg1BFuTb7GBJ8lW6u5hO134k=";
+    sha256 = "sha256-qeyPCJTNnwuaCosHzqnrQc0JNznGBfDTLsuDmuKREjU=";
   };
 
   nativeBuildInputs = [
     pkg-config unixtools.netstat expect socat
     perl # for pod2man
+    python3
     autoreconfHook
   ];
 
   checkInputs = [
-    python3 which
+    which
   ];
 
   buildInputs = [
     libtpms
-    openssl libtasn1 libseccomp
-    fuse glib json-glib
+    openssl libtasn1
+    glib json-glib
     gnutls
+  ] ++ lib.optionals stdenv.isLinux [
+    fuse
+    libseccomp
   ];
 
   configureFlags = [
-    "--with-cuse"
     "--localstatedir=/var"
+  ] ++ lib.optionals stdenv.isLinux [
+    "--with-cuse"
   ];
 
   postPatch = ''
@@ -56,9 +61,31 @@ stdenv.mkDerivation rec {
 
     # Use the correct path to the certtool binary
     # instead of relying on it being in the environment
-    substituteInPlace src/swtpm_localca/swtpm_localca.c --replace \
+    substituteInPlace src/swtpm_localca/swtpm_localca.c \
+      --replace \
+        '# define CERTTOOL_NAME "gnutls-certtool"' \
+        '# define CERTTOOL_NAME "${gnutls}/bin/certtool"' \
+      --replace \
         '# define CERTTOOL_NAME "certtool"' \
         '# define CERTTOOL_NAME "${gnutls}/bin/certtool"'
+
+    substituteInPlace tests/common --replace \
+        'CERTTOOL=gnutls-certtool;;' \
+        'CERTTOOL=certtool;;'
+
+    # Fix error on macOS:
+    # stat: invalid option -- '%'
+    # This is caused by the stat program not being the BSD version,
+    # as is expected by the test
+    substituteInPlace tests/common --replace \
+        'if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then' \
+        'if [[ "$(uname -s)" =~ (Linux|Darwin|CYGWIN_NT-) ]]; then'
+
+    # Otherwise certtool seems to pick up the system language on macOS,
+    # which might cause a test to fail
+    substituteInPlace tests/test_swtpm_setup_create_cert --replace \
+        '$CERTTOOL' \
+        'LC_ALL=C.UTF-8 $CERTTOOL'
   '';
 
   doCheck = true;
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index ecd3851d242..7e6484a1c9b 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -29073,7 +29073,9 @@ with pkgs;
 
   psst = callPackage ../applications/audio/psst { };
 
-  squeezelite = callPackage ../applications/audio/squeezelite { };
+  squeezelite = callPackage ../applications/audio/squeezelite { audioBackend = "alsa"; };
+
+  squeezelite-pulse = callPackage ../applications/audio/squeezelite { audioBackend = "pulse"; };
 
   ltunify = callPackage ../tools/misc/ltunify { };
 
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index 9f13c501b7d..a8e942dd1e0 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -456,6 +456,8 @@ in {
 
   allpairspy = callPackage ../development/python-modules/allpairspy { };
 
+  allure-behave = callPackage ../development/python-modules/allure-behave { };
+
   allure-python-commons = callPackage ../development/python-modules/allure-python-commons { };
 
   allure-python-commons-test = callPackage ../development/python-modules/allure-python-commons-test { };