diff --git a/modules/nixos/base/power-monitoring.nix b/modules/nixos/base/power-monitoring.nix index 6fad1b35..6854a432 100644 --- a/modules/nixos/base/power-monitoring.nix +++ b/modules/nixos/base/power-monitoring.nix @@ -1,7 +1,6 @@ { config, lib, - mylib, pkgs, ... }: @@ -30,29 +29,9 @@ in node-exporter.extraGroups = [ "rapl" ]; }; - systemd.services.rapl-permissions = lib.mkIf config.services.prometheus.exporters.node.enable { - description = "Allow node_exporter to read RAPL energy counters"; - wantedBy = [ "multi-user.target" ]; - unitConfig.ConditionPathExists = "/sys/class/powercap"; - serviceConfig = mylib.systemdHardening.privilegedOneshot // { - Type = "oneshot"; - RemainAfterExit = true; - CapabilityBoundingSet = [ "CAP_CHOWN" ]; - }; - script = '' - shopt -s nullglob - for f in /sys/class/powercap/*/energy_uj; do - chgrp rapl "$f" - chmod 0440 "$f" - done - ''; - }; - - systemd.services.prometheus-node-exporter = - lib.mkIf config.services.prometheus.exporters.node.enable - { - requires = [ "rapl-permissions.service" ]; - after = [ "rapl-permissions.service" ]; - }; + # udev's GROUP/MODE only apply to device nodes, not sysfs attributes. + services.udev.extraRules = lib.mkIf config.services.prometheus.exporters.node.enable '' + ACTION=="add", SUBSYSTEM=="powercap", TEST=="energy_uj", RUN+="${pkgs.coreutils}/bin/chgrp rapl /sys%p/energy_uj", RUN+="${pkgs.coreutils}/bin/chmod 0440 /sys%p/energy_uj" + ''; }; } diff --git a/outputs/x86_64-linux/tests/cpu-power/expr.nix b/outputs/x86_64-linux/tests/cpu-power/expr.nix index ab424a73..9edd4359 100644 --- a/outputs/x86_64-linux/tests/cpu-power/expr.nix +++ b/outputs/x86_64-linux/tests/cpu-power/expr.nix @@ -41,7 +41,7 @@ in name: configs.${name}.config.modules.powerMonitoring.enable && builtins.elem "rapl" configs.${name}.config.services.prometheus.exporters.node.enabledCollectors - && configs.${name}.config.systemd.services ? rapl-permissions + && lib.hasInfix "chgrp rapl" configs.${name}.config.services.udev.extraRules ); serverRaplReaderOnly = lib.all ( name: @@ -51,9 +51,9 @@ in desktopRaplDisabled = !configs.ai-niri.config.modules.powerMonitoring.enable && !(builtins.elem "rapl" configs.ai-niri.config.services.prometheus.exporters.node.enabledCollectors) - && !(configs.ai-niri.config.systemd.services ? rapl-permissions); - guestsHaveNoRapl = lib.all (name: !(configs.${name}.config.systemd.services ? rapl-permissions)) ( - lib.subtractLists physicalHosts (builtins.attrNames configs) - ); + && !(lib.hasInfix "chgrp rapl" configs.ai-niri.config.services.udev.extraRules); + guestsHaveNoRapl = lib.all ( + name: !(lib.hasInfix "chgrp rapl" configs.${name}.config.services.udev.extraRules) + ) (lib.subtractLists physicalHosts (builtins.attrNames configs)); desktopBatteryReporting = configs.ai-niri.config.services.upower.enable; } diff --git a/outputs/x86_64-linux/tests/idols-aquamarine/expr.nix b/outputs/x86_64-linux/tests/idols-aquamarine/expr.nix index b82949bd..26368fa3 100644 --- a/outputs/x86_64-linux/tests/idols-aquamarine/expr.nix +++ b/outputs/x86_64-linux/tests/idols-aquamarine/expr.nix @@ -82,7 +82,7 @@ in ) cfg.environment.systemPackages; gpuMetricsExported = builtins.elem "drm" cfg.services.prometheus.exporters.node.enabledCollectors; raplMetricsExported = builtins.elem "rapl" cfg.services.prometheus.exporters.node.enabledCollectors; - raplPermissionsExposed = cfg.systemd.services ? rapl-permissions; + raplPermissionsExposed = lib.hasInfix "chgrp rapl" cfg.services.udev.extraRules; # node_exporter rejects a repeated flag, and this list merges with the base # module's entries, so a duplicate restart-loops the unit. collectorFlagsUnique = diff --git a/outputs/x86_64-linux/tests/security-service-hardening/expected.nix b/outputs/x86_64-linux/tests/security-service-hardening/expected.nix index c55ec723..04fe4a54 100644 --- a/outputs/x86_64-linux/tests/security-service-hardening/expected.nix +++ b/outputs/x86_64-linux/tests/security-service-hardening/expected.nix @@ -34,9 +34,6 @@ in }; privilegedOneshot = { - rapl-permissions = privilegedOneshot // { - CapabilityBoundingSet = [ "CAP_CHOWN" ]; - }; hdd-no-spindown = privilegedOneshot // { CapabilityBoundingSet = [ "CAP_SYS_RAWIO" ]; DeviceAllow = [ "block-sd rw" ]; diff --git a/outputs/x86_64-linux/tests/security-service-hardening/expr.nix b/outputs/x86_64-linux/tests/security-service-hardening/expr.nix index 2f1495ba..1577eff8 100644 --- a/outputs/x86_64-linux/tests/security-service-hardening/expr.nix +++ b/outputs/x86_64-linux/tests/security-service-hardening/expr.nix @@ -38,7 +38,6 @@ units "youko" [ // units "aquamarine" [ "whisper-asr" ] // { privilegedOneshot = { - rapl-permissions = privilegedUnit "aquamarine" "rapl-permissions"; hdd-no-spindown = privilegedUnit "youko" "hdd-no-spindown"; }; }