Fan control and keyboard lighting for HP Victus / Omen laptops on Linux.
Stock firmware parks both fans near 2000 RPM in AUTO while the CPU cooks.
victus-control gives you a real fan curve, animated RGB backlighting, a
privileged backend, a GTK4 desktop app, and a GNOME Shell extension.
- Why victus-control
- Quick install
- Support matrix
- Secure Boot / userspace alternative
- System requirements
- Install & update
- The OMEN key
- Daily usage
- Telemetry history
- Lighting effects
- Cinnamon applet
- GNOME Shell extension
- Developing
- Troubleshooting
- Contributing
- License
| Feature | What it does | |
|---|---|---|
| 🌀 | Better Auto | Samples CPU/GPU temperature and utilisation every ~2 s, clamps to each fan's hardware maximum, and reapplies targets every 90 s with the firmware-required 10 s stagger. Fans climb smoothly with load instead of idling at 2000 RPM like HP's AUTO. |
| 🎚️ | Manual mode | Eight RPM steps (~2000 ➜ 5800/6100 RPM) with per-fan precision and watchdog refreshes that keep settings alive through firmware quirks. |
| 🌈 | Animated lighting | Single-zone and four-zone RGB, brightness, and rainbow / breathe / flow animations that keep running after the app is closed. |
| 📊 | Analog telemetry | Fan dials whose blades turn with the real RPM, and thermometers that shift colour as they heat. |
| 📈 | History graphs | Recent temperature, fan speed, CPU/GPU load, RAM and VRAM on a shared time axis. |
| 🖥️ | Panel integration | Fan and keyboard controls from the panel — a Cinnamon applet and a GNOME Shell extension. |
Warning
Validated primarily on HP Victus 16-s00xxxx and contributor-tested on the Fedora/Arch variants listed in PRs and issues. Other models may work but are not guaranteed — monitor your thermals. On HP Victus 15 fa0xxx, manual fan speeds appear unsupported; only MAX, AUTO, and Better Auto are known to behave.
curl -fsSL https://raw.githubusercontent.com/Batuhan4/victus-control/main/bootstrap.sh | bashThe bootstrap script downloads the current main branch into a temporary directory and runs install.sh.
Caution
Do not pipe this into sudo. install.sh elevates itself and needs to know the original desktop user to set up the GNOME extension.
| Component | Status |
|---|---|
| Main installer | Arch-based, Fedora, and Ubuntu/Debian-based distros |
| Desktop app | GTK4, installed by the main project installer |
| GNOME Shell extension | GNOME Shell 45+, auto-installed by install.sh when GNOME is present |
| Ubuntu / Debian | Contributor-tested on Ubuntu 24.04 LTS (GNOME 46); other Debian-based distros use the same path but are less tested |
If you can't load the patched hp-wmi DKMS module — most notably on Ubuntu with Secure Boot enabled, where unsigned out-of-tree modules are rejected — see victus-fan/.
It is a self-contained userspace controller that drives the stock in-tree hp-wmi driver (two-state pwm1_enable, no kernel module), tying fan speed to your power profile and CPU / iGPU / NVIDIA temperature via a small daemon + CLI (no GUI). Tested on an HP Victus 15-fb0xxx running Ubuntu 26.04 — see victus-fan/README.md.
Important
Pick one fan controller, not both. victus-fan and the main victus-backend both write the same pwm1_enable knob; running both at once makes them fight over the fans. Use victus-fan instead of the DKMS stack on machines where the patched module can't load — not alongside it.
| Requirement | Detail |
|---|---|
| OS | 64-bit Linux with systemd |
| Package manager | pacman (Arch), dnf (Fedora), or apt-get (Ubuntu/Debian) |
| Desktop | GNOME Shell 45+ for the panel extension (optional) |
| Privileges | Root, for the DKMS module, sudoers rules, and systemd units |
curl -fsSL https://raw.githubusercontent.com/Batuhan4/victus-control/main/bootstrap.sh | bashUse this if you want a temporary checkout and the shortest install path.
git clone https://github.com/Batuhan4/victus-control.git
cd victus-control
sudo ./install.shThe wrapper routes to arch-install.sh, fedora-install.sh, or ubuntu-install.sh based on your OS. On GNOME systems it also installs the panel extension for the desktop user automatically.
The installer handles dependency install, user/group creation, DKMS module registration, build + install, and restarts victus-backend.service.
Note
Log out and back in afterwards so your user joins the victus group.
- Validated by contributors on
HP Victus 16-S0046NTwith Fedora 43. - The Fedora installer verifies that the patched
hp_wmimodule is actually active before starting the backend. - If you recently updated the kernel, reboot first so the running kernel matches the installed
kernel-develpackage.
- Contributor-tested on Ubuntu 24.04 LTS (GNOME 46) with an HP Victus 16.
- The installer accepts DKMS-managed
hp_wmimodule layouts used by both/extraand/updates/dkms. - Secure Boot can block the DKMS module from loading. If install succeeds but
hp_wmistill does not load, enroll the MOK key withsudo mokutil --import /var/lib/shim-signed/mok/MOK.deror disable Secure Boot, then reboot.
| Unit | Role |
|---|---|
victus-healthcheck.service |
Runs at boot to ensure the patched hp-wmi DKMS module is built for the current kernel and hp_wmi is loaded before the backend starts |
victus-backend.service |
Starts at boot and stays active, keeping Better Auto and the lighting applied even with no UI client connected |
victus-hotkeyd.service |
A user unit that watches for the dedicated OMEN key and opens the dashboard. See The OMEN key |
The dedicated OMEN key above the keyboard opens Victus Control.
The hp-wmi driver reports that key on its HP WMI hotkeys input device as
KEY_PROG2 (scancodes 0x21a5 and 0x21a8 both map to it). victus-hotkeyd
watches for it and runs victus-control. The app is a single instance, so
pressing the key again raises the window that is already open rather than
stacking up a second dashboard.
It runs as a user service, not a system one, because it has to launch a GUI into the session that owns the display:
systemctl --user status victus-hotkeyd.service
systemctl --user disable --now victus-hotkeyd.service # to turn it offReading the hotkey device needs permission, which
/etc/udev/rules.d/99-victus-hotkey.rules grants to the victus group. That
device only carries the firmware hotkeys — brightness, mic mute, OMEN — never
the typing keyboard, so this does not expose keystrokes. It is deliberately
narrower than adding your user to the input group, which would hand over every
input device including the real keyboard.
If the key does nothing, check in this order:
systemctl --user is-active victus-hotkeyd # should print "active"
ls -l /dev/input/by-path/*event-kbd # device present at all?
journalctl --user -u victus-hotkeyd -n 20 # should say it is watchingThe event node number is not stable across reboots or DKMS rebuilds, so the daemon finds the device by name and re-scans every 5 s if it disappears — a module reload does not require restarting the service.
Launch the GTK app (victus-control) or use the CLI client (test_backend.py).
Press the OMEN key, or pick it from the desktop menu.
Everything lives on one page, with a card per subsystem.
Cooling card — the profile dropdown offers AUTO, Better Auto, MANUAL, MAX:
- Better Auto is enforced by the background service on each boot, keeps fans in manual PWM, and adjusts RPM from temperature and utilisation — ideal for gaming or heavy workloads.
- Manual maps slider positions to calibrated RPM steps; fan 2 honours the 10 s offset automatically.
Fan speed and temperature are shown as analog dials with the digital value under each. The rotor blades turn at a rate derived from the measured RPM, and a stopped fan renders grey rather than merely still. Thermometers and readouts shift cyan → amber → red, crossing at 70 °C and 85 °C.
Note
On boards whose firmware exposes no fan speed targets, manual speed is removed from the card entirely and both MANUAL and Better Auto are dropped from the profile list, since both steer the fans through those targets. AUTO and MAX remain, and the backend leaves such boards on the firmware curve at start-up.
Keyboard card — a switch turns the backlight on and off, a row of style radios picks the lighting mode, and the speed slider or colour picker appears depending on which style is selected. There is no Apply step; changing anything applies it.
Backend status: systemctl status victus-backend.service (logs via journalctl -u victus-backend).
Switch History on in the Cooling card to plot recent telemetry. Off by default; the choice is remembered.
Every trace shares one time axis along the bottom, and each has its own scale drawn as a parallel axis down the left in that trace's colour. Click a legend entry to add or remove a trace and its axis.
| Trace | Source |
|---|---|
| CPU / GPU temperature | the backend's sensors |
| Fan 1 / Fan 2 speed | the backend's sensors |
| CPU load, RAM | /proc, read directly |
| GPU load, VRAM | GET_GPU_USAGE / GET_GPU_VRAM, reusing the nvidia-smi call the fan loop already makes |
Note
Ranges fit the data rather than starting at zero, because a fan at 5300 of 6000 RPM is a flat line on a zero-based axis. Both ends of every axis are labelled, so a non-zero baseline is visible rather than implied.
Tip
Lines are overlaid but scaled independently, so where two lines cross means nothing — it is an artefact of the scaling. Compare each line against its own colour-matched axis, not against the others.
| Effect | Behaviour |
|---|---|
| Static colour | One fixed colour — the classic behaviour |
| Rainbow cycle | The whole keyboard walks the hue wheel |
| Breathe | The current colour fades in and out |
| Flow (river) | On four-zone Omen keyboards the hue travels left-to-right across the zones, so the colour flows along the board. Not offered on single-zone hardware, which has no geometry for it |
Picking Solid swaps the speed slider for a colour picker — the card only shows the control that applies.
- The Speed slider (1–100) sets the cycle rate.
- Picking a static colour stops the animation. Whichever you chose last, an effect or a solid colour, is restored after a reboot.
- The animation runs in the backend, so lighting keeps going after the GUI is closed. It pauses while the backlight is switched off and resumes when it is switched back on.
Tip
Controls that cannot do anything are not shown: Flow is absent on single-zone boards, the colour picker only appears for Solid, and the speed slider only for the animated styles.
For Cinnamon desktops (Linux Mint, and Cinnamon on Ubuntu/Fedora/Arch). Fan mode, keyboard backlight and lighting effects from the panel, next to the battery and volume icons — the same idea as the brightness slider in the battery menu, so the desktop app is not needed for everyday adjustments.
In the panel next to the battery and volume icons — showing CPU temperature at a glance.
| Menu | Fan mode | History |
|---|---|---|
![]() |
![]() |
![]() |
| Live RPM and temperatures, backlight switch and sliders | Mode submenu with the active mode marked | Sparklines, each on its own scale |
| In the menu | |
|---|---|
| 🌀 | Fan mode — Auto, Better Auto, Max (and Manual where the firmware supports it) |
| 📊 | Live telemetry — both fan RPMs and CPU/GPU temperature |
| ⌨️ | Keyboard backlight — on/off switch and a brightness slider |
| 🌈 | Lighting effect — Static, Rainbow, Breathe (and Flow on four-zone boards) with a speed slider |
The panel itself shows CPU temperature by default; right-click → Configure to show fan RPM instead, or just the icon.
bash cinnamon-applet/install.shinstall.sh runs this automatically when Cinnamon is detected. If the applet does
not appear, restart Cinnamon with Alt+F2, then r, Enter.
Note
Controls that the hardware cannot honour are hidden rather than shown inert: Manual fan mode is absent where the firmware refuses fan speed targets, and Flow is absent on single-zone keyboards.
Tip
The applet polls slowly (10 s) while its menu is closed and only speeds up to 2 s while you have it open, so it costs very little when you are not using it. The interval is configurable in its settings.
Quick access to fan and keyboard controls from the top panel.
| Feature | |
|---|---|
| 🌀 | Fan mode control — AUTO, Better Auto, MANUAL, MAX |
| 📊 | Manual fan speed — per-fan sliders with 8 RPM steps (visible in MANUAL mode) |
| ⌨️ | Keyboard RGB — 10 colour presets and a brightness slider |
| 🌡️ | Live status — real-time CPU temperature and fan RPM |
sudo ./install.sh
gnome-extensions enable victus-control@victusinstall.sh installs the extension automatically on GNOME systems. You only need the manual gnome-extensions enable ... step after install or after logging back in.
Install the extension by itself
cd gnome-extension
bash ./install.sh
gnome-extensions enable victus-control@victusRequirements: GNOME Shell 45+, victus-backend.service running. On Ubuntu GNOME and other GNOME desktops the extension can be installed separately as long as the backend socket is available.
See gnome-extension/README.md for detailed documentation.
meson setup build --prefix=/usr
meson compile -C build
sudo meson install -C build- Smoke test (requires the backend running):
python test_backend.py - The installer fetches
hp-wmi-fan-and-backlight-control; it is git-ignored to keep the repo lean.
Fans ignore commands
Ensure the DKMS module is loaded:
dkms status | grep hp-wmi-fan-and-backlight-control
modprobe --show-depends hp_wmi | tail -n1The last command should point at the DKMS-built hp-wmi.ko under /updates/dkms/ on Arch or /extra/ on other distros.
Fans stuck at one speed after the service starts
A few boards report software fan support but have a BIOS that ignores per-RPM targets. Better Auto then switches the fans to MANUAL and cannot steer them, leaving them pinned with the firmware curve disabled.
Check with the backend in Better Auto and the machine under load:
grep . /sys/devices/platform/hp-wmi/hwmon/hwmon*/fan*_input
journalctl -u victus-backend -n 20If the RPM readings sit at one value while the better-auto: lines in the log keep raising the level, your board is affected. Keep the keyboard lighting and leave the fans to the firmware:
sudo mkdir -p /etc/systemd/system/victus-backend.service.d
printf '[Service]\nEnvironment=VICTUS_NO_FAN_CONTROL=1\n' | \
sudo tee /etc/systemd/system/victus-backend.service.d/no-fan-control.conf
sudo systemctl daemon-reload && sudo systemctl restart victus-backendWith that set the backend puts the driver back into AUTO on every start, refuses fan commands from any client, and the app's cooling card shows fan speeds and temperatures only.
Permission errors
Confirm victus group membership, then re-run the installer:
groups $USER
sudo usermod -aG victus $USERLog out and back in for the group change to take effect.
Socket missing
sudo systemd-tmpfiles --create
sudo systemctl restart victus-backend.serviceGNOME extension missing after install
Log out and back in once, then:
gnome-extensions enable victus-control@victusUninstall
sudo systemctl disable --now victus-backend
sudo dkms remove hp-wmi-fan-and-backlight-control/$(dkms status -m hp-wmi-fan-and-backlight-control | sed -n 's#.*/\([^,]*\),.*#\1#p' | head -n1) --allSubstitute the version shown by dkms status if the command above does not resolve it.
See AGENTS.md for coding style, testing, and PR expectations. Hardware validation notes are very welcome in PR descriptions — this project lives on contributors reporting what does and does not work on their board.
GPLv3. See LICENSE for the full text.




