Last Updated on June 18, 2026 by Thiago Crepaldi
You compiled your proprietary Nvidia drivers natively on Proxmox 9.2 (Debian Trixie / Kernel 7.x) using our previous post, and you verified that your host recognizes the silicon. But letting your hypervisor have all the fun may be a waste of pure compute horsepower in certain applications, say when you want to run a Kubernetes within your Proxmox Hypervisor. In this post, we will remove the GPU from the host OS and inject it directly into a headless Ubuntu virtual machine. If you have multiple GPUs, like me, you can leave a couple GPUs under Proxmox control and reserve a couple for passthrough to your VM.
To make sure we can debug things, we will utilize a multi-console design to always have access to any boot or otherwise error message. We will configure the VM to simultaneously support the Proxmox Web UI console, a host-level serial terminal interface, and also direct PCIe passthrough for your GPU workloads.
Step 1: Isolate a Specific GPU on the Proxmox Host
Before your Ubuntu VM can claim the GPU, we have to force the Proxmox host kernel to completely let go of its hardware lock.
If you are running a single GPU, you can usually isolate it by its global hardware IDs. However, if you are running identical dual graphics cards (like two Nvidia Titan V cards), both devices will share the exact same hardware Hex IDs. Running a blanket device-ID lock will accidentally isolate both cards at once. To target just one of your identical cards, we have to isolate it by its physical PCI Bus Address.
1.1 Enable IOMMU in the Bootloader
Open your Proxmox boot configuration. If your setup uses GRUB, edit /etc/default/grub and ensure Intel or AMD virtualization handles passthrough translation correctly:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"Save the file and commit the changes to your bootloader:
sudo update-grub
1.2 Map Your Physical PCI Bus Paths
Run the following command to see exactly where your identical cards sit on the motherboard layout:
lspci -nn | grep -i nvidiaYour output will look like this:
03:00.0 VGA compatible controller [0300]: NVIDIA Corporation GV100 [TITAN V] [10de:1d81] (rev a1)
03:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f2] (rev a1)
04:00.0 VGA compatible controller [0300]: NVIDIA Corporation GV100 [TITAN V] [10de:1d81] (rev a1)
04:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10f2] (rev a1)Notice that while the Hex IDs (10de:1d81) are identical, the bus paths are distinct (03:00.0 vs 04:00.0). We are going to isolate the card on Bus 04 for our VM, leaving Bus 03 completely untouched so the Proxmox host can continue running its native graphics workloads.
1.3 Enforce a Low-Level Driver Override via Systemd
Because identical cards are easily grabbed by the native host driver during early initialization, we must use an initialization script to intercept Bus 04 before the main driver registers it.
Create a dedicated script at /etc/initramfs-tools/scripts/init-top/vfio-override.sh
#!/bin/sh
# Force the card on Bus 04 to bind to vfio-pci instead of native drivers
DEVS="0000:04:00.0 0000:04:00.1"
for DEV in $DEVS; do
echo "vfio-pci" > /sys/bus/pci/devices/$DEV/driver_override
doneMake the script executable:
sudo chmod +x /etc/initramfs-tools/scripts/init-top/vfio-override.shNow, force Proxmox to refresh its initial ramdisk configuration so this rule runs during the absolute earliest stage of the boot cycle:
sudo update-initramfs -u -k all1.4 Register the GUI Resource Map
With the low-level kernel block set up, we want to expose this card cleanly to the Proxmox UI. This creates a friendly alias we can reference during VM creation, abstracting away raw hardware IDs.
- Navigate to Datacenter -> Resource Mappings -> PCI.
- Click Add and name your map ID
nvidia-passthrough-card. - Choose the path for your isolated card (
04:00.0).
Reboot your Proxmox host. Once it comes back up, execute nvidia-smi on the host. You will see that only GPU 0 (Bus 03) registers in the host panel. The card on Bus 04 is successfully hidden away, waiting for our virtual infrastructure.
Step 2: Spin Up the Headless Ubuntu VM (The Cloud-Image Way)
To ensure our Cloud-Init environment boots successfully without hitting a UEFI dead end or throwing SSH key initialization errors, we will download the official, pre-configured Ubuntu 24.04 LTS Cloud Image directly onto the Proxmox host and use the CLI tool to inject it into our virtual hardware shell.
2.1 Download the Cloud Image on the Host Terminal
SSH into your Proxmox host shell and grab the official minimal runtime image from Canonical:
wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img2.2 Create the Hardware Shell via Web Wizard
Click Create VM in the top-right corner of the Proxmox 9.2 UI and step through the tabs with these precise settings:
- General: Assign a unique VM ID (e.g.,
100) and name itk3s-node-01. - OS: Select Do not use any media.
- System:
- Graphic card: Select Standard VGA (
std). This keeps the Proxmox web VNC interface active alongside our upcoming hardware mappings. - Machine: Change this to q35. Crucial for stable PCIe mapping topologies.
- BIOS: Switch to OVMF (UEFI). Select your local storage pool to host the EFI variables disk.
- TPM Storage: Check Add TPM, set the version to v2.0, and assign it to your local storage.
- QEMU Guest Agent: Check this box. This allows clean, automated runtime orchestration via the host API.
- SCSI Controller: Change to VirtIO SCSI Single.
- Graphic card: Select Standard VGA (
- Disks: Delete the default disk that Proxmox automatically populates. Leave this tab completely empty.
- CPU: Allocate a minimum of 4 vCPUs. Set the Type to host. This forces the hypervisor to present your exact physical instruction sets directly to the guest VM.
- Memory: Allocate a minimum of 8GB (8192 MB) of RAM and uncheck “Ballooning Device”. Container runtimes manage their own memory structures; dynamic ballooning can cause instant out-of-memory kernel panics.
- Network: Set the Model type to VirtIO (Intel MTU optimized) and point the bridge to your primary local LAN interface (
vmbr0).
Click Finish to construct the bare hardware shell.
2.3 Import the Disk and Inject the Multi-Console Pipeline
Before starting the VM for the first time, run these commands in sequence on your Proxmox host terminal to flash the OS partition map, add the physical serial interface component, and provision the Cloud-Init boundaries:
# 1. Import the downloaded Ubuntu Cloud Image directly into your VM storage
qm importdisk 100 noble-server-cloudimg-amd64.img local-lvm
# 2. Attach the newly imported image to your VM as scsi0
qm set 100 --scsi0 local-lvm:vm-100-disk-2,discard=on,iothread=1
# 3. Grow the operating system partition footprint to your desired size (e.g., 128GB)
qm resize 100 scsi0 +126G
# 4. Attach a dedicated Cloud-Init hardware drive on the IDE bus
qm set 100 --ide0 local-lvm:cloudinit
# 5. Attach the physical virtual serial port adapter hardware to the VM
qm set 100 --serial0 socket
# 6. Explicitly force QEMU to prioritize booting from scsi0
qm set 100 --boot order=scsi0Now, return to the Proxmox Web UI, click on your VM, navigate to the Cloud-Init panel, populate your administrative username, password, SSH public key, and your Static IP configuration (e.g., 192.168.1.12/24), then click Regenerate Image.
2.4 The First Launch (Monitoring Progress)
Because we configured a robust multi-console layout, you can watch the first-boot sequence straight from your host terminal:
qm start 100 && qm terminal 100đź’ˇ PRO-TIP: Don’t Panic at First Boot Logs When you first hook into the console or serial terminal, you will see a rapid wall of text from the UEFI firmware (
BdsDxe), followed by a quickReset Systemand an ominous-looking line:error: prohibited by secure boot policy.This is entirely normal. The virtual motherboard is simply mapping out the new SCSI drive paths and enforcing your security policy. As long as you see it proceed to print
EFI stub: UEFI Secure Boot is enabled, the system has successfully negotiated the boot sequence and is loading the Ubuntu kernel cleanly. To exit the serial console terminal at any time, simply pressCtrl + O.
Step 3: Configure the Proxmox VM Hardware Layout
With your base Ubuntu VM successfully provisioned and verified with a real boot partition, it’s time to connect the virtual architecture to our isolated physical silicon.
3.1 Attach the Mapped PCI Device
Go to your VM’s Hardware settings. Click Add -> PCI Device and choose Mapped Device. Select your nvidia-passthrough-card map alias we registered in Step 1.4. Ensure you toggle the following flags:
- Primary GPU: Enabled. This forces the VM’s underlying execution layer to leverage the TITAN V’s VBIOS as the baseline primary console display output immediately on boot. This ensures the headless driver initializes cleanly without throwing memory mapping errors.
- ROM-Bar: Enabled. This passes the card’s native physical firmware binary down to the guest.
- PCI-Express: Enabled. Crucial for performance—it forces the hypervisor to present the hardware as a native PCIe link instead of an unaccelerated legacy device.
Step 4: Guest-Side Provisioning (Ubuntu Server)
Fire up your Ubuntu guest VM by clicking Start or running qm start 100 on the host.
4.1 Log in via Your Preferred Console Interface
Because we configured a zero-compromise multi-console display system, you have three independent ways to access your new machine:
- The Web-UI Way: Click on the VM’s Console tab in Proxmox to view the machine over Standard VGA (
std). - The CLI-Terminal Way: Run
qm terminal 100directly from your Proxmox host shell to connect via the virtual serial port interface. - The SSH Way: Open a native terminal on your laptop or desktop and connect straight over the local network:Bash
ssh thiago@192.168.1.12
4.2 Configure the Linux Kernel for Both Consoles
To ensure that all boot sequences, kernel messages, and login prompts mirror gracefully across both the Proxmox web console (`std`) and the command-line serial interface (`qm terminal`), log into your VM and open the GRUB configuration layout:
sudo vim /etc/default/grubFind the GRUB_CMDLINE_LINUX_DEFAULT line and modify it to map out both the video subsystem console (tty0) and the primary serial subsystem interface (ttyS0):
GRUB_CMDLINE_LINUX_DEFAULT="quiet console=tty0 console=ttyS0,115200"Save the file and force the guest OS to commit the boot parameters:
sudo update-grub4.3 Verify the Pipeline Link
Verify that the Linux kernel inside the VM successfully detects the passed hardware link over its PCIe lane:
lspci -nnk | grep -i nvidiaIf your card details populate correctly, your Proxmox-to-VM hardware bridge is perfectly intact.
4.4 Install the Production Headless Server Driver
Because this VM will run containerized apps, databases, or orchestrators, skip the heavy desktop display packages and deploy the clean production server driver:
sudo apt update
sudo apt install -y nvidia-headless-550-server nvidia-utils-550-server⚠️ CRITICAL SECURE BOOT NOTE: Because we enabled OVMF (UEFI) and a TPM 2.0 chip during step 2.2, Ubuntu’s package manager will detect that Secure Boot is active mid-installation. A full-screen pink TUI prompt will interrupt the install asking you to configure a Machine Owner Key (MOK) Password.
Create a simple, temporary password here (e.g.,
12345678) and write it down. You will need to type this exact password on your screen in the next step when the machine reboots.
4.5 The First Reboot & MOK Enrollment
Now, we must commit the drivers and authorize the kernel modules through the UEFI framework.
- Issue a system restart command:
sudo reboot- Instantly drop into your Proxmox web console helper or run `qm terminal 100` from the host.
- Upon initialization, you will be met with a blue screen titled **Shim UEFI Key Management**.
- Press any key to enter the menu, then select **Enroll MOK** -> **Continue**.
- When prompted to confirm, select **Yes**, and then input the temporary MOK password you just created during the driver installation in step 4.4.
- Once the keys are enrolled, select **Reboot** to exit the utility.
4.6 The Moment of Truth
Once the system initializes back into user space, log back into your session via SSH and query the Nvidia system management interface:
nvidia-smiYou will be greeted by the classic system monitoring grid, displaying your specific GPU model, current operating temperatures, and available VRAM layout. Your hardware pipeline is officially running at native, bare-metal speeds!

