Files
nixos-config/modules/system/cpugov.nix
Mans Ziesel da7c0282c6 Replace ppd waybar widget with cpufreq governor toggle
The Ryzen 7 3700U (Zen+) lacks CPPC, and the laptop exposes no ACPI
platform_profile, so power-profiles-daemon has no real backend and only
shows placeholder profiles. Swap the ppd widget for a custom waybar
module backed by a small `cpugov` helper that reads and toggles the
cpufreq governor directly. Left-click cycles schedutil <-> performance
via a NOPASSWD sudo rule scoped to the wrapper path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 16:08:26 +02:00

80 lines
2.3 KiB
Nix

{
config,
lib,
pkgs,
...
}:
# CPU governor toggle for hosts without a power-profiles-daemon backend
# (e.g. Zen+ CPUs that lack CPPC and laptops with no ACPI platform_profile).
# Installs a `cpugov` helper used by the waybar custom/cpugov widget and
# allows wheel users to write the governor without a password prompt.
let
cpugov = pkgs.writeShellApplication {
name = "cpugov";
text = ''
cur() {
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
}
apply() {
local gov="$1"
case "$gov" in
performance|schedutil|powersave|ondemand|conservative|userspace) ;;
*) echo "Unsupported governor: $gov" >&2; exit 1 ;;
esac
for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
printf '%s\n' "$gov" > "$f"
done
}
cycle() {
case "$(cur)" in
schedutil) apply performance ;;
performance) apply schedutil ;;
*) apply schedutil ;;
esac
}
status() {
local gov
gov=$(cur)
case "$gov" in
performance) printf '{"text":" 󰓅 perf ","tooltip":"CPU governor: performance","class":"performance"}\n' ;;
schedutil) printf '{"text":" 󰊚 sched ","tooltip":"CPU governor: schedutil","class":"schedutil"}\n' ;;
*) printf '{"text":" %s ","tooltip":"CPU governor: %s","class":"other"}\n' "$gov" "$gov" ;;
esac
}
case "''${1:-status}" in
status) status ;;
cycle) cycle ;;
set) apply "''${2:-}" ;;
*) echo "Usage: cpugov [status|cycle|set <gov>]" >&2; exit 1 ;;
esac
'';
};
in
{
config = lib.mkIf config.custom.isLaptop {
environment.systemPackages = [ cpugov ];
# Writing scaling_governor requires root; allow wheel members to call
# the helper without a password so the waybar widget can toggle on click.
# Sudo matches command paths literally (no symlink canonicalization), so
# use the stable wrapper path instead of the per-build store path.
security.sudo.extraRules = [
{
groups = [ "wheel" ];
commands = [
{
command = "/run/current-system/sw/bin/cpugov";
options = [ "NOPASSWD" ];
}
];
}
];
};
}