Proxmox 9 mit GPU für eine vLLM-VM konfigurieren

Eigene Sprachmodelle souverän im eigenen Rechenzentrum betreiben – ohne Cloud-Zwang. Diese Anleitung zeigt Schritt für Schritt, wie Sie unter Proxmox VE 9 eine NVIDIA-GPU per IOMMU/VFIO an eine virtuelle Maschine durchreichen und darin vLLM als hochperformanten, OpenAI-kompatiblen LLM-Server betreiben.

Das Wichtigste vorab

  • Plattform: Proxmox VE 9.0 basiert auf Debian 13 „Trixie“, Linux-Kernel 6.14 und QEMU 10.
  • Prinzip: Die GPU wird dem Host entzogen, an vfio-pci gebunden und exklusiv an eine VM durchgereicht.
  • Gast: Ubuntu 24.04 LTS mit NVIDIA-Treiber und Docker – CUDA bringt das vLLM-Docker-Image selbst mit.
  • Ergebnis: Ein /v1/chat/completions-Endpunkt, der sich wie die OpenAI-API verhält – nur lokal und DSGVO-konform.

Architektur & Idee

Warum überhaupt eine VM? Weil die saubere Trennung zählt. Der Proxmox-Host bleibt schlank und kümmert sich nur um Virtualisierung, Storage und Netz. Die GPU wird ihm vollständig entzogen und ausschließlich einer VM überlassen. In dieser VM läuft die komplette KI-Welt – NVIDIA-Treiber, Docker und der vLLM-Container – isoliert, versionierbar und jederzeit als Ganzes sicherbar oder migrierbar.

vLLM ist eine Inferenz-Engine, die zwei Dinge besonders gut macht: Sie hält den GPU-Speicher dank PagedAttention effizient zusammen und bündelt viele gleichzeitige Anfragen per Continuous Batching. Nach außen spricht sie die OpenAI-API – Ihre bestehenden Werkzeuge, SDKs und RAG-Pipelines funktionieren ohne Umbau.

Schichtmodell: Clients sprechen per HTTP mit dem OpenAI-Server in der VM; die GPU wird per VFIO vom Proxmox-Host direkt in den Gast durchgereicht.
Abbildung 1: Der Schichtaufbau – die GPU wird am Host vorbei direkt in den VM-Gast geleitet.

Voraussetzungen

Für ein verlässliches Passthrough brauchen Sie Hardware, die Virtualisierung der I/O-MMU unterstützt – das ist heute bei Server- und den meisten Desktop-Plattformen Standard:

Prüfen Sie zunächst die Version und die CPU-Fähigkeiten direkt auf dem Host:

bashProxmox-Host · Shell
# Show the Proxmox version and kernel
pveversion -v | head -n 3

# CPU vendor and virtualisation flags
lscpu | grep -E "Virtualization|Vendor ID|Model name"

Hinweis: Planen Sie den VRAM nach dem Modell. Als Faustregel braucht ein Modell in 16-Bit etwa 2 GB pro Milliarde Parameter allein für die Gewichte – plus Reserve für den KV-Cache. Ein 8B-Modell passt komfortabel auf 24 GB; für 70B brauchen Sie mehrere Karten oder Quantisierung.

1.BIOS/UEFI vorbereiten

Aktivieren Sie im Firmware-Setup des Servers folgende Optionen (Bezeichnungen variieren je Hersteller):

2.IOMMU im Kernel aktivieren

Proxmox VE 9 nutzt je nach Installation zwei verschiedene Bootloader: systemd-boot (bei ZFS-Root bzw. UEFI) oder GRUB. Mit einem Befehl finden Sie heraus, welcher aktiv ist:

bashBootloader ermitteln
proxmox-boot-tool status

Variante A – systemd-boot

Ergänzen Sie die Kernel-Befehlszeile in /etc/kernel/cmdline um die IOMMU-Parameter (alles in einer Zeile) und schreiben Sie die Bootconfig neu:

conf/etc/kernel/cmdline
# Intel CPU – append to the existing line:
root=ZFS=rpool/ROOT/pve-1 boot=zfs intel_iommu=on iommu=pt

# AMD CPU instead:  amd_iommu=on iommu=pt
bashÜbernehmen
proxmox-boot-tool refresh

Variante B – GRUB

Bearbeiten Sie /etc/default/grub, ergänzen Sie die Parameter in GRUB_CMDLINE_LINUX_DEFAULT und aktualisieren Sie GRUB:

conf/etc/default/grub
# Intel:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"

# AMD:
# GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"
bashÜbernehmen & neu starten
update-grub
reboot

Tipp: iommu=pt („pass-through“) lässt der IOMMU nur dort Arbeit, wo sie nötig ist und kostet bei nicht durchgereichten Geräten keine Performance.

3.VFIO-Module laden

Tragen Sie die VFIO-Kernelmodule ein, damit sie beim Boot bereitstehen. Auf Kernel 6.14 zieht vfio_pci die übrigen Module zwar automatisch nach – die explizite Liste schadet aber nicht:

conf/etc/modules
vfio
vfio_iommu_type1
vfio_pci

4.IOMMU prüfen & Gruppen verstehen

Nach dem Neustart sollte die IOMMU aktiv sein. Das verifizieren Sie im Kernel-Log:

bashVerifizieren
dmesg | grep -e DMAR -e IOMMU
# Expect, among others:  DMAR: IOMMU enabled

dmesg | grep 'remapping'
# Expect:  DMAR-IR: Enabled IRQ remapping  (Intel)
#          AMD-Vi: Interrupt remapping enabled  (AMD)

Entscheidend für sauberes Passthrough sind die IOMMU-Gruppen. Eine Gruppe ist die kleinste Einheit, die sich isoliert durchreichen lässt. Eine GPU besteht meist aus zwei Funktionen – dem Grafik- und dem HDMI-Audio-Teil – die zusammengehören. Mit diesem kleinen Skript sehen Sie alle Gruppen:

bashIOMMU-Gruppen auflisten
#!/bin/bash
# Print all IOMMU groups and the PCI devices they contain
for g in /sys/kernel/iommu_groups/*/devices/*; do
    n=${g%%/devices/*}; n=${n##*/}
    printf 'IOMMU group %s: ' "$n"
    lspci -nns "${g##*/}"
done | sort -V
Ablauf: GPU und Audio-Funktion bilden eine IOMMU-Gruppe; beim Boot übernimmt vfio-pci das Gerät; danach erhält der VM-Gast exklusiven Zugriff.
Abbildung 2: Vom Host-Treiber zu vfio-pci – beide Funktionen einer Karte wandern gemeinsam in den Gast.

Achtung: Liegen in der GPU-Gruppe noch fremde Geräte (z. B. ein USB-Controller), lassen sie sich nicht trennen. Wechseln Sie dann den PCIe-Slot oder nutzen Sie – mit Bedacht und nur in vertrauenswürdigen Umgebungen – einen ACS-Override (pcie_acs_override=downstream).

5.GPU an vfio-pci binden

Zuerst die exakten Geräte-IDs ermitteln. Die Form [10de:2204] ist die Hersteller-/Geräte-ID, die wir gleich an vfio-pci übergeben:

bashGPU-IDs finden
lspci -nn | grep -Ei "nvidia|vga|audio"
# Example output:
# 01:00.0 VGA compatible controller [0300]: NVIDIA ... [10de:2204]
# 01:00.1 Audio device          [0403]: NVIDIA ... [10de:1aef]

Nun binden wir beide IDs an vfio-pci und sorgen per softdep dafür, dass vfio-pci vor jedem NVIDIA-Treiber greift:

conf/etc/modprobe.d/vfio.conf
# Bind the GPU (VGA) + audio function firmly to vfio-pci
options vfio-pci ids=10de:2204,10de:1aef

# vfio-pci must load before the NVIDIA drivers
softdep nouveau  pre: vfio-pci
softdep nvidia   pre: vfio-pci
softdep nvidiafb pre: vfio-pci
softdep drm      pre: vfio-pci

Zusätzlich verbannen wir die Host-Treiber per Blacklist, damit der Proxmox-Host die Karte gar nicht erst anfasst:

conf/etc/modprobe.d/blacklist-nvidia.conf
blacklist nouveau
blacklist nvidia
blacklist nvidiafb
blacklist nvidia_drm
bashInitramfs neu bauen & neu starten
update-initramfs -u -k all
reboot

Nach dem Reboot prüfen Sie, dass tatsächlich vfio-pci die Karte hält – nicht nouveau oder nvidia:

bashBindung kontrollieren
lspci -nnk -s 01:00.0
# Kernel driver in use: vfio-pci   <-- exactly what you want

6.VM erstellen (q35 + OVMF)

Für PCIe-Passthrough braucht die VM den q35-Maschinentyp und OVMF (UEFI) statt SeaBIOS. Sie können die VM in der Weboberfläche anlegen – hier der reproduzierbare CLI-Weg:

bashVM 100 anlegen
# New VM with the q35 chipset and UEFI/OVMF
qm create 100 \
  --name vllm-gpu \
  --machine q35 \
  --bios ovmf \
  --cpu host \
  --cores 8 --sockets 1 \
  --memory 32768 \
  --scsihw virtio-scsi-single \
  --net0 virtio,bridge=vmbr0 \
  --ostype l26

# Add the EFI disk (for UEFI variables) and the system disk
qm set 100 --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0
qm set 100 --scsi0 local-lvm:80,ssd=1,discard=on

# Attach the Ubuntu Server ISO as a CD-ROM and set the boot order
qm set 100 --ide2 local:iso/ubuntu-24.04-live-server-amd64.iso,media=cdrom
qm set 100 --boot 'order=scsi0;ide2'

7.GPU durchreichen

Jetzt die GPU der VM zuweisen. Geben Sie nur die Geräteadresse ohne Funktionsnummer an (0000:01:00) – dann werden beide Funktionen (.0 und .1) gemeinsam durchgereicht:

bashhostpci0 zuweisen
qm set 100 --hostpci0 0000:01:00,pcie=1,x-vga=1
# pcie=1   -> attach as a native PCIe device (requires q35)
# x-vga=1  -> use the GPU as the VM's primary display

Das Ergebnis landet in der VM-Konfiguration /etc/pve/qemu-server/100.conf und sieht dann etwa so aus:

conf/etc/pve/qemu-server/100.conf (Auszug)
machine: q35
bios: ovmf
cpu: host
hostpci0: 0000:01:00,pcie=1,x-vga=1
efidisk0: local-lvm:vm-100-disk-0,efitype=4m,pre-enrolled-keys=0,size=4M
scsi0: local-lvm:vm-100-disk-1,discard=on,size=80G,ssd=1

Profi- & Data-Center-GPUs: Diese Karten sind ausdrücklich für den Virtualisierungs- und Passthrough-Betrieb ausgelegt und benötigen keine Sonderbehandlung. Achten Sie auf den passenden Treiberzweig (Production Branch bzw. Data Center Driver) und auf ausreichende Kühlung passiv gekühlter Data-Center-Karten im Servergehäuse.

8.Gast: NVIDIA-Treiber installieren

Installieren Sie Ubuntu 24.04 LTS in der VM. Nach dem ersten Start sollte die GPU im Gast sichtbar sein:

bashVM-Gast · Ubuntu 24.04
# Did the GPU arrive in the guest?
lspci | grep -i nvidia

# Build tools and DKMS for the driver
sudo apt update && sudo apt install -y build-essential dkms

# Pick and install the recommended NVIDIA driver automatically
sudo ubuntu-drivers install
# or explicitly:  sudo apt install -y nvidia-driver-570

sudo reboot

Nach dem Neustart muss nvidia-smi die Karte sauber anzeigen – das ist der Moment der Wahrheit:

bashGPU im Gast prüfen
nvidia-smi
# Shows driver version, GPU model, VRAM and running processes.

9.Docker & Container-Toolkit

vLLM betreiben wir als offiziellen Container – das bringt CUDA, PyTorch und alle Abhängigkeiten gebündelt mit und hält den Gast sauber. Dafür installieren wir Docker und das NVIDIA Container Toolkit, das die GPU in den Container durchreicht:

bashDocker & NVIDIA Container Toolkit
# Install Docker
curl -fsSL https://get.docker.com | sh

# NVIDIA Container Toolkit – add the package repository
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt update && sudo apt install -y nvidia-container-toolkit

# Point Docker at the NVIDIA runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

# Test: is the GPU visible inside a container?
docker run --rm --gpus all ubuntu nvidia-smi

Tipp: Binden Sie das Hugging-Face-Cache-Verzeichnis als Docker-Volume ein, damit heruntergeladene Modelle erhalten bleiben und nicht die System-Disk füllen. Für gesperrte Modelle (z. B. Llama) hinterlegen Sie ein Token über die Umgebungsvariable HF_TOKEN.

10.vLLM-Container starten

Ein einziger docker run-Befehl startet den OpenAI-kompatiblen Server: Er lädt das Modell, richtet die HTTP-API ein und reserviert den GPU-Speicher. --gpus all reicht die GPU durch, --ipc=host gibt vLLM ausreichend geteilten Speicher:

bashOpenAI-kompatiblen Server als Container starten
docker run -d --name vllm --gpus all --ipc=host \
  -p 8000:8000 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  -e "HF_TOKEN=dein-hf-token" \
  vllm/vllm-openai:latest \
  --model meta-llama/Llama-3.1-8B-Instruct \
  --served-model-name llama3.1-8b \
  --gpu-memory-utilization 0.90 \
  --max-model-len 8192 \
  --api-key "dein-geheimer-schluessel"
Anfrage-Fluss: Client zum OpenAI-Server, weiter in den Scheduler mit Continuous Batching und auf die GPU mit PagedAttention; Tokens fließen als Stream zurück.
Abbildung 3: So verarbeitet vLLM eine Anfrage – mit Continuous Batching und PagedAttention.

Verfügen Sie über mehrere GPUs, verteilt vLLM ein großes Modell per Tensor-Parallelität über die Karten:

bashMulti-GPU (Tensor-Parallel)
# Shard the model across, say, 2 GPUs
docker run -d --name vllm --gpus all --ipc=host \
  -p 8000:8000 -v ~/.cache/huggingface:/root/.cache/huggingface \
  vllm/vllm-openai:latest \
  --model Qwen/Qwen2.5-32B-Instruct \
  --tensor-parallel-size 2 \
  --gpu-memory-utilization 0.92 --max-model-len 16384

11.Dauerbetrieb mit Docker Compose

Für den Dauerbetrieb gießen wir den Container in eine docker-compose.yml – mit automatischem Neustart, fester Konfiguration und sauberen Logs:

yamldocker-compose.yml
services:
  vllm:
    image: vllm/vllm-openai:latest
    container_name: vllm
    restart: unless-stopped
    ports:
      - "8000:8000"
    volumes:
      - ~/.cache/huggingface:/root/.cache/huggingface
    environment:
      - HF_TOKEN=dein-hf-token
    ipc: host
    command: >
      --model meta-llama/Llama-3.1-8B-Instruct
      --served-model-name llama3.1-8b
      --gpu-memory-utilization 0.90 --max-model-len 8192
      --api-key dein-geheimer-schluessel
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
bashStack starten & Logs verfolgen
docker compose up -d
docker compose logs -f vllm

12.Testen

Der Endpunkt verhält sich wie die OpenAI-API. Ein schneller Test mit curl:

bashChat-Completion testen
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dein-geheimer-schluessel" \
  -d '{
    "model": "llama3.1-8b",
    "messages": [
      {"role": "system", "content": "Du bist ein hilfreicher Assistent."},
      {"role": "user", "content": "Erklaere PagedAttention in einem Satz."}
    ]
  }'

Und dieselbe Anfrage mit dem offiziellen OpenAI-Python-SDK – nur die base_url ändert sich:

pythonclient.py
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="dein-geheimer-schluessel",
)

resp = client.chat.completions.create(
    model="llama3.1-8b",
    messages=[{"role": "user", "content": "Hallo!"}],
)
print(resp.choices[0].message.content)

Wichtige vLLM-Parameter

ParameterWirkung
--gpu-memory-utilizationAnteil des VRAM, den vLLM belegen darf (0–1). Höher = größerer KV-Cache = mehr parallele Anfragen. Typisch 0.85–0.95.
--max-model-lenMaximale Kontextlänge (Tokens). Begrenzt den KV-Cache-Bedarf pro Anfrage.
--tensor-parallel-sizeVerteilt ein Modell über mehrere GPUs (Anzahl der Karten).
--served-model-nameFrei wählbarer Modellname für die API – entkoppelt vom Pfad/Repo.
--quantizationQuantisierung (z. B. awq, gptq, fp8) – spart VRAM bei großen Modellen.
--dtypeRechengenauigkeit, meist auto (bf16/fp16).
--api-keySchützt den Endpunkt mit einem Bearer-Token.
--max-num-seqsObergrenze gleichzeitig verarbeiteter Sequenzen (Batch-Breite).

Performance-Tuning

Troubleshooting

SymptomUrsache & Lösung
VM startet nicht, „IOMMU not present“IOMMU im BIOS oder Kernel nicht aktiv. Schritte 1–2 prüfen, dmesg | grep IOMMU.
vfio-pci hält die Karte nichtBlacklist/softdep unvollständig oder Initramfs nicht neu gebaut. update-initramfs -u -k all, dann lspci -nnk.
„Cannot reserve … IOMMU group not viable“Fremde Geräte in der GPU-Gruppe. Anderen PCIe-Slot wählen oder ACS-Override (mit Bedacht).
nvidia-smi findet keine GPUTreiber fehlt/zu alt oder GPU nicht durchgereicht. Passenden Data-Center- bzw. Production-Branch-Treiber installieren und die hostpci0-Zuweisung prüfen.
CUDA out of memory beim Start--gpu-memory-utilization oder --max-model-len senken, ggf. Quantisierung nutzen.
API antwortet, aber langsamKontext zu groß, Batch zu klein oder GPU am falschen NUMA-Knoten. Siehe Tuning.

Sicherheit & Betrieb

Ein lokaler LLM-Server ist ein produktiver Dienst – behandeln Sie ihn auch so. Drei Grundregeln:

Häufige Fragen

Welche NVIDIA-GPUs sind für diesen Aufbau geeignet?

Empfehlenswert sind professionelle Karten: die RTX-Profiklasse (z. B. RTX 4000/5000/6000 Ada) sowie Data-Center-GPUs wie NVIDIA L4, L40S, A100 oder H100. Sie bieten ECC-Speicher, hohe VRAM-Kapazität und sind für Dauerbetrieb und Virtualisierung ausgelegt.

Brauche ich im Gast ein CUDA-Toolkit?

Für den reinen Betrieb von vLLM nicht. Das offizielle vLLM-Docker-Image bringt CUDA, PyTorch und alle Abhängigkeiten gebündelt mit. Im Gast genügen der NVIDIA-Treiber und das NVIDIA Container Toolkit. Ein vollständiges CUDA-Toolkit ist nur nötig, wenn Sie eigene CUDA-Kernel kompilieren.

Kann ich mehrere GPUs an dieselbe VM durchreichen?

Ja. Jede GPU wird als eigenes hostpci-Gerät zugewiesen (hostpci0, hostpci1 …). In vLLM verteilen Sie das Modell anschließend per --tensor-parallel-size über die Karten.

Warum eine VM statt eines LXC-Containers?

Eine VM mit echtem PCIe-Passthrough bietet starke Isolation und exklusiven, treibernahen GPU-Zugriff. LXC mit geteilter GPU ist ressourcenschonender, vermischt aber Host- und Gast-Treiber und ist für eine saubere, mandantenfähige Trennung weniger geeignet.

Welche Hardware empfiehlt sich für den Produktivbetrieb?

Für Dauerlast und mehrere Nutzer sind Data-Center-GPUs (z. B. NVIDIA L4, L40S oder A100/H100) ideal – passiv gekühlt, ECC-Speicher, für 24/7 ausgelegt. Für Einstieg und Entwicklung genügt oft eine professionelle RTX-Karte (z. B. RTX 6000 Ada) mit reichlich VRAM.

Quellen

Externe Quellen, Stand August 2026 (öffnen in einem neuen Tab):

On-Premise KI mit Nokkela

Souveräne KI – ohne Cloud-Zwang

Sie möchten eigene Sprachmodelle sicher im eigenen Rechenzentrum oder in unseren Rechenzentren in Deutschland und Finnland betreiben? Wir planen, bauen und betreiben Ihre GPU-Infrastruktur und Inferenz-Plattform – herstellerunabhängig und DSGVO-konform.

Anfrage Mehr zu nokkela.ai

Dieser Beitrag dient der allgemeinen Information. Befehle, Geräte-IDs und Versionsangaben sind Beispiele und an Ihre Hardware anzupassen. Stand: August 2026, Proxmox VE 9.0.