feat(power): laptop power management (power-profiles-daemon + TLP)

Adds a `nomarchy.system.power.*` surface (modules/nixos/power.nix),
replacing the bare `services.upower` (Waybar reporting only) baseline:

- power-profiles-daemon ships by default; switched through polkit (no
  root prompt). TLP is the opt-in `backend = "tlp"` for deeper battery
  tuning — the two are mutually exclusive (asserted).
- thermald behind `power.thermal.enable` (Intel-only).
- `power.batteryChargeLimit` (e.g. 80): a backend-independent sysfs
  oneshot writes charge_control_end_threshold; gated on `power.laptop`.

Switcher + indicator live home-side and self-gate on a battery being
present + powerprofilesctl running, so they hide on desktops and under
TLP — no system->home wiring (like the Waybar battery widget):

- rofi.nix: `nomarchy-menu power-profile` module + a picker entry shown
  only on laptops with PPD.
- waybar.nix: first `custom/*` module — click cycles the profile.

Installer writes `power.laptop = true` (battery probe) and
`power.thermal.enable` (GenuineIntel) into the generated system.nix, and
scaffolds the charge limit commented-out.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-14 17:35:42 +01:00
parent 8853f6ae49
commit 00f5311499
7 changed files with 233 additions and 37 deletions

View File

@@ -408,6 +408,26 @@ NIX
)
fi
# Laptop power: power-profiles-daemon ships by default; mark this a laptop
# so battery-only features apply, and enable thermald on Intel. Keyed off
# the same battery probe that chose the common-pc-laptop hardware profile.
POWER_CONFIG=""
if [[ " ${HW_PROFILES[*]:-} " == *" common-pc-laptop "* ]]; then
power_lines=" # Laptop power management (power-profiles-daemon + menu/Waybar
# switcher). Uncomment to stop charging at 80% to extend battery life.
nomarchy.system.power.laptop = true;
# nomarchy.system.power.batteryChargeLimit = 80;"
if grep -q GenuineIntel /proc/cpuinfo 2>/dev/null; then
power_lines+="
nomarchy.system.power.thermal.enable = true; # thermald (Intel)"
fi
POWER_CONFIG=$(cat <<NIX
$power_lines
NIX
)
fi
# initialHashedPassword is safe to template: mkpasswd's alphabet is
# [a-zA-Z0-9./$] — no Nix string metacharacters.
cat > "$FLAKE_DIR/system.nix" <<EOF
@@ -440,7 +460,7 @@ cat > "$FLAKE_DIR/system.nix" <<EOF
extraGroups = [ "wheel" "networkmanager" "video" "input" ];
initialHashedPassword = "$HASHED_PASSWORD";
};
$AUTOLOGIN_CONFIG$RESUME_CONFIG
$AUTOLOGIN_CONFIG$POWER_CONFIG$RESUME_CONFIG
# Hourly/daily BTRFS timeline snapshots + nixos-rebuild-snap.
nomarchy.system.snapper.enable = true;