One script to diagnose, repair and bootstrap NVIDIA graphics, MUX switching and fan control on Ubuntu for ASUS ROG / TUF / Zephyrus laptops.
If your NVIDIA GPU is installed correctly and still doesn't work on Ubuntu, the cause is probably a single orphaned config file that no package owns and that reinstalling the driver cannot remove. This script finds it, fixes it, and verifies the result.
$ nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver.
Make sure that the latest NVIDIA driver is installed and running.
$ journalctl -u supergfxd
[ERROR supergfxctl::controller] Modprobe error: modprobe nvidia_drm failed:
could not find module by name='off'
could not insert 'off': Unknown symbol in module, or unknown parameter
$ lspci -nnk | grep -A3 NVIDIA
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation ... [10de:2757]
Kernel modules: nvidia_drm, nvidia <-- note: no "Kernel driver in use"
Plus any of: dkms status says installed, Secure Boot is enrolled correctly, you've
purged and reinstalled nvidia-driver-* several times, and nothing helped.
That's this bug.
Ubuntu ships nvidia-prime / gpu-manager — Canonical's own GPU switcher. Running
prime-select intel, or clicking "Intel (Power Saving Mode)" in NVIDIA Settings →
PRIME Profiles, writes this file:
/usr/lib/modprobe.d/blacklist-nvidia.conf
blacklist nvidia
blacklist nvidia-drm
blacklist nvidia-modeset
alias nvidia off <-- there is no kernel module called "off"
alias nvidia-drm off
alias nvidia-modeset off
Every modprobe nvidia now resolves to a module named off, which does not exist. Nothing
binds to the GPU. nvidia-smi fails. And critically:
prime-selectgenerates that file, so no package owns it.apt purge '^nvidia-.*'provably cannot remove it. Neither can reinstalling the driver.
It is also baked into your initramfs, so deleting it alone doesn't survive a reboot, and
gpu-manager regenerates it at boot unless masked. That is why the usual advice — reinstall
the driver, re-enroll Secure Boot keys, rebuild DKMS — never works.
On ASUS laptops this is compounded by nvidia-prime and supergfxd being two GPU switchers
fighting over one GPU. asus-linux's own docs say to remove PRIME
managers first; almost no Ubuntu guide does.
git clone <this-repo> && cd asus-nvidia-setup
chmod +x asus-nvidia-setup.shRun it as your normal user — never with
sudo. It callssudoper-command and will prompt for your password. Running the whole script as root installs Rust into/root/.cargoand leaves root-owned build trees in$HOME.
./asus-nvidia-setup.shThis is always safe. Run it any time. It never writes anything without --fix or --install.
./asus-nvidia-setup.sh --fixRemoves the blacklist, loads the module, masks gpu-manager, rebuilds the initramfs.
Prompts before each change.
./asus-nvidia-setup.sh --install --hardenInstalls the NVIDIA driver, then builds and installs asusctl + supergfxctl from the
official asus-linux sources. Budget 20–40 minutes for the compile.
./asus-nvidia-setup.sh --reinstall --hardenWipes an existing source install (including the files upstream's own make uninstall
misses) and rebuilds from scratch. Your /etc/asusd/ fan curves and /etc/supergfxd.conf
are preserved — nothing in the removal touches /etc.
| Flag | Effect |
|---|---|
| (none) | Read-only diagnosis. Safe. Exits 0 if healthy. |
--fix |
Repair configuration on an existing install |
--install |
Full bootstrap on a fresh Ubuntu |
--reinstall |
Wipe the existing source install and rebuild clean |
--harden |
Neutralise prime-select via dpkg-divert so it can't break things again |
--undo-harden |
Restore prime-select |
--yes / -y |
No prompts |
--driver nvidia-driver-NNN |
Pin a specific driver version |
Reboots are always announced, never taken automatically.
- NVIDIA dGPU present, and whether anything is actually bound to it
- DKMS built for the running kernel
- Secure Boot: whether the module is signed and whether that key is enrolled
- The orphaned
blacklist-nvidia.conf, from every path it can live in - Live
modprobe --showconfig, to catch blocks from sources it didn't predict gpu-managermaskedsupergfxdrunning; current and available graphics modes- Whether
rog-control-centerwas built Wayland-only (see below) - dGPU actually reaching D3cold (~0 W) at idle
- Platform profile, and whether it's holding your fans at an unnecessary floor
rog-control-center built Wayland-only. A plain make defaults to X11 ?= 0, producing
a GUI that panics with No backends configured on any X11 session — including the one
Ubuntu's GDM selects by default once an NVIDIA driver is bound. Build with:
make X11=1This script does that automatically. Symptom of the broken build:
Error initializing winit event loop: neither WAYLAND_DISPLAY nor WAYLAND_SOCKET is set;
note: enable the `winit/x11` feature to support X11
Fixing NVIDIA moves you from Wayland to X11. GDM's 61-gdm.rules prefers Xorg whenever
an NVIDIA driver binds (except two whitelisted Dell SKUs). It writes
PreferredDisplayServer=xorg — not WaylandEnable=false — so Wayland is still selectable
via the gear icon at the login screen.
nvidia-smi wakes the GPU. It must power the GPU up to answer, so it reports D0 and
tens of watts even when the GPU was in D3cold a moment earlier. Never poll it in a loop or
run a GPU monitor widget — that pins the GPU awake and creates the very problem you're
trying to avoid. Read /sys/bus/pci/devices/<addr>/power_state instead; it doesn't wake it.
Platform profile, not the GPU, is usually your fan noise. On performance the EC holds a
fan floor (~18% at 30 °C) and lets the CPU draw its full sustained power. asusctl profile set -a Balanced is the fix. Fan curves stay firmware-controlled — that's ASUS's own tuning,
the same one Armoury Crate uses, and you should leave it alone.
| Armoury Crate | Linux | Firmware attribute |
|---|---|---|
| Eco | supergfxctl -m Integrated |
dgpu_disable=1 |
| Standard | supergfxctl -m Hybrid |
gpu_mux_mode=1 |
| Ultimate | supergfxctl -m AsusMuxDgpu |
gpu_mux_mode=0 |
Note that prime-select is not a MUX switcher — it changes software render routing, not
the physical display wiring. Real MUX switching needs vendor firmware access.
For ML/CUDA users: stay in Hybrid. The iGPU drives your display, the dGPU sits in
D3cold at ~0 W, and it wakes in about a second when CUDA asks for it — giving you
essentially the entire VRAM. Integrated powers the dGPU off completely and takes CUDA
with it.
- ASUS ROG Zephyrus M16 (GU604VY), i9-13900H + RTX 4090 Laptop
- Ubuntu 24.04.4 LTS, kernel 7.0.0-31-generic, GNOME 46
- NVIDIA 595.84, Secure Boot enabled with an enrolled MOK
- asusctl / supergfxctl 6.3.8 / 5.2.7
Should work on any ASUS ROG/TUF laptop on Ubuntu 22.04+. The NVIDIA/Optimus half applies to any Ubuntu laptop with an NVIDIA dGPU, ASUS or not.
The blacklist bug and its fix are vendor-neutral — the script handles that part anywhere. True MUX switching is vendor-specific firmware:
- Lenovo Legion → legion-linux
- Generic Optimus → EnvyControl
asusctl and supergfxctl are by the asus-linux project
(Luke Jones). This script only installs and configures them correctly on Ubuntu, which
upstream does not officially support.
MIT — see LICENSE.