Installing NVIDIA Graphics Card Drivers on Proxmox VE 9 (manual procedure)

Guides~30 min

Manual installation and configuration of NVIDIA drivers on a Proxmox VE 9 host, plus the LXC wiring needed to expose the GPU to one or more containers. Covers driver install, persistence service, optional NVENC patch and the per-container setup.

Note

This is the manual procedure preserved as a reference. For most users the recommended path is the automated ProxMenux flow: Install NVIDIA Drivers (Host) in the GPUs and Coral-TPU menu, and Add GPU to LXC (or Add GPU to VM) for the per-guest wiring. The automated flow handles the same steps documented here (with extra safety checks: kernel-headers compatibility, IOMMU validation, VFIO conflict resolution). This page is for operators who want to understand each command, or who need to deviate from the standard flow.

Targeted at Proxmox VE 9 (Debian Trixie). PVE 7 (Bullseye) and PVE 8 (Bookworm) are no longer covered.

What you'll do

  1. Prepare the Proxmox VE 9 host (blacklist nouveau, repos, prerequisites).
  2. Install the NVIDIA driver on the host.
  3. Install the NVIDIA persistence service.
  4. (Optional) Apply the keylase patch to lift the NVENC concurrent-session limit on consumer GPUs.
  5. Wire the GPU into one or more LXC containers and install the matching driver inside each.

1. Prepare the host (PVE 9)

1.1 Blacklist nouveau

Check whether the open-source nouveau driver is already blacklisted:

cat /etc/modprobe.d/blacklist.conf

If blacklist nouveau does not appear, add it and reboot:

echo "blacklist nouveau" '>>' /etc/modprobe.d/blacklist.conf
reboot
Blacklist check

1.2 Verify repositories (PVE 9 / Trixie)

If you ran the ProxMenux Post-Install script (or any other Proxmox post-install tooling), the repositories are already in place — skip this step.

Otherwise, on a vanilla PVE 9 install with no enterprise subscription:

nano /etc/apt/sources.list.d/proxmox.sources

Make sure it contains the no-subscription source for Trixie:

Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg

And the Debian sources at /etc/apt/sources.list.d/debian.sources:

Types: deb
URIs: http://deb.debian.org/debian/
Suites: trixie trixie-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: http://security.debian.org/debian-security/
Suites: trixie-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

1.3 Update the system and install prerequisites

apt update && apt dist-upgrade -y

Install the build tools and kernel headers needed to compile the NVIDIA kernel module:

apt-get install -y git
apt-get install -qqy pve-headers-$(uname -r) gcc make

2. Install the NVIDIA driver on the host

2.1 Pick a driver version

Check the latest stable driver:

https://download.nvidia.com/XFree86/Linux-x86_64/latest.txt

Heads up

If you plan to apply the NVENC patch (step 4), verify the patch supports your chosen driver version first: github.com/keylase/nvidia-patch

Replace latest.txt in the URL with the version number to find the installer file ending in .run. The full driver list is at:

https://download.nvidia.com/XFree86/Linux-x86_64/
NVIDIA driver download

Throughout the rest of this guide, replace <VERSION> with the actual version (for example 580.95.05).

2.2 Download and run the installer

mkdir -p /opt/nvidia
cd /opt/nvidia
wget https://download.nvidia.com/XFree86/Linux-x86_64/'<'VERSION'>'/NVIDIA-Linux-x86_64-'<'VERSION'>'.run
chmod +x NVIDIA-Linux-x86_64-'<'VERSION'>'.run

First pass — this disables nouveau and prepares the system:

./NVIDIA-Linux-x86_64-'<'VERSION'>'.run --no-questions --ui=none --disable-nouveau
reboot

After the host comes back, run the installer again to compile and install the kernel module:

/opt/nvidia/NVIDIA-Linux-x86_64-'<'VERSION'>'.run --no-questions --ui=none

2.3 Load NVIDIA modules at boot

Edit the modules-load configuration:

nano /etc/modules-load.d/modules.conf

Add the VFIO and NVIDIA modules:

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
nvidia
nvidia_uvm

Save (Ctrl+X) and rebuild initramfs:

update-initramfs -u -k all

2.4 Create udev rules

So that /dev/nvidia* device nodes are created when the modules load:

nano /etc/udev/rules.d/70-nvidia.rules
# /etc/udev/rules.d/70-nvidia.rules
# Create /dev/nvidia0, /dev/nvidia1 ... and /dev/nvidiactl when nvidia module is loaded
KERNEL=="nvidia", RUN+="/bin/bash -c ''/usr/bin/nvidia-smi -L''"

# Create the CUDA node when nvidia_uvm CUDA module is loaded
KERNEL=="nvidia_uvm", RUN+="/bin/bash -c ''/usr/bin/nvidia-modprobe -c0 -u''"

Save (Ctrl+X).

3. NVIDIA driver persistence service

The persistence daemon keeps the GPU initialised between uses, which avoids the latency hit and occasional state loss that happens when the kernel module is loaded and unloaded repeatedly:

cd /opt/nvidia
git clone https://github.com/NVIDIA/nvidia-persistenced.git
cd nvidia-persistenced/init
./install.sh
reboot

Verify the driver is loaded and the service is running after reboot:

nvidia-smi
NVIDIA SMI output
systemctl status nvidia-persistenced
NVIDIA persistence service status

4. (Optional) Lift the NVENC concurrent-session limit

Consumer NVIDIA GPUs ship with a hardcoded limit on the number of simultaneous NVENC encoding sessions (typically 3, 5 or 8 depending on generation). The keylase patch removes that restriction. Useful when running Plex / Jellyfin / Frigate transcoding workloads.

cd /opt/nvidia
git clone https://github.com/keylase/nvidia-patch.git
cd nvidia-patch
./patch.sh
NVIDIA patch application

The patch must be re-applied after every driver update. The keylase repo also includes patch-fbc.sh for the FBC (frame buffer capture) limit if you need it.

5. Configure an LXC container to use the GPU

5.1 Identify the device numbers

On the host:

ls -l /dev/nv*
NVIDIA device list

Note the major numbers — they vary between systems. Typical values:

DeviceTypical major
/dev/nvidia0, /dev/nvidiactl195
/dev/nvidia-uvm, /dev/nvidia-uvm-tools509 (varies)
/dev/dri/*226
/dev/nvidia-modeset195 (shares with nvidia)

5.2 Edit the LXC config

Stop the container first if it's running. Open its config file (replace <CTID> with the container ID):

nano /etc/pve/lxc/'<'CTID'>'.conf

Comment out any pre-existing lxc.cgroup2.devices.allow or /dev/dri lines that conflict, then append the NVIDIA wiring (adjust the major numbers to match what ls -l /dev/nv* showed on your host):

lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 509:* rwm
lxc.cgroup2.devices.allow: c 10:* rwm
lxc.cgroup2.devices.allow: c 238:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-modeset dev/nvidia-modeset none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
lxc.mount.entry: /dev/nvram dev/nvram none bind,optional,create=file
LXC configuration

Save (Ctrl+X) and start the container.

5.3 Install the driver inside the container

Important

This part runs inside the container, not on the host.

The kernel module is already loaded by the host — the container only needs the userland libraries that match the same driver version:

mkdir -p /opt/nvidia
cd /opt/nvidia
wget https://download.nvidia.com/XFree86/Linux-x86_64/'<'VERSION'>'/NVIDIA-Linux-x86_64-'<'VERSION'>'.run
chmod +x NVIDIA-Linux-x86_64-'<'VERSION'>'.run
./NVIDIA-Linux-x86_64-'<'VERSION'>'.run --no-kernel-module

Accept the defaults at every prompt.

NVIDIA driver installation

5.4 Verify inside the container

nvidia-smi
NVIDIA SMI in LXC
ls -l /dev/nv*
NVIDIA devices in LXC

You should see the GPU listed and the device nodes mounted into the container's filesystem.

5.5 Confirm a real workload picks up the GPU

For Plex / Jellyfin, transcode a video and check the dashboard / logs — hardware-accelerated transcoding is now active.

Plex using NVIDIA GPUPlex using NVIDIA GPU - active session

To wire the GPU into another container, repeat section 5 for each additional CTID. The driver install inside the container only needs to be done once per container.

6. (Optional) NVIDIA Docker inside an LXC

If the container runs Docker and you want containers-inside-the-container to use the GPU, install nvidia-docker2. From inside the LXC:

wget https://raw.githubusercontent.com/MacRimi/manuales/main/NVIDIA/nvidia-docker.sh
chmod +x nvidia-docker.sh
./nvidia-docker.sh

The script handles the repository setup, package install and Docker daemon configuration in one go.

Troubleshooting

  • nvidia-smi on the host shows the GPU, but inside the container it errors with "No devices found": the driver versions don't match. Re-download the same <VERSION> inside the container and run with --no-kernel-module.
  • Driver compile fails on the host with "No precompiled kernel interface was found": kernel headers are missing or out of sync. Re-run apt-get install pve-headers-$(uname -r) and confirm uname -r matches the running kernel.
  • NVENC sessions still capped after applying the patch: the patch was overwritten by a driver update. Re-run ./patch.sh from /opt/nvidia/nvidia-patch.
  • GPU stops responding after a few hours of idle: persistence daemon isn't running. Check with systemctl status nvidia-persistenced and start / enable it.
  • Container starts but ls /dev/nv* shows nothing: the major numbers in the LXC config don't match the host's. Re-run ls -l /dev/nv* on the host and adjust the lxc.cgroup2.devices.allow lines accordingly.

Sponsor

If you would like to support the project.

Support me on Ko-fi

Connect

Join the community discussions on GitHub to get help, share ideas, and contribute to the project. Every idea is welcome!

Join the Discussion

ProxMenux, an open-source and collaborative project by MacRimi.