Prevent Electron apps from waking NVIDIA dGPU on hybrid laptops (LD_PRELOAD)
libnvidia-hide is a userspace NVIDIA-hiding solution for hybrid GPU laptops.
It consists of:
- a shared library (
libnvidia-hide.so) that hides NVIDIA devices from a process usingLD_PRELOAD - a launcher binary (
nvidia-hide) that applies the library per application, without requiring a global preload
The goal is to prevent Electron / Chromium-based applications (VS Code, Discord, Slack, etc.) from waking the NVIDIA dGPU unnecessarily, while keeping:
- full filesystem access
- portals, camera, microphone, clipboard
- normal desktop integration
No sandboxing, cgroups, udev rules, kernel patches, or driver removal are involved.
On modern hybrid GPU laptops, Electron applications frequently:
- enumerate all DRM devices (
/dev/dri/card*,renderD*) - load NVIDIA GBM / GLX / Vulkan libraries
- parse NVIDIA Vulkan ICDs and implicit layers
- probe PCI configuration space for GPUs
- open
/dev/nvidia*character devices
Any of the above is enough to runtime-resume the NVIDIA GPU, causing:
- unnecessary power usage
- slow application startup
- possibly broken power management
Environment variables such as:
DRI_PRIME=0__GLX_VENDOR_LIBRARY_NAME=mesa- Vulkan loader overrides
are not sufficient in many real-world cases.
libnvidia-hide prevents NVIDIA from being considered at discovery time, not just at usage time.
- Scans
/sys/class/drm/*/device/vendor - Identifies NVIDIA DRM nodes by vendor ID (
0x10de) - Resolves corresponding PCI BDFs dynamically
- No hardcoded card numbers or assumptions
Filters NVIDIA-related entries from:
/dev/dev/dri/dev/dri/by-path
As a result, Electron never “sees” NVIDIA devices during probing.
Prevents access to:
- NVIDIA
renderD*nodes /dev/nvidia*character devices
Prevents loading of:
libGLX_nvidia.sonvidia-drm_gbm.solibnvidia-*
This stops Chromium / Electron from selecting NVIDIA paths early.
Blocks reads of:
/sys/.../<NVIDIA_BDF>/config
This avoids runtime PM wakeups even when character devices are blocked.
- Every Electron subprocess loads the library
- Initialization happens once per process
- Repeated debug output is expected and correct
- No sandboxing
- No cgroup device filtering
- No permission or group changes
- No driver blacklisting
- No kernel patches
- No system-wide preload unless you explicitly choose to do so
- Does not work with Flatpak / Snap applications
LD_PRELOADis blocked by design in sandboxed environments
This repository from now on ships source only. You are expected to build locally.
gccglibc(forlibdl)
gcc -O2 -fPIC -Wall -Wextra -std=c11 \
-shared -ldl \
-o libnvidia-hide.so libnvidia-hide.c
gcc -O2 -Wall -Wextra -std=c11 \
-o nvidia-hide nvidia-hide.c(Optional) install locations:
install -Dm755 libnvidia-hide.so /usr/local/lib/libnvidia-hide.so
install -Dm755 nvidia-hide /usr/local/bin/nvidia-hideAlternatively, you can use the included makefile, and run:
make
sudo make installnvidia-hide run -- codeThis:
- sets
LD_PRELOADonly for that process tree - automatically applies policy (allowlist / denylist)
- avoids polluting your entire desktop session
If you want to preload manually:
LD_PRELOAD=/path/to/libnvidia-hide.so codeThe library decides whether it should be active per process by inspecting /proc/self/exe.
Location:
~/.config/nvidia-hide/allowlist
~/.config/nvidia-hide/denylist
Format:
- one glob pattern per line
#comments supported- empty lines ignored
Matching rules:
- patterns without
/match the executable basename - patterns with
/match the full executable path
Examples:
# allow only VS Code
code
*/visual-studio-code/code
# never hide NVIDIA from these
grep
bash
# allow discord
echo "discord" > ~/.config/nvidia-hide/allowlist
# deny discord
echo "discord" > ~/.config/nvidia-hide/denylist
- If an allowlist exists, the library is inactive unless matched
- Denylist always wins
If policy results in active=0, the library becomes a true no-op:
- no DRM probing
- no sysfs scanning
- no side effects
Instead of files, you may use env vars (colon-separated globs):
LIBNVIDIAHIDE_ALLOWLIST="code:electron*"
LIBNVIDIAHIDE_DENYLIST="bash:grep"Enable verbose logging:
LIBNVIDIAHIDE_DEBUG=1 nvidia-hide run -- codeExample output:
[libnvidia-hide] policy: exe=/opt/visual-studio-code/code
[libnvidia-hide] policy: active=1 (has_allow=1 allow_match=1 deny_match=0)
[libnvidia-hide] init: nvidia_nodes=2 nvidia_bdfs=1
[libnvidia-hide] node: card1
[libnvidia-hide] node: renderD129
[libnvidia-hide] bdf: 0000:01:00.0
watch -n0.5 cat /sys/bus/pci/devices/0000:01:00.0/power/runtime_statusExpected:
suspended
sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat
/str(args->filename) ~ "nvidia|renderD"/
{ printf("%s %d %s\n", comm, pid, str(args->filename)); }'With libnvidia-hide active, no NVIDIA paths should appear.
This is a userspace-only workaround:
- no kernel patches
- no driver removal
- no power-management hacks
You essentially force electron to behave like a good citizen.