From 3a8b38d4ee7cb9ecc9221af00f6eb4a0c43b8a19 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 22:29:28 +0200 Subject: [PATCH 01/17] nixos/polkit: modernize --- nixos/modules/security/polkit.nix | 90 ++++++++++++++++++++----------- nixos/tests/rtkit.nix | 2 +- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/nixos/modules/security/polkit.nix b/nixos/modules/security/polkit.nix index c2bbe706529f..cc62f22df6bd 100644 --- a/nixos/modules/security/polkit.nix +++ b/nixos/modules/security/polkit.nix @@ -6,27 +6,51 @@ }: let - cfg = config.security.polkit; + inherit (lib) + mkEnableOption + mkOption + mkIf + mkPackageOption + mkRemovedOptionModule + types + ; + cfg = config.security.polkit; in { + imports = [ + (mkRemovedOptionModule [ "security" "polkit" "debug" ] "Use security.polkit.extraArgs instead") + ]; - options = { + options.security.polkit = { + enable = mkEnableOption "polkit"; - security.polkit.enable = lib.mkEnableOption "polkit"; - security.polkit.package = lib.mkPackageOption pkgs "polkit" { }; + package = mkPackageOption pkgs "polkit" { }; - security.polkit.debug = lib.mkEnableOption "debug logs from polkit. This is required in order to see log messages from rule definitions"; + extraArgs = mkOption { + type = types.listOf types.str; + default = [ + "--no-debug" + "--log-level=notice" + ]; + description = '' + List of arguments to pass to the polkitd executable. - security.polkit.extraConfig = lib.mkOption { - type = lib.types.lines; + ::: {.note} + To see debug logs you need to negate the default `--no-debug` setting. + ::: + ''; + }; + + extraConfig = mkOption { + type = types.lines; default = ""; example = '' /* Log authorization checks. */ polkit.addRule(function(action, subject) { - // Make sure to set { security.polkit.debug = true; } in configuration.nix + // Make sure to negate --no-debug in services.polkit.extraArgs: { security.polkit.extraArgs = [ "--log-level=notice" ]; } polkit.log("user " + subject.user + " is attempting action " + action.id + " from PID " + subject.pid); }); @@ -41,8 +65,8 @@ in ''; }; - security.polkit.adminIdentities = lib.mkOption { - type = lib.types.listOf lib.types.str; + adminIdentities = mkOption { + type = with types; listOf str; default = [ "unix-group:wheel" ]; example = [ "unix-user:alice" @@ -58,25 +82,35 @@ in }; - config = lib.mkIf cfg.enable { + config = mkIf cfg.enable { environment.systemPackages = [ cfg.package.bin cfg.package.out ]; + services.dbus.packages = [ cfg.package.out ]; + systemd.packages = [ cfg.package.out ]; - systemd.services.polkit.serviceConfig.ExecStart = [ - "" - "${cfg.package.out}/lib/polkit-1/polkitd ${lib.optionalString (!cfg.debug) "--no-debug"}" - ]; - - systemd.services.polkit.restartTriggers = [ config.system.path ]; - systemd.services.polkit.reloadTriggers = [ - config.environment.etc."polkit-1/rules.d/10-nixos.rules".source - ]; - systemd.services.polkit.stopIfChanged = false; + systemd.services.polkit = { + restartTriggers = [ config.system.path ]; + reloadTriggers = [ + config.environment.etc."polkit-1/rules.d/10-nixos.rules".source + ]; + stopIfChanged = false; + serviceConfig.ExecStart = [ + # nuke default ExecStart + "" + # provide our own instead + (toString ( + [ + "${lib.getLib cfg.package}/lib/polkit-1/polkitd" + ] + ++ cfg.extraArgs + )) + ]; + }; systemd.sockets."polkit-agent-helper".wantedBy = [ "sockets.target" ]; @@ -89,7 +123,7 @@ in # The upstream unit uses PrivateDevices=yes and ProtectHome=yes, # which prevents PAM modules from accessing hardware (e.g. FIDO # tokens via /dev/hidraw*) or reading key files from home directories. - (lib.mkIf config.security.pam.u2f.enable { + (mkIf config.security.pam.u2f.enable { # Override upstream PrivateDevices=yes to allow access to /dev/hidraw* PrivateDevices = false; DeviceAllow = [ @@ -100,7 +134,7 @@ in # ~/.config/Yubico/u2f_keys (the default key file location) ProtectHome = "read-only"; }) - (lib.mkIf config.security.pam.zfs.enable { + (mkIf config.security.pam.zfs.enable { PrivateDevices = false; DeviceAllow = [ "/dev/zfs rw" @@ -120,23 +154,15 @@ in ${cfg.extraConfig} ''; # TODO: validation on compilation (at least against typos) - services.dbus.packages = [ cfg.package.out ]; - security.pam.services.polkit-1 = { }; security.wrappers.pkexec = { setuid = true; owner = "root"; group = "root"; - source = "${cfg.package.bin}/bin/pkexec"; + source = lib.getExe' cfg.package "pkexec"; }; - systemd.tmpfiles.rules = [ - # Probably no more needed, clean up - "R /var/lib/polkit-1" - "R /var/lib/PolicyKit" - ]; - users.users.polkituser = { description = "PolKit daemon"; uid = config.ids.uids.polkituser; diff --git a/nixos/tests/rtkit.nix b/nixos/tests/rtkit.nix index 74bf69e02a83..295fd36a1391 100644 --- a/nixos/tests/rtkit.nix +++ b/nixos/tests/rtkit.nix @@ -55,7 +55,7 @@ # Provide a little logging of polkit checks - otherwise it's # impossible to know what's going on. - security.polkit.debug = true; + security.polkit.extraArgs = [ "--log-level=notice" ]; security.polkit.extraConfig = '' polkit.addRule(function(action, subject) { const ns = "org.freedesktop.RealtimeKit1."; From e88efa73069adf9abd9b0e78d10a1367560728d2 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 22:29:49 +0200 Subject: [PATCH 02/17] nixos/polkit: make pkexec opt-in --- nixos/doc/manual/release-notes/rl-2611.section.md | 2 ++ nixos/modules/security/polkit.nix | 2 ++ 2 files changed, 4 insertions(+) diff --git a/nixos/doc/manual/release-notes/rl-2611.section.md b/nixos/doc/manual/release-notes/rl-2611.section.md index 3697b3bb2e3e..3a00b506896f 100644 --- a/nixos/doc/manual/release-notes/rl-2611.section.md +++ b/nixos/doc/manual/release-notes/rl-2611.section.md @@ -28,6 +28,8 @@ - Python 2 has been removed from the top-level package set, as it is long past end-of-life. The `python2`, `python27`, `python2Full`, `python27Full`, `python2Packages`, and `python27Packages` attributes, along with the legacy `python`, `pythonFull`, and `pythonPackages` aliases, now throw an error directing you to `python3`. The `isPy2` and `isPy27` package flags have been removed accordingly. The only remaining Python 2 interpreter is vendored inside the `resholve` package for its `oil` dependency and is not exposed for general use. +- `security.polkit.enablePkexecWrapper` has been introduced, making the `pkexec` setuid wrapper opt-in. + - `systemd.user.extraConfig` has been removed in favor of the structured [](#opt-systemd.user.settings.Manager) option. Use `systemd.user.settings.Manager` to set any `systemd-user.conf(5)` option directly. For example, replace `systemd.user.extraConfig = "DefaultTimeoutStartSec=60";` with `systemd.user.settings.Manager.DefaultTimeoutStartSec = 60;`. - `services.timesyncd.extraConfig` has been removed in favor of the structured [](#opt-services.timesyncd.settings.Time) option. Use `services.timesyncd.settings.Time` to set any `timesyncd.conf(5)` option directly. For example, replace `services.timesyncd.extraConfig = "PollIntervalMaxSec=180";` with `services.timesyncd.settings.Time.PollIntervalMaxSec = 180;`. diff --git a/nixos/modules/security/polkit.nix b/nixos/modules/security/polkit.nix index cc62f22df6bd..3e8b0a3924a7 100644 --- a/nixos/modules/security/polkit.nix +++ b/nixos/modules/security/polkit.nix @@ -26,6 +26,7 @@ in options.security.polkit = { enable = mkEnableOption "polkit"; + enablePkexecWrapper = mkEnableOption "the setuid pkexec wrapper"; package = mkPackageOption pkgs "polkit" { }; @@ -157,6 +158,7 @@ in security.pam.services.polkit-1 = { }; security.wrappers.pkexec = { + enable = cfg.enablePkexecWrapper; setuid = true; owner = "root"; group = "root"; From 0c1e323f6aadc184674e45e1fcc3890d0108444c Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:05:33 +0200 Subject: [PATCH 03/17] nixos/installers/calamares: opt into pkexec --- .../installer/cd-dvd/installation-cd-graphical-calamares.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix index 097a4eca51d5..59e050fe2846 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix @@ -11,6 +11,9 @@ in { imports = [ ./installation-cd-graphical-base.nix ]; + # required for calamares + security.polkit.enablePkexecWrapper = true; + # required for kpmcore to work correctly programs.partition-manager.enable = true; From 581de9713ce0a5736a5680721222d31583d058ca Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:24:21 +0200 Subject: [PATCH 04/17] nixos/throne: opt into pkexec https://github.com/throneproj/Throne/blob/4.3.7/src/ui/mainwindow.cpp#L843-L847 --- nixos/modules/programs/throne.nix | 48 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/nixos/modules/programs/throne.nix b/nixos/modules/programs/throne.nix index 2023055892dd..a64178c77757 100644 --- a/nixos/modules/programs/throne.nix +++ b/nixos/modules/programs/throne.nix @@ -64,32 +64,36 @@ in # 3. Put ThroneCore into a systemd service, and let polkit check service name. # This is the most secure and convenient way but requires heavy modification # to Throne source code. Would be good to let upstream support that eventually. - security.polkit.extraConfig = - lib.mkIf (cfg.tunMode.enable && (!cfg.tunMode.setuid) && config.services.resolved.enable) - '' - polkit.addRule(function(action, subject) { - const allowedActionIds = [ - "org.freedesktop.resolve1.revert", - "org.freedesktop.resolve1.set-domains", - "org.freedesktop.resolve1.set-default-route", - "org.freedesktop.resolve1.set-dns-servers" - ]; + security.polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + extraConfig = + lib.mkIf (cfg.tunMode.enable && (!cfg.tunMode.setuid) && config.services.resolved.enable) + '' + polkit.addRule(function(action, subject) { + const allowedActionIds = [ + "org.freedesktop.resolve1.revert", + "org.freedesktop.resolve1.set-domains", + "org.freedesktop.resolve1.set-default-route", + "org.freedesktop.resolve1.set-dns-servers" + ]; - if (allowedActionIds.indexOf(action.id) !== -1) { - try { - var parentPid = polkit.spawn(["${lib.getExe' pkgs.procps "ps"}", "-o", "ppid=", subject.pid]).trim(); - var parentCap = polkit.spawn(["${lib.getExe' pkgs.libcap "getpcaps"}", parentPid]).trim(); - if (parentCap.includes("cap_net_admin") && parentCap.includes("cap_net_raw")) { - return polkit.Result.YES; - } else { + if (allowedActionIds.indexOf(action.id) !== -1) { + try { + var parentPid = polkit.spawn(["${lib.getExe' pkgs.procps "ps"}", "-o", "ppid=", subject.pid]).trim(); + var parentCap = polkit.spawn(["${lib.getExe' pkgs.libcap "getpcaps"}", parentPid]).trim(); + if (parentCap.includes("cap_net_admin") && parentCap.includes("cap_net_raw")) { + return polkit.Result.YES; + } else { + return polkit.Result.NOT_HANDLED; + } + } catch (e) { return polkit.Result.NOT_HANDLED; } - } catch (e) { - return polkit.Result.NOT_HANDLED; } - } - }) - ''; + }) + ''; + }; }; meta.maintainers = with lib.maintainers; [ aleksana ]; From 85af19563a855c79870a03df8607ee998422bfff Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:26:22 +0200 Subject: [PATCH 05/17] nixos/xfce: opt into pkexec https://github.com/search?q=org%3Axfce-mirror%20pkexec&type=code --- nixos/modules/services/x11/desktop-managers/xfce.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 2d53eb58f287..3dcc5431e7c8 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -220,7 +220,10 @@ in # Enable helpful DBus services. services.udisks2.enable = true; - security.polkit.enable = true; + security.polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + }; services.accounts-daemon.enable = true; services.upower.enable = config.powerManagement.enable; services.gnome.glib-networking.enable = true; From 29e29c39b151f03795f8a4c9f9f2151959fa178f Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:27:20 +0200 Subject: [PATCH 06/17] nixos/cinnamon: opt into pkexec https://github.com/search?q=repo%3Alinuxmint%2Fcinnamon%20pkexec&type=code --- nixos/modules/services/x11/desktop-managers/cinnamon.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/x11/desktop-managers/cinnamon.nix b/nixos/modules/services/x11/desktop-managers/cinnamon.nix index a91fa045aa7a..738aaa000a79 100644 --- a/nixos/modules/services/x11/desktop-managers/cinnamon.nix +++ b/nixos/modules/services/x11/desktop-managers/cinnamon.nix @@ -111,7 +111,10 @@ in services.blueman.enable = mkDefault (notExcluded pkgs.blueman); services.hardware.bolt.enable = mkDefault (notExcluded pkgs.bolt); hardware.bluetooth.enable = mkDefault true; - security.polkit.enable = true; + security.polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + }; services.accounts-daemon.enable = true; services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true)); services.dbus.packages = with pkgs; [ From 861d61d3a8ba08c67f875669f23843da10f75ec1 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:36:26 +0200 Subject: [PATCH 07/17] nixos/cosmic: opt into pkexec https://github.com/search?q=org%3Apop-os%20pkexec&type=code --- nixos/modules/services/desktop-managers/cosmic.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/desktop-managers/cosmic.nix b/nixos/modules/services/desktop-managers/cosmic.nix index c780a5164922..3d367f01defe 100644 --- a/nixos/modules/services/desktop-managers/cosmic.nix +++ b/nixos/modules/services/desktop-managers/cosmic.nix @@ -146,7 +146,10 @@ in environment.sessionVariables.X11_EXTRA_RULES_XML = "${config.services.xserver.xkb.dir}/rules/base.extras.xml"; programs.dconf.enable = true; programs.dconf.packages = [ pkgs.cosmic-session ]; - security.polkit.enable = true; + security.polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + }; security.rtkit.enable = true; services.accounts-daemon.enable = true; services.displayManager.sessionPackages = [ pkgs.cosmic-session ]; From 6e6895d6bfbfcd889a98a4e6f001e0818467aba2 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:38:06 +0200 Subject: [PATCH 08/17] nixos/budgie: opt into pkexec https://github.com/search?q=org%3ABuddiesOfBudgie%20pkexec&type=code --- nixos/modules/services/desktop-managers/budgie.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nixos/modules/services/desktop-managers/budgie.nix b/nixos/modules/services/desktop-managers/budgie.nix index 29bdb469d7f1..807d6b019b72 100644 --- a/nixos/modules/services/desktop-managers/budgie.nix +++ b/nixos/modules/services/desktop-managers/budgie.nix @@ -243,6 +243,8 @@ in # Required by Budgie's Polkit Dialog. security.polkit.enable = mkDefault true; + # Required by Budige's Control Center and Desktop + security.polkit.enablePkexecWrapper = mkDefault true; # Required by Budgie Panel plugins and/or Budgie Control Center panels. networking.networkmanager.enable = mkDefault true; # for BCC's Network panel. From 947ef21d343d41b0fac2180afbc54acc8c55bef1 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:40:59 +0200 Subject: [PATCH 09/17] nixos/gnome: opt into pkexec --- nixos/modules/services/desktop-managers/gnome.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/desktop-managers/gnome.nix b/nixos/modules/services/desktop-managers/gnome.nix index 3747a491098f..1d850f1f26e5 100644 --- a/nixos/modules/services/desktop-managers/gnome.nix +++ b/nixos/modules/services/desktop-managers/gnome.nix @@ -325,7 +325,11 @@ in i18n.inputMethod.enable = mkDefault true; i18n.inputMethod.type = mkDefault "ibus"; programs.dconf.enable = true; - security.polkit.enable = true; + security.polkit = { + enable = true; + # Required by gnome-initial-setup, gnome-system-monitor, gvfs for admin:// + enablePkexecWrapper = lib.mkDefault true; + }; security.rtkit.enable = mkDefault true; services.accounts-daemon.enable = true; services.dleyna.enable = mkDefault true; From 00343843d4a153e1cbb0bace3d0bbeea0457f924 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:46:35 +0200 Subject: [PATCH 10/17] nixos/tuned: opt into pkexec --- nixos/modules/services/hardware/tuned.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/hardware/tuned.nix b/nixos/modules/services/hardware/tuned.nix index 65a857f4fde8..f399dc55c306 100644 --- a/nixos/modules/services/hardware/tuned.nix +++ b/nixos/modules/services/hardware/tuned.nix @@ -246,7 +246,10 @@ in systemPackages = [ cfg.package ]; }; - security.polkit.enable = lib.mkDefault true; + security.polkit = { + enable = lib.mkDefault true; + enablePkexecWrapper = lib.mkDefault true; + }; services = { dbus.packages = [ cfg.package ]; From 6ef165d25f172500e308e8dd2d3893ec9e774d2b Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 9 Jun 2026 23:53:35 +0200 Subject: [PATCH 11/17] nixos/tests/timekpr: hook up in all-tests, migrate to container --- nixos/tests/all-tests.nix | 1 + nixos/tests/timekpr.nix | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 5b17b838e343..a2b16804b4cb 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1700,6 +1700,7 @@ in tiddlywiki = runTest ./tiddlywiki.nix; tigervnc = handleTest ./tigervnc.nix { }; tika = runTest ./tika.nix; + timekpr = runTest ./timekpr.nix; timezone = runTest ./timezone.nix; timidity = handleTestOn [ "aarch64-linux" "x86_64-linux" ] ./timidity { }; tinc = handleTest ./tinc { }; diff --git a/nixos/tests/timekpr.nix b/nixos/tests/timekpr.nix index 1ae793d8f70e..9f832d2b62dd 100644 --- a/nixos/tests/timekpr.nix +++ b/nixos/tests/timekpr.nix @@ -1,13 +1,15 @@ -{ pkgs, lib, ... }: +{ + lib, + ... +}: + { name = "timekpr"; meta.maintainers = [ lib.maintainers.atry ]; - nodes.machine = - { pkgs, lib, ... }: - { - services.timekpr.enable = true; - }; + containers.machine = { + services.timekpr.enable = true; + }; testScript = '' start_all() From 45d40120be493bea3566af42aee59d8727618ae5 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Wed, 10 Jun 2026 17:27:44 +0200 Subject: [PATCH 12/17] nixos/security/run0: enable guard, polkit, refactor The module now enables polkit, which run0 requires to faciliate elevation. This warrants guarding the config by an opt-in enable toggle. For the options that existed prior to the enable toggle we now assert that users need to opt into the module for them to have an effect. --- nixos/modules/security/run0.nix | 66 +++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/nixos/modules/security/run0.nix b/nixos/modules/security/run0.nix index 22296a76c95e..6aa7f9ad3155 100644 --- a/nixos/modules/security/run0.nix +++ b/nixos/modules/security/run0.nix @@ -6,6 +6,13 @@ }: let + inherit (lib) + mkEnableOption + mkIf + mkMerge + mkOption + ; + cfg = config.security.run0; sudoAlias = pkgs.writeShellScriptBin "sudo" '' @@ -18,7 +25,9 @@ let in { options.security.run0 = { - wheelNeedsPassword = lib.mkOption { + enable = mkEnableOption "support for run0"; + + wheelNeedsPassword = mkOption { type = lib.types.bool; default = true; description = '' @@ -27,26 +36,45 @@ in ''; }; - enableSudoAlias = lib.mkEnableOption "make {command}`sudo` an alias to {command}`run0`."; + enableSudoAlias = mkEnableOption "make {command}`sudo` an alias to {command}`run0`."; }; - config = { - assertions = [ - { - assertion = - cfg.enableSudoAlias -> (!config.security.sudo.enable && !config.security.sudo-rs.enable); - message = "`security.run0.enableSudoAlias` cannot be enabled if `security.sudo` or `security.sudo-rs` are enabled."; - } - ]; - - security.polkit.extraConfig = lib.mkIf (!cfg.wheelNeedsPassword) '' - polkit.addRule(function(action, subject) { - if (action.id == "org.freedesktop.systemd1.manage-units" && subject.isInGroup("wheel")) { - return polkit.Result.YES; + config = mkMerge [ + { + # Late introduction of the enable toggle, this should help during migration. + # TODO: Remove after 26.11 release + assertions = [ + { + assertion = !cfg.wheelNeedsPassword -> cfg.enable; + message = "`security.run0.enable` is currently disabled, but is required for the `security.run0.wheelNeedsPassword` option to take effect"; } - }); - ''; + { + assertion = cfg.enableSudoAlias -> cfg.enable; + message = "`security.run0.enableSudoAlias` depends on `security.run0.enable`, which is disabled."; + } + ]; + } + (mkIf cfg.enable { + assertions = [ + { + assertion = + cfg.enableSudoAlias -> (!config.security.sudo.enable && !config.security.sudo-rs.enable); + message = "`security.run0.enableSudoAlias` cannot be enabled if `security.sudo` or `security.sudo-rs` are enabled."; + } + ]; - environment.systemPackages = lib.optional cfg.enableSudoAlias sudoAlias; - }; + security.polkit = { + enable = true; + extraConfig = mkIf (!cfg.wheelNeedsPassword) '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.systemd1.manage-units" && subject.isInGroup("wheel")) { + return polkit.Result.YES; + } + }); + ''; + }; + + environment.systemPackages = lib.optional cfg.enableSudoAlias sudoAlias; + }) + ]; } From f252c4820dad8bb37d2b45e8b0d45a4b08321dee Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Wed, 10 Jun 2026 01:51:48 +0200 Subject: [PATCH 13/17] nixos/gnome-remote-desktop: opt into pkexec Calls pkexec in src/grd-ctl.c. --- .../modules/services/desktops/gnome/gnome-remote-desktop.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nixos/modules/services/desktops/gnome/gnome-remote-desktop.nix b/nixos/modules/services/desktops/gnome/gnome-remote-desktop.nix index 958fbb546dc3..eaa9399862a4 100644 --- a/nixos/modules/services/desktops/gnome/gnome-remote-desktop.nix +++ b/nixos/modules/services/desktops/gnome/gnome-remote-desktop.nix @@ -22,6 +22,10 @@ config = lib.mkIf config.services.gnome.gnome-remote-desktop.enable { services.pipewire.enable = true; services.dbus.packages = [ pkgs.gnome-remote-desktop ]; + security.polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + }; environment.systemPackages = [ pkgs.gnome-remote-desktop ]; From 3da268745ad0ce3d36520bcd5dff78ec33a5ae61 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Wed, 10 Jun 2026 17:10:26 +0200 Subject: [PATCH 14/17] nixos/installer/tools: enable run0 module The run0 module now enables polkit and properly reflects the intent behind the `enableRun0Elevation` option. --- nixos/modules/installer/tools/tools.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index 8fd268ee0d2d..23a0bebe388c 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -330,7 +330,7 @@ in ''; config = lib.mkIf config.system.tools.nixos-rebuild.enableRun0Elevation { - security.polkit.enable = lib.mkDefault true; + security.run0.enable = lib.mkDefault true; environment.systemPackages = [ pkgs.polkit-stdin-agent ]; }; } From 517a082accdd727933b69cf16809867b450ebb09 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Wed, 10 Jun 2026 23:38:46 +0200 Subject: [PATCH 15/17] nixos/polkit: stop if changed We concluded this is fine, because we don't require elevation while switching generations. Co-Authored-By: r-vdp Co-Authored-By: Grimmauld --- nixos/modules/security/polkit.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/nixos/modules/security/polkit.nix b/nixos/modules/security/polkit.nix index 3e8b0a3924a7..6ea840d4ccf3 100644 --- a/nixos/modules/security/polkit.nix +++ b/nixos/modules/security/polkit.nix @@ -99,7 +99,6 @@ in reloadTriggers = [ config.environment.etc."polkit-1/rules.d/10-nixos.rules".source ]; - stopIfChanged = false; serviceConfig.ExecStart = [ # nuke default ExecStart "" From 73c9e8d0fa59da12e5b8bd95ba010693f2eb2435 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 11 Jun 2026 22:10:11 +0200 Subject: [PATCH 16/17] nixos/test/lomiri/desktop-appinteractions: use run0 for elevation --- nixos/tests/lomiri.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/tests/lomiri.nix b/nixos/tests/lomiri.nix index 5dc43286c0f3..61893abe91a1 100644 --- a/nixos/tests/lomiri.nix +++ b/nixos/tests/lomiri.nix @@ -669,7 +669,7 @@ in # Doing this here, since we need an in-session shell & separately starting a terminal again wastes time with subtest("polkit agent works"): - machine.send_chars("pkexec touch /tmp/polkit-test\n") + machine.send_chars("run0 touch /tmp/polkit-test\n") # There's an authentication notification here that gains focus, but we struggle with OCRing it # Just hope that it's up after a short wait machine.sleep(10) From 7a3819ed28c9daf01944f51f31628ce9d3345e01 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Fri, 12 Jun 2026 00:50:44 +0200 Subject: [PATCH 17/17] nixos/gamemode: opt into pkexec --- nixos/modules/programs/gamemode.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/programs/gamemode.nix b/nixos/modules/programs/gamemode.nix index 834ae6f54a1d..3e568f9a68aa 100644 --- a/nixos/modules/programs/gamemode.nix +++ b/nixos/modules/programs/gamemode.nix @@ -60,7 +60,10 @@ in }; security = { - polkit.enable = true; + polkit = { + enable = true; + enablePkexecWrapper = lib.mkDefault true; + }; wrappers = lib.mkIf cfg.enableRenice { gamemoded = { owner = "root";