PowerNap is a local, capability-aware Linux power-management daemon. It balances workload demand, electricity prices, and thermal conditions, then applies the safest power controls exposed by the running kernel and hardware drivers.
PowerNap is profile-centric rather than governor-centric. It selects an abstract operating profile, then maps that profile to the controls the current system actually supports. A machine may use CPUFreq governors and frequency ceilings, another may expose energy-performance preferences, and a GPU may provide a bounded power limit. Unsupported controls are reported and skipped instead of guessed.
Project status: PowerNap 0.11.8 is a pre-release intended for dry-run validation and hardware testing. The supplied configuration has
dry_run = true. CPU governor and frequency-ceiling writes across all twelve acpi-cpufreq policies, plus NVIDIA power-limit write, readback, and restoration through NVML, have been validated on the target Ubuntu host. Other physical control paths remain under validation.
- Why PowerNap
- Features
- Supported hardware and controls
- How it works
- Safety model
- Requirements
- Installation
- Quick start
- Configuration
- Command reference
- Example decisions
- Running as a systemd service
- Data and privacy
- Testing
- Validation status
- Roadmap
- Contributing
- Security
- License
Linux power-management tools often focus on one part of the system, such as CPU frequency, laptop battery life, thermal control, or a vendor-specific GPU interface. PowerNap brings those signals together in one local decision process.
PowerNap is designed to answer four questions continuously:
- How much CPU and GPU performance does the current workload need?
- Is electricity relatively cheap or expensive right now?
- Is temperature limiting the safe performance ceiling?
- Which documented controls are actually available on this machine?
Electricity price influences discretionary headroom. It does not override thermal protection or reduce a real workload below its measured or configured minimum profile.
- Abstract Eco, Balanced, Responsive, and Maximum profiles
- Immediate thermal protection for critical conditions
- CPU demand calculated from average use, peak-core use, busy-core ratio, normalized load, and warmed-up sustained activity
- GPU demand from utilization, memory activity, and video engines when available
- Swedish electricity prices through Elpris.eu with Elpriset Just Nu as an optional fallback
- Hourly and quarter-hour price intervals with provider isolation, DST-aware complete-day validation, gap detection, and duration-weighted lookahead
- Capability discovery before control planning
- Multiple CPUFreq policy support with direction-aware global operation ordering
- CPU governor, frequency ceiling, and energy-performance preference planning
- NVIDIA telemetry and hardware-bounded power limits through NVML
- AMDGPU discovery and documented performance-level control
- Powercap and RAPL discovery
- Separate CPU and GPU thermal states and safety ceilings
- Protected-process minimum profiles
- Candidate-based transitions with faster promotion, delayed relaxation, and restart-safe state
- External-setting conflict detection with persisted yield and policy events
- Read-back verification after changes
- Required-operation rollback after failure
- Baseline restoration on shutdown
- SQLite history for samples, decisions, control events, capability snapshots, price intervals, and transition state
- Versioned JSON status and report output with aggregate transaction state
- systemd readiness and watchdog notifications
- Dry-run mode enabled by default
- No web server or remote-control interface
PowerNap discovers generic Linux CPUFreq policy directories and records the active driver, available governors, policy CPU membership, current limits, hardware limits, and energy-performance preferences when exposed.
Expected discovery paths include:
acpi-cpufreqintel_pstateamd_pstate- Other drivers using the standard CPUFreq policy interface
Available control depends on the driver and kernel configuration:
- Scaling governor
- Maximum scaling frequency
- Energy-performance preference
- Powercap or RAPL discovery
PowerNap does not assume that every system exposes RAPL, EPP, or the same governor names.
With the optional nvidia-ml-py dependency and a compatible NVIDIA driver, PowerNap can discover:
- Stable GPU identity
- GPU and memory utilization
- Encoder and decoder activity
- Temperature
- Power draw
- Current, minimum, maximum, and default power limits
Power limits are clamped to the range reported by the driver and verified after application.
For AMDGPU devices exposing documented sysfs controls, PowerNap can discover:
- GPU identity
- Current performance level
- Available power profile modes
- Current, minimum, and maximum power caps when exposed through hwmon
The current adapter plans documented low, auto, and high performance-level changes. Fan control, overdrive tables, voltage control, and undocumented registers are outside the project scope.
Intel GPU support is observation-first. PowerNap does not write Intel GPU controls unless a documented, discoverable, and verifiable interface is implemented for the active driver.
A system without a supported GPU remains usable. A system without CPUFreq can still be inspected, but CPU control is unavailable and powernap check reports the missing capability when CPU management is enabled.
Capability discovery
|
v
CPU, GPU, thermal, workload, and price observations
|
v
Immutable system state
|
+--> Demand floor
+--> Price preference
+--> Thermal safety ceiling
|
v
Profile selection
|
v
Transition gating and hysteresis
|
v
Capability-specific control plan
|
v
Apply, read back, verify, record
The decision relationship is conceptually:
selected profile = clamp(price preference, demand floor, safety ceiling)
This prevents price from being counted several times and ensures workload demand cannot be reduced below the required floor.
PowerNap changes low-level power controls, so safety is part of the architecture rather than an optional feature.
- Dry-run by default: the supplied configuration calculates and records simulated plans without writing hardware controls.
- Capability-driven planning: values are selected only from discovered interfaces and reported ranges.
- Thermal ceiling: warm and hot conditions cap escalation; critical temperature forces Eco immediately.
- Read-back verification: a change is marked applied only when the resulting value matches the request.
- Rollback: when a required operation fails, previously applied operations in that plan are restored where possible.
- Baseline restoration: managed file-backed controls can be restored during a clean shutdown.
- External-change handling: the default
yieldpolicy stops active management after conflicting external changes are detected. - No overclocking or undervolting: PowerNap does not bypass manufacturer limits or firmware thermal protection.
- No global PCI power sweep: PowerNap does not blindly enable runtime power management across every PCI device.
Dry-run output must be reviewed on every target computer before physical control is enabled.
- Linux
- Python 3.10 or newer
psutilrequests- Write access to selected sysfs controls when physical management is enabled
- Optional
nvidia-ml-pyfor NVIDIA telemetry and control - systemd only when using the supplied service unit
git clone https://github.com/swetoast/PowerNap.git
cd PowerNap
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[test,nvidia]'If the system has no NVIDIA GPU, the optional NVIDIA dependency can be omitted:
python -m pip install -e '.[test]'powernap --config powernap.conf capabilitiespowernap --config powernap.conf checkpowernap --config powernap.conf --dry-run once --no-pricepowernap --config powernap.conf --dry-run onceDo not set dry_run = false until the capabilities and representative plans have been reviewed on the target hardware.
The included powernap.conf is a safe starting point and remains in dry-run mode.
Important settings:
[general]
dry_run = true
external_change_policy = yield
restore_on_exit = true
[price]
area = SE3
timezone = Europe/Stockholm
provider = elpris_eu
fallback_provider = elprisetjustnu
[thermal]
warm_temp_c = 60
hot_temp_c = 75
critical_temp_c = 90
[cpu]
enabled = true
powercap_enabled = false
[gpu]
nvidia_enabled = true
amdgpu_enabled = trueA comma-separated process list can establish a Responsive minimum profile while matching processes are active:
[workloads]
protected_processes = ffmpeg, HandBrakeCLINames are examples only. PowerNap does not hardcode application-specific rules.
Supported Swedish areas are SE1, SE2, SE3, and SE4.
external_change_policy accepts:
yield: stop managing after a conflicting external changeobserve: accept the external statemanage: continue applying PowerNap decisions
yield is the safest default when another power-management service may be active.
powernap --config /etc/powernap/powernap.conf runpowernap --config powernap.conf capabilitiespowernap --config powernap.conf checkpowernap --config powernap.conf --dry-run oncepowernap --config powernap.conf --dry-run once --no-pricepowernap --config powernap.conf pricespowernap --config powernap.conf statuspowernap --config powernap.conf reportDemand floor: Eco
Price preference: Eco
Thermal ceiling: Maximum
Selected profile: Eco
Average utilization: low
Peak-core utilization: high
Demand floor: Responsive
Selected profile: Responsive
Peak-core demand prevents a single-threaded workload from being misclassified as idle.
GPU demand floor: Responsive
Price preference: Eco
Thermal ceiling: Maximum
Selected profile: Responsive
Measured workload demand overrides the lower price preference.
Thermal ceiling: Eco
Selected profile: Eco
Transition: immediate
Critical thermal protection bypasses normal transition holds.
First install PowerNap and validate it in dry-run mode. Then install the configuration and service:
sudo install -d -m 0755 /etc/powernap /var/lib/powernap
sudo install -m 0644 powernap.conf /etc/powernap/powernap.conf
sudo install -m 0644 systemd/powernap.service /etc/systemd/system/powernap.service
sudo systemctl daemon-reload
sudo systemctl enable --now powernap.serviceInspect service state and logs:
sudo systemctl status powernap.service
sudo journalctl -u powernap.service -fThe service uses systemd readiness and watchdog notifications. Its hardening settings still allow access to the selected sysfs and database paths required for power management.
PowerNap runs locally and has no web server or remote-control interface.
It stores local records in SQLite:
- System observation summaries
- Profile decisions
- Control attempts and verification results
- Normalized price records and metadata where implemented
Process protection matches configured executable or process names. It does not inspect document contents or network payloads.
Electricity-price requests are sent only to the configured provider and optional fallback provider.
Install test dependencies and run:
python -m pip install -e '.[test,nvidia]'
pytestThe current automated suite covers:
- Configuration parsing and validation
- Inline comments on boolean settings
- Single-core burst detection
- Missing-price behavior
- Critical thermal override
- Transition candidate behavior
- Generic CPUFreq fixture discovery
- Governor mapping
- SQLite cycle persistence
Hardware integration testing must be performed explicitly because automated tests do not write to the host's real power controls.
- Python module compilation
- 134 regression tests with measured branch coverage, covering capabilities, configuration, CLI behavior, control ordering, rollback, dry-run isolation, thermal safety and recovery, transitions, electricity prices, database migration, workloads, packaging, and telemetry
- One-shot dry-run execution
- JSON validation for one-shot, capability, and check output
- Final ZIP integrity and content inspection
- Removal of bytecode, caches, and test artifacts from the archive
- Physical writes on every CPUFreq, EPP, AMDGPU, NVIDIA, and RAPL implementation
- Long-term service stability on a broad hardware set
- systemd watchdog behavior on every distribution
- Live price-provider behavior in every network environment
- The design target of 85 percent branch coverage. Current measured branch coverage is 83.90 percent
See docs/VALIDATION.md for the exact validation record.
Before a 1.0 release, the project needs:
- Real-hardware validation for each advertised writable adapter
- Wider tests for hourly, quarter-hour, DST, missing, duplicate, overlapping, and out-of-order price intervals
- Cache-corruption recovery and additional price-quality diagnostics
- Expanded AMDGPU and Intel GPU validation
- Physical RAPL application and restoration tests on supported hardware
- Service installation and upgrade tests
- Branch coverage measurement and expansion toward the documented target
- Long-duration daemon and suspend/resume testing
- Distribution-specific installation documentation
Contributions are welcome. Start with CONTRIBUTING.md, run the regression suite, and keep new hardware controls capability-driven, bounded, and verifiable.
A new hardware adapter should include:
- Documented discovery logic
- Valid range detection
- Dry-run output
- Read-back verification
- Failure handling
- Fixture-based tests
- Real-hardware validation notes
Do not publish suspected vulnerabilities in a public issue. Follow SECURITY.md for reporting guidance.
PowerNap can run with privileges capable of changing hardware power settings. Review configuration, service permissions, dependency sources, and dry-run plans before deployment.
PowerNap is licensed under the GNU General Public License v3.0. You may use, study, modify, and redistribute the software under the terms of that license.
The project repository is swetoast/PowerNap. Issues and source history are maintained there.