diff --git a/nixos/lib/systemd-lib.nix b/nixos/lib/systemd-lib.nix index 39961f0f25d5..fdf5525c5385 100644 --- a/nixos/lib/systemd-lib.nix +++ b/nixos/lib/systemd-lib.nix @@ -579,6 +579,8 @@ in rec { '' else "") + optionalString (def ? stopIfChanged && !def.stopIfChanged) '' X-StopIfChanged=false + '' + optionalString (def ? notSocketActivated && def.notSocketActivated) '' + X-NotSocketActivated=true '' + attrsToSection def.serviceConfig); }; diff --git a/nixos/lib/systemd-unit-options.nix b/nixos/lib/systemd-unit-options.nix index b02a11ef33a6..44fef28ec11e 100644 --- a/nixos/lib/systemd-unit-options.nix +++ b/nixos/lib/systemd-unit-options.nix @@ -535,6 +535,18 @@ in rec { ''; }; + notSocketActivated = mkOption { + type = types.bool; + default = false; + description = '' + If set, a changed unit is never assumed to be + socket-activated on configuration activation, even if + it might have associated socket units. Instead, the unit + will be restarted (or stopped/started) as if it had no + associated sockets. + ''; + }; + startAt = mkOption { type = with types; either str (listOf str); default = []; diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index a532f629efd0..1ea001fcc26a 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -433,8 +433,9 @@ in fi ''; - systemd.services.systemd-udevd = - { restartTriggers = [ config.environment.etc."udev/rules.d".source ]; + systemd.services.systemd-udevd = { + restartTriggers = [ config.environment.etc."udev/rules.d".source ]; + notSocketActivated = true; }; }; diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index 130d6098b1e2..9fd5f8fcfa69 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -2883,6 +2883,7 @@ let config.environment.etc."systemd/networkd.conf".source ]; aliases = [ "dbus-org.freedesktop.network1.service" ]; + notSocketActivated = true; }; networking.iproute2 = mkIf (cfg.config.addRouteTablesToIPRoute2 && cfg.config.routeTables != { }) { diff --git a/pkgs/by-name/sw/switch-to-configuration-ng/src/src/main.rs b/pkgs/by-name/sw/switch-to-configuration-ng/src/src/main.rs index 61932cb55591..811945bdad4a 100644 --- a/pkgs/by-name/sw/switch-to-configuration-ng/src/src/main.rs +++ b/pkgs/by-name/sw/switch-to-configuration-ng/src/src/main.rs @@ -68,6 +68,8 @@ const RELOAD_LIST_FILE: &str = "/run/nixos/reload-list"; // `stopIfChanged = true` is ignored, switch-to-configuration will handle `restartIfChanged = // false` and `reloadIfChanged = true`. This is the same as specifying a restart trigger in the // NixOS module. +// In addition, switch-to-configuration will handle notSocketActivated=true to disable treatment +// of units as "socket-activated" even though they might have any associated sockets. // // The reload file asks this program to reload a unit. This is the same as specifying a reload // trigger in the NixOS module and can be ignored if the unit is restarted in this activation. @@ -583,6 +585,8 @@ fn handle_modified_unit( } else { // If this unit is socket-activated, then stop the socket unit(s) as well, and // restart the socket(s) instead of the service. + // We count as "socket-activated" any unit that doesn't declare itself not so + // via X-NotSocketActivated, that has any associated .socket units. let mut socket_activated = false; if unit.ends_with(".service") { let mut sockets = if let Some(Some(Some(sockets))) = new_unit_info.map(|info| { @@ -634,6 +638,12 @@ fn handle_modified_unit( } } } + if parse_systemd_bool(new_unit_info, "Service", "X-NotSocketActivated", false) { + // If the unit explicitly opts out of socket + // activation, restart it as if it weren't (but do + // restart its sockets, that's fine): + socket_activated = false; + } // If the unit is not socket-activated, record that this unit needs to be started // below. We write this to a file to ensure that the service gets restarted if