The fan curve previously only controlled fan index 0; secondary fans
stayed on driver control. The curve can now target all fans (new
default) or any individual fan(s).
Backend:
- hal/fans.py: get_num_fans() via nvmlDeviceGetNumFans; get_fan_info()
returns per-fan speeds; set_fan_speed() accepts a fan index list
(None = all fans; all-fans mode is lenient toward driver-locked
fans, explicit lists are strict); reset_fan() restores all fans.
- server.py: per-GPU fan_targets state; the poller applies the curve to
all target fans and logs write failures (once per distinct error);
activation validates targets against the hardware (stale indices fall
back to all fans); POST /api/fans accepts fans, POST /api/fans/speed
accepts a fan index, GET /api/fans returns num_fans/fans/fan_targets.
- Persistence format is now {"curve": ..., "fans": ...}; legacy
bare-curve entries migrate to "all fans" at startup.
- Profiles save/apply fan_targets alongside fan_curve.
- MonitoringSample carries per-fan speeds for live gauges.
Frontend:
- Fans tab: All / Fan 1 / Fan 2 / ... selector with live per-fan %;
the selection is applied together with the curve.
- Live monitor: per-fan gauges with sparklines for multi-fan GPUs.
5.7 KiB
NVCurve brings MSI Afterburner-style per-point voltage-frequency curve control to Linux via undocumented NvAPI functions. A React web UI for interactive editing and monitoring; a Python CLI for scripting and headless use.
Warning
Experimental software. Undocumented NvAPI functions may change between driver releases. Write operations alter GPU operational parameters. Always run
nvcurve setupbefore applying changes.
Important
Blackwell GPU memory — This is a specialized fork with extended memory offset support (up to +3000 MHz) for Blackwell GPUs (RTX 50-series).
Fan Controls — There is an additional "Fans" tab to setup a customized fan curve, controlling all fans or individual fans.
Dashboard — The default tab is an Dashboard with additional information (PCIe link speed, VBIOS information, Max Core Clock, Throttle Reason and much much more.)
Authentification — For production deplyoment, I added authentification with bcrypt hashing to allow only one or multiple people to have access.
Installing the pre-built PyPI package will NOT include these features. You must build from source.
![]() |
![]() |
![]() |
![]() |
Prerequisites
- Linux with NVIDIA proprietary drivers
- Python 3.12+
- Node.js 18+ and npm (for building the React frontend)
- uv — Python package manager
- Root/sudo access (required for GPU hardware interactions)
Installation from Source
git clone <this-repo-url>.git
cd nvcurve
# Build the React frontend
cd frontend
npm install
npm run build
cd ..
# Install the Python package (includes bundled frontend)
uv tool install .
After installation, verify hardware compatibility:
nvcurve setup
Getting Started
nvcurve # Launch web UI at http://localhost:8042
nvcurve read # Quick curve read from CLI
Authentication (Multi-User)
The server runs open by default. On a shared machine (e.g. an AI server), add users to require a login — the web UI then shows a sign-in screen and every API/WebSocket call is protected. Passwords are stored as bcrypt hashes; sessions last 24 hours.
sudo nvcurve user add alice # add a user (prompts for password)
nvcurve user list # list users
sudo nvcurve user remove alice # remove a user
Adding the first user enables authentication immediately; removing the last user disables it. See the Usage Guide for details.
Systemd Service
Install the daemon for automatic profile loading on boot and optional web server auto-start:
Install with web server auto-start
nvcurve service install --auto-serve --host 0.0.0.0 --port 8042
Install daemon only (start web server on demand)
nvcurve service install
Manage
nvcurve service start|stop|restart|status
nvcurve service uninstall
Reconfigure
nvcurve service configure --auto-serve # Enable web server auto-start
nvcurve service configure --no-auto-serve # Disable web server auto-start
nvcurve service configure --host 0.0.0.0 --port 8042
Manual systemd Unit
If you prefer managing the unit file directly, here is the template installed by nvcurve service install:
[Unit]
Description=NVCurve NVIDIA GPU V/F Curve Daemon
After=nvidia-persistenced.service
Wants=nvidia-persistenced.service
[Service]
Type=simple
ExecStart=/usr/bin/python3 -m nvcurve daemon
Restart=on-failure
RestartSec=5
Environment=PYTHONDONTWRITEBYTECODE=1
[Install]
WantedBy=multi-user.target
Place at /etc/systemd/system/nvcurve.service, then:
sudo systemctl daemon-reload
sudo systemctl enable --now nvcurve
Persistent Configuration
The daemon reads settings from /etc/nvcurve/config.json:
{
"host": "127.0.0.1",
"port": 8042,
"auto_serve": false,
"max_delta_khz": 3000000,
"auto_snapshot": true,
"max_snapshots": 20,
"auto_load_profiles": {
"idx:0": "my_profile"
}
}
| Setting | Description |
|---|---|
host |
Web server bind address (0.0.0.0 for network access) |
port |
Web server port (default 8042) |
auto_serve |
Auto-start web server on boot |
max_delta_khz |
Safety cap for frequency offsets (default 3000 MHz) |
auto_snapshot |
Save snapshot before every write |
max_snapshots |
Max snapshots to keep (0 = unlimited) |
auto_load_profiles |
Per-GPU profile to apply on boot ({gpu_key: profile_name}) |
The GPU key can be a UUID, pci:XXXX, or idx:N fallback. Find your GPU key with nvcurve gpus.
Documentation
- Overview — What it does, capabilities, architecture
- Installation — Prerequisites, source build, troubleshooting
- Usage Guide — Web UI, CLI reference, systemd service
- Tips and Tricks — Workflows, curve flattening, safety
Upgrading
cd nvcurve
git pull
cd frontend && npm run build && cd ..
uv tool install .
If running as a systemd service:
nvcurve service restart
Changelog
See CHANGELOG.md.



