Software Local AINvidiaProxmox

NVIDIA-GPU unter Proxmox VE für einen LXC-Container einrichten

Diese Anleitung ist die Fortsetzung meines Artikels zur Proxmox-Grundinstallation. Nachdem Proxmox VE erfolgreich eingerichtet wurde, geht es jetzt darum, die NVIDIA RTX 3060 für meinen Local-AI-Server vorzubereiten und anschließend für den LXC-Container 101 verfügbar zu machen.

Docker und Nvidia
10 Schritte 603 Views

Nachdem wir im vorherigen Artikel Proxmox VE als Grundlage für unseren Local-AI-Server installiert haben, geht es jetzt an einen der wichtigsten Schritte: Wir bringen die NVIDIA RTX 3060 dazu, innerhalb unseres LXC-Containers verwendet werden zu können.

Zum Einsatz kommt eine NVIDIA RTX 3060 mit 12 GB VRAM. Als Host läuft Proxmox VE 9.2.20. Der LXC-Container mit der ID 101 wird später unsere Umgebung für Docker, Docker Compose und llama.cpp bereitstellen.

Wie funktioniert der Aufbau 🤔?

Die grundlegende Aufteilung ist dabei relativ einfach:

Der Proxmox-Host übernimmt die GPU.

Hier installieren wir den vollständigen NVIDIA-Treiber inklusive der benötigten Kernel-Module. Der Proxmox-Kernel ist für die Kommunikation mit der Grafikkarte verantwortlich und stellt die entsprechenden NVIDIA-Geräte bereit.

Der LXC-Container bekommt Zugriff auf diese GPU.

Im Container installieren wir anschließend den NVIDIA-Treiber erneut, allerdings ausdrücklich ohne Kernel-Module. Der Container verwendet damit die vom Host bereitgestellte GPU und deren Kernel-Schnittstelle, während die benötigten NVIDIA-Userspace-Komponenten innerhalb des Containers vorhanden sind.

Damit schaffen wir die Grundlage dafür, dass später auch Anwendungen innerhalb des Containers, insbesondere Docker und llama.cpp, auf die RTX 3060 zugreifen können.

Warum installieren wir den Treiber zweimal ?

Das wirkt auf den ersten Blick etwas ungewöhnlich. Auf dem Host benötigen wir den Treiber, damit der Linux-Kernel die Grafikkarte überhaupt verwalten kann.

Im Container benötigen Anwendungen dagegen die passenden NVIDIA-Bibliotheken und Werkzeuge, um mit dieser GPU kommunizieren zu können. Deshalb wird der NVIDIA-Treiber dort ebenfalls installiert, aber ohne die Kernel-Module.

Genau diese Trennung ist für unseren Aufbau entscheidend:

Proxmox Host: NVIDIA-Treiber + Kernel-Module
LXC 101: NVIDIA-Treiber ohne Kernel-Module
GPU: RTX 3060 mit 12 GB VRAM
Später: Docker + Docker Compose + llama.cpp

Wir gehen jetzt Schritt für Schritt vor und überprüfen nach jedem wichtigen Abschnitt, ob die GPU weiterhin korrekt funktioniert.

1

NVIDIA-Treiber auf dem Proxmox-Host installieren

Alle Befehle in diesem Abschnitt werden auf dem Proxmox-Host ausgeführt.

Wichtig: Der NVIDIA-Treiber lädt sein Kernelmodul bei aktivem Secure Boot in der Regel nicht. Deaktiviere Secure Boot im BIOS, bevor du den Treiber installierst. Den Status prüfst du mit apt install mokutil -y und danach mokutil --sb-state. Das Signieren des Moduls behandelt diese Anleitung nicht.

1.1 Proxmox aktualisieren

Melde dich über die Proxmox-Weboberfläche an und öffne die Shell des Hosts. Alternativ kannst du dich per SSH verbinden.

Prüfe zunächst die installierte Version:

pveversion -v

Aktualisiere anschließend die Paketlisten und installiere verfügbare Updates:

apt update && apt full-upgrade -y

Falls ein Kernel-Update installiert wurde, ist ein Neustart erforderlich, damit der neue Kernel tatsächlich läuft.

** 1.2 NVIDIA GPU erkennen**

Bevor wir irgendwelche NVIDIA-Treiber installieren, prüfen wir zunächst,
ob Proxmox die Grafikkarte überhaupt erkennt.

lspci | grep -i nvidia

Wenn die RTX 3060 korrekt erkannt wird, sollte eine Ausgabe ähnlich dieser erscheinen:

01:00.0 VGA compatible controller: NVIDIA Corporation GA106 [GeForce RTX 3060] (rev a1)
01:00.1 Audio device: NVIDIA Corporation GA106 High Definition Audio Controller (rev a1)

Damit wissen wir, dass die Grafikkarte auf PCIe-Ebene erkannt wird.

1.3 Benötigte Pakete installieren

Bevor wir den NVIDIA-Treiber installieren, richten wir zunächst die benötigten Werkzeuge ein. Dazu gehören die Compiler-Werkzeuge für den Bau des NVIDIA-Kernel-Moduls, DKMS sowie einige Hilfsprogramme, die wir im weiteren Verlauf der Installation benötigen.

Installiere die Pakete mit:

apt install build-essential dkms pciutils wget curl nano mc btop nvtop

Die einzelnen Pakete haben dabei folgende Aufgaben:

  • build-essential – enthält Compiler und Werkzeuge, die für den Bau des NVIDIA-Kernel-Moduls benötigt werden.
  • dkms – verwaltet und baut Kernel-Module bei Bedarf automatisch für den verwendeten Kernel.
  • pciutils – stellt unter anderem lspci bereit, mit dem wir die erkannte NVIDIA-GPU überprüfen können.
  • wget – wird zum Herunterladen von Dateien verwendet.
  • curl – wird ebenfalls für Downloads und zum Abrufen von Informationen verwendet.
  • nano – einfacher Editor zum Bearbeiten von Konfigurationsdateien.
  • mc – komfortabler Dateimanager für das Terminal.
  • btop – zeigt CPU-Auslastung, RAM-Verbrauch, laufende Prozesse und Systemressourcen an.
  • nvtop – zeigt GPU-Auslastung, VRAM-Verbrauch, Temperaturen und laufende GPU-Prozesse in Echtzeit an.

Anschließend prüfen wir, welchen Kernel der Proxmox-Host aktuell verwendet:

uname -r

Für den Bau des NVIDIA-Kernel-Moduls müssen die passenden Kernel-Header installiert sein. Unter Proxmox VE 9 verwenden wir dafür das Header-Metapaket des aktuellen Proxmox-7.0-Kernel-Zweigs:

apt install proxmox-headers-7.0

Damit wird die zum installierten Proxmox-Kernel passende Header-Version eingerichtet.

Zum Abschluss kontrollieren wir, ob das benötigte Build-Verzeichnis vorhanden ist:

ls -ld /lib/modules/$(uname -r)/build

Wenn hier ein gültiges Verzeichnis angezeigt wird, sind die benötigten Kernel-Header vorhanden und die Voraussetzungen für die NVIDIA-Treiberinstallation erfüllt.

Falls das Verzeichnis fehlt, sollte die NVIDIA-Treiberinstallation an dieser Stelle noch nicht durchgeführt werden. Zuerst müssen die Kernel-Header für den aktuell laufenden Proxmox-Kernel korrekt installiert werden.

1.4 NVIDIA-Treiber herunterladen

Lade den passenden Linux-Treiber für deine Nvidia RTX Grafikkarte von der offiziellen NVIDIA-Seite herunter:

NVIDIA – Treiber herunterladen

Für die RTX 3060 verwenden wir in diesem Beispiel die Production-Branch-Version 595.99.02.

Öffne anschließend die NVIDIA-Treiberseite im Browser und kopiere den direkten Download-Link der .run-Datei.
Füge diesen Link anschließend in den folgenden Befehl ein:

wget <kopierter-Download-Link>

Beispiel für die verwendete Version:

wget https://download.nvidia.com/XFree86/Linux-x86_64/595.99.02/NVIDIA-Linux-x86_64-595.99.02.run

Prüfe anschließend, ob die Datei erfolgreich heruntergeladen wurde:

ls -lh NVIDIA-Linux-x86_64-*.run

Mache die heruntergeladene Datei ausführbar. Verwende dabei am besten den exakten Dateinamen:

chmod +x NV*

Hinweis: chmod +x NV* funktioniert, wenn sich im Verzeichnis /root nur die heruntergeladene NVIDIA-.run-Datei befindet. Wenn dort mehrere Dateien mit NV beginnen, sollte stattdessen der vollständige Dateiname verwendet werden.

1.5 NVIDIA-Treiber mit DKMS installieren

Starte den Installer:

./NV* --dkms

Während der Installation werden verschiedene Abfragen angezeigt.

Kernelmodul auswählen:

→ NVIDIA proprietary

Das proprietäre Kernelmodul ist der klassische NVIDIA-Kerneltreiber. Die MIT/GPL-Variante ist das offene NVIDIA-Kernelmodul und wird insbesondere bei neueren GPU-Generationen (RTX50xx usw.) und aktuellen NVIDIA-Treibern eingesetzt. Für unseren Aufbau mit der RTX 3060 verwenden wir die proprietäre Variante.

Weitere Abfragen:

  • Nouveau deaktivieren → Yes
  • Installation trotz aktuell geladenem Nouveau fortsetzen → Continue installation
  • 32-bit compatibility libraries → OK; diese werden nicht benötigt
  • Kernelmodul mit DKMS registrieren → Yes
  • initramfs neu erstellen → Rebuild initramfs
  • nvidia-xconfig ausführen → No

Die Option --dkms sorgt dafür, dass das NVIDIA-Kernelmodul über DKMS verwaltet wird. Dadurch kann das Modul bei späteren Kernel-Updates automatisch für den neuen Kernel gebaut werden, sofern die passenden Kernel-Header vorhanden sind.

Da Nouveau zum Zeitpunkt der Installation noch im laufenden Kernel geladen ist, muss der Proxmox-Host anschließend neu gestartet werden. Die Deaktivierung von Nouveau wird erst nach dem Neustart wirksam.

1.6 Automatische NVIDIA-Device-Initialisierung einrichten

Auf Headless-Servern erstellt der NVIDIA-Treiber die Gerätedateien (/dev/nvidiactl etc.) erst beim ersten Zugriff. Damit Proxmox-LXC-Container beim Booten nicht mit TASK ERROR: Device /dev/nvidiactl does not exist abbrechen, legen wir einen kleinen Systemd-Dienst an. Dieser führt nvidia-smi aus, bevor Proxmox die Container startet:

Kernel-Module eintragen:

cat <<EOF > /etc/modules-load.d/nvidia.conf
nvidia
nvidia_uvm
EOF

Systemd-Dienst anlegen:

cat <<EOF > /etc/systemd/system/nvidia-init.service
[Unit]
Description=Initialize NVIDIA Device Nodes
DefaultDependencies=no
After=systemd-modules-load.service
Before=pve-guests.service

[Service]
Type=oneshot
ExecStart=/usr/bin/nvidia-smi

[Install]
WantedBy=multi-user.target
EOF

Dienst aktivieren:

systemctl daemon-reload
systemctl enable nvidia-init.service

1.7 Treiber überprüfen

Nach dem Neustart öffnest du erneut die Host-Shell und prüfst:

nvidia-smi

Anschließend:

lsmod | grep nvidia

Wenn nvidia-smi die RTX 3060 mit 12 GB VRAM und die installierte Treiberversion anzeigt und das NVIDIA-Kernelmodul geladen ist, ist der Host fertig für den nächsten Schritt.

2

LXC-Container 101 erstellen und vorbereiten

Bevor wir die RTX 3060 an einen LXC-Container durchreichen können, benötigen wir zunächst einen passenden Container. In diesem Beispiel erstellen wir den Container mit der ID 101. Später werden darin Docker und llama.cpp laufen.

2.1 Debian-Template herunterladen

Gehe auf der Proxmox-Weboberfläche zu:
local (pve) → CT Templates → Templates
Suche nach Debian 13 und lade das aktuelle Debian-13-Template herunter.

2.2 LXC-Container erstellen

Klicke anschließend oben rechts auf Create CT.
Verwende für unseren Testaufbau folgende Einstellungen:

  • General
    CT ID: 101
    Hostname: llamacpp
    Passwort: eigenes sicheres Passwort
    Unprivileged Container: aktiviert
    Nesting: aktiviert
  • Template
    Debian 13 auswählen
  • Disk
    Storage: gewünschten Proxmox-Speicher auswählen
    Größe: 40 GB
  • CPU
    Cores: 6
  • Memory
    RAM: 8192 MB
    Swap: 0 MB
  • Network
    IPv4: 192.168.178.134/24
    Gateway (IPv4):192.168.178.1
    Bridge: normalerweise vmbr0

Die restlichen Einstellungen können zunächst auf den Standardwerten bleiben.

Klicke anschließend auf Finish, um den Container zu erstellen.

Die gewählten Ressourcen sind für den Einstieg gedacht. Speicher, CPU-Kerne und Arbeitsspeicher können bei Bedarf später angepasst werden. Beachte dabei, dass größere lokale KI-Modelle vor allem ausreichend Arbeitsspeicher beziehungsweise GPU-Speicher benötigen.

2.3 Container starten

Starte den Container zunächst über die Proxmox-Weboberfläche.
Öffne anschließend die Shell des Proxmox-Hosts und kopiere den zuvor heruntergeladenen NVIDIA-Treiber in den CT 101:

pct push 101 /root/NV* /root/NV*

Wechsle anschließend direkt in den Container:

pct enter 101

Jetzt befindest du dich in der Shell des CT 101.
Aktualisiere zunächst Debian:

apt update && apt full-upgrade -y

Prüfe anschließend, ob der NVIDIA-Installer vorhanden ist:

ls -lh /root/NV*

Wenn die Datei angezeigt wird, ist der Container für die nächsten Schritte vorbereitet.
Verlasse anschließend den Container wieder:

exit

Damit befindest du dich wieder in der Shell des Proxmox-Hosts.

Hinweis: Zu diesem Zeitpunkt ist die RTX 3060 noch nicht im Container verfügbar. Die NVIDIA-Geräte werden erst im nächsten Schritt vom Proxmox-Host an den LXC-Container durchgereicht.

3

NVIDIA-Geräte für den LXC-Container bereitstellen

Ab hier arbeiten wir mit CT 101.

3.1 Container 101 stoppen

Gehe auf die Shell des Proxmox-Hosts:

pct stop 101

3.2 Vorhandene NVIDIA-Geräte prüfen

nvidia-smi
ls -l /dev/nvidia*

Die Gerätedateien können je nach Treiber und GPU variieren. Typischerweise gibt es unter anderem:

/dev/nvidia0
/dev/nvidiactl
/dev/nvidia-uvm
/dev/nvidia-uvm-tools

gegebenenfalls /dev/nvidia-modeset

Verwende nur Geräte, die auf deinem Host tatsächlich vorhanden sind.

3.3 Geräte in der Container-Konfiguration eintragen

Die NVIDIA-Geräte müssen in der Konfiguration von CT 101 eingetragen werden. Dafür gibt es zwei Möglichkeiten:
Über die Proxmox-Weboberfläche oder über die CLI (Kommandozeile)

Wir verwenden in dieser Anleitung die Weboberfläche, da sich die Geräte dort bequem hinzufügen lassen. Wer lieber mit der Kommandozeile arbeitet, kann alternativ die Konfigurationsdatei direkt bearbeiten.

Über die Proxmox-Weboberfläche (unser Weg)

Wähle in der Proxmox-Weboberfläche den CT 101 aus.
Gehe zu:

Resources → Add → Device Passthrough

Füge die zuvor auf dem Host geprüften NVIDIA-Geräte einzeln hinzu:

/dev/nvidia0
/dev/nvidiactl
/dev/nvidia-uvm
/dev/nvidia-uvm-tools

Übernimm die Einstellungen und speichere die Änderungen.

Über die CLI (Alternative)

Öffne die Shell des Proxmox-Hosts und bearbeite die Konfigurationsdatei von CT 101:

nano /etc/pve/lxc/101.conf

Füge die benötigten Gerätezuordnungen am Ende der Datei ein:

dev0: /dev/nvidia0
dev1: /dev/nvidiactl
dev2: /dev/nvidia-uvm
dev3: /dev/nvidia-uvm-tools

Verwende nur Geräte, die auf deinem Host tatsächlich vorhanden sind. Falls weitere Geräte benötigt werden, müssen diese entsprechend ergänzt werden.

Speichere die Datei mit Ctrl + O, bestätige mit Enter und beende den Editor mit Ctrl + X.

Wichtig: Nutze nur einen der beiden Wege. Wenn du die Geräte bereits über die Weboberfläche hinzugefügt hast, musst du sie nicht zusätzlich über die CLI eintragen.

3.4 Container starten

pct start 101

Öffne die Container-Shell:

pct enter 101

Prüfe, ob die Geräte im Container sichtbar sind:

ls -l /dev/nvidia*

Wenn die Geräte fehlen, kontrolliere zuerst die Host-Geräte und die Konfiguration des CT. Ein erfolgreicher Start allein beweist noch nicht, dass die GPU nutzbar ist.

4

NVIDIA-Treiber im LXC installieren

Jetzt installieren wir die Userspace-Komponenten des NVIDIA-Treibers im Container. Die Kernel-Module werden dabei ausdrücklich nicht installiert.

4.1 NVIDIA-Installer ausführbar machen

Mache den vorhandenen NVIDIA-Installer ausführbar:

chmod +x /root/NV*

4.2 NVIDIA-Treiber ohne Kernelmodul installieren

Starte anschließend den Installer ohne Installation eines NVIDIA-Kernelmoduls:

/root/NV* --no-kernel-module

Während der Installation folgende Abfragen bestätigen:

  • Kernelmodul-Typ: NVIDIA Proprietary → auswählen
  • Hinweis zu --no-kernel-modules: OK
  • X-Library-Pfade: OK
  • 32-Bit-Kompatibilitätsbibliotheken: No
  • Vulkan-Loader fehlt: OK
  • nvidia-xconfig ausführen: No

Damit werden die benötigten NVIDIA-Userspace-Komponenten im Container installiert. Das NVIDIA-Kernelmodul selbst läuft weiterhin auf dem Proxmox-Host.

4.3 GPU-Zugriff im Container testen

Nach erfolgreicher Installation prüfen wir, ob der Container auf die RTX 3060 zugreifen kann:

nvidia-smi

Wenn die RTX 3060 und die installierte NVIDIA-Treiberversion angezeigt werden, kann der Container auf die GPU zugreifen.

4.4 Proxmox-Host neu starten und abschließend testen

Verlasse zunächst die Container-Shell:

exit

Starte anschließend den gesamten Proxmox-Host neu:

reboot

Warte, bis Proxmox wieder vollständig gestartet ist, und verbinde dich erneut mit dem Shell des Proxmox-Host.

Prüfe zunächst auf dem Host, ob die NVIDIA-GPU erkannt wird:

nvidia-smi

Anschließend prüfen wir, ob die NVIDIA-Geräte vorhanden sind:

ls -l /dev/nvidia*

Starte danach den Container und betrete ihn:

pct start 101
pct enter 101

Führe im Container den abschließenden GPU-Test durch:

nvidia-smi

Wenn die RTX 3060 auch nach dem Neustart auf dem Host und im Container angezeigt wird, ist die GPU erfolgreich für CT 101 eingerichtet und steht für die nächsten Schritte mit Docker und llama.cpp zur Verfügung.

5

GPU-Leistungsgrenze festlegen (optional)

Dieser Schritt ist optional. Bei einer einzelnen RTX 3060 ist eine Leistungsbegrenzung für unser Setup nicht notwendig. Die Karte kann mit ihren normalen Standardeinstellungen betrieben werden.

Bei einem Multi-GPU-System kann es dagegen sinnvoll sein, die maximale Leistungsaufnahme etwas zu begrenzen. Gerade bei einem Local-AI-Server können GPUs über längere Zeit unter hoher Last laufen. Eine moderate Begrenzung kann dabei helfen, Stromverbrauch, Abwärme und dauerhafte Belastung zu reduzieren.

Das Ziel ist bei einem solchen Server nicht, die letzten Prozent Leistung herauszuholen, sondern einen guten Kompromiss zwischen Leistung, Verbrauch, Temperaturen und langfristiger Nutzung der Hardware zu erreichen.

Hinweis: Eine Leistungsbegrenzung garantiert keine längere Lebensdauer der GPU. Sie reduziert jedoch die maximale Leistungsaufnahme und damit unter anderem Wärmeentwicklung und elektrische Belastung.

Wichtig: Die Befehle in diesem Schritt führst du auf dem Proxmox-Host aus, nicht im Container. Nach Schritt 4 befindest du dich noch in der Shell von CT 101. Verlasse sie mit exit.

5.1 Zulässige Leistungsgrenze prüfen

Bevor eine Leistungsgrenze gesetzt wird, sollte zunächst geprüft werden, welchen Bereich die jeweilige GPU unterstützt:

nvidia-smi -q -d POWER

Suche in der Ausgabe nach den Zeilen Default Power Limit, Min Power Limit und Max Power Limit. Dein Wert muss zwischen Min und Max liegen. Als Ausgangspunkt wählen viele etwa 75 bis 85 % des Default-Werts. Das ist eine Faustregel und kein Garantiewert. Die Werte unterscheiden sich je nach GPU-Modell und Hersteller, übernimm deshalb nie einen Wert aus einem anderen Tutorial.

5.2 Leistungsgrenze einmal testen

Setze die Grenze zuerst nur für die aktuelle Sitzung (ersetze WATT durch deinen Wert):

nvidia-smi -pl WATT

Mit nvidia-smi prüfst du das Ergebnis. In der Spalte Pwr:Usage/Cap steht rechts vom Schrägstrich die aktuelle Grenze. Sie sollte deinem Wert entsprechen. Nach einem Neustart gilt wieder der Standardwert.

Bei mehreren GPUs gilt der Befehl ohne weitere Angabe für alle Karten. Für eine einzelne Karte nutzt du -i mit der Nummer aus der Ausgabe von nvidia-smi:

nvidia-smi -i 0 -pl WATT

5.3 Leistungsgrenze beim Systemstart setzen

Wenn die Grenze dauerhaft gelten soll, trägst du sie in den Root-Crontab ein:

crontab -e

Folgende Zeile eintragen und WATT durch deinen getesteten Wert ersetzen:

@reboot sleep 10; nvidia-smi -pm 1; nvidia-smi -pl WATT

nvidia-smi -pm 1 aktiviert den Persistenzmodus. Das sleep 10 gibt dem System nach dem Start etwas Zeit, die GPU vollständig bereitzustellen. Die Befehle sind mit ; getrennt, damit die Leistungsgrenze auch dann gesetzt wird, wenn ein früherer Befehl eine Warnung ausgibt.

Prüfe nach einem Neustart mit nvidia-smi, ob die Grenze übernommen wurde.

Rückgängig machen: Entferne die Zeile mit crontab -e und starte den Host neu. Danach gilt wieder der Standardwert.

6

System vorbereiten und Docker installieren

Ab diesem Punkt arbeiten wir innerhalb von CT 101. Falls du dich noch auf dem Proxmox-Host befindest (zum Beispiel nach Schritt 5), wechsle mit pct enter 101 in den Container.

6.1 Docker-Abhängigkeiten installieren

Zunächst installieren wir die benötigten Pakete für die Einrichtung des offiziellen Docker-Repositorys:

apt install ca-certificates curl -y

ca-certificates ermöglicht die sichere Verbindung zu HTTPS-Quellen.
curl wird verwendet, um den Docker-GPG-Schlüssel herunterzuladen.

6.2 Offizielles Docker-Repository einrichten

Debian 13 enthält Docker bereits in den eigenen Paketquellen. Dort ist Docker unter anderem als docker.io verfügbar.

Für diese Anleitung verwenden wir jedoch das offizielle Docker-Repository, über das Docker seine eigene Docker Engine und das aktuelle Compose-Plugin bereitstellt.

Zuerst legen wir das Verzeichnis für den GPG-Schlüssel an:

install -m 0755 -d /etc/apt/keyrings

GPG-Schlüssel herunterladen:

curl -fsSL https://download.docker.com/linux/debian/gpg \
  -o /etc/apt/keyrings/docker.asc

Berechtigungen setzen:

chmod a+r /etc/apt/keyrings/docker.asc

Anschließend wird das offizielle Docker-Repository eingerichtet:

cat <<EOF > /etc/apt/sources.list.d/docker.sources
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: trixie
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc
EOF

Danach aktualisieren wir die Paketquellen:

apt update

Damit kann Debian die Docker-Pakete direkt aus dem offiziellen Docker-Repository beziehen.

6.3 Docker und Docker Compose installieren

Jetzt installieren wir Docker Engine, die Docker CLI, Containerd, Buildx und das Docker-Compose-Plugin:

apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Anschließend prüfen wir die installierten Versionen:

docker --version
docker compose version

Prüfe außerdem, ob der Docker-Dienst läuft:

systemctl status docker

Falls Docker nicht läuft, kann der Dienst mit folgendem Befehl gestartet und gleichzeitig für den automatischen Start aktiviert werden:

systemctl enable --now docker

6.4 Docker testen

Bevor wir mit dem NVIDIA Container Toolkit weitermachen, testen wir zunächst die grundlegende Docker-Installation.
Dafür verwenden wir den offiziellen Docker-Testcontainer:

docker run hello-world

Docker lädt dabei das kleine Test-Image herunter und startet einen Container.
Wenn am Ende die Meldung

Hello from Docker!

erscheint, funktioniert Docker grundsätzlich.

Im nächsten Schritt richten wir das NVIDIA Container Toolkit ein.

7

NVIDIA Container Toolkit installieren

Damit Docker auf die NVIDIA-GPU des LXC-Containers zugreifen kann, installieren wir das NVIDIA Container Toolkit. Es stellt die Verbindung zwischen Docker und der bereits eingerichteten NVIDIA-GPU her.

Wir arbeiten weiterhin in CT 101.

7.1 Voraussetzungen installieren

apt update
apt install ca-certificates curl gnupg2 -y

7.2 NVIDIA-Paketquelle einrichten
Keyring-Verzeichnis erstellen:

install -m 0755 -d /etc/apt/keyrings

NVIDIA-GPG-Key herunterladen:

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | gpg --dearmor -o /etc/apt/keyrings/nvidia-container-toolkit-keyring.gpg

NVIDIA-Paketquelle hinzufügen:

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
  | sed 's#deb https://#deb [signed-by=/etc/apt/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
  > /etc/apt/sources.list.d/nvidia-container-toolkit.list

Danach:

apt update

7.3 NVIDIA Container Toolkit installieren


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

Installation überprüfen:

nvidia-ctk --version

7.4 Docker für NVIDIA konfigurieren

Jetzt konfigurieren wir Docker für die Verwendung der NVIDIA Container Runtime:

nvidia-ctk runtime configure --runtime=docker

Anschließend deaktivieren wir die cgroup-Verwaltung der NVIDIA Runtime. Diese Anpassung ist bei unserem unprivilegierten LXC-Container notwendig, da die NVIDIA Runtime innerhalb des Containers keine eigenen cgroup-Geräteregeln setzen kann.

Die vorhandene Konfiguration wird automatisch angepasst:

sed -i 's/^#no-cgroups = false/no-cgroups = true/' /etc/nvidia-container-runtime/config.toml

Kontrolliere anschließend die Einstellung:

grep '^no-cgroups' /etc/nvidia-container-runtime/config.toml

Erwartete Ausgabe:

no-cgroups = true

Danach Docker neu starten:

systemctl restart docker

Damit ist Docker für die NVIDIA-GPU innerhalb unseres LXC-Containers vorbereitet.

7.5 NVIDIA-GPU aus Docker testen

Jetzt prüfen wir, ob Docker innerhalb von CT 101 tatsächlich auf die NVIDIA-GPU zugreifen kann.

Führe folgenden Test aus:

docker run --rm --gpus all nvidia/cuda:12.8.1-base-ubuntu24.04 nvidia-smi

Beim ersten Aufruf wird das benötigte CUDA-Image automatisch von Docker Hub heruntergeladen.

Wenn die Einrichtung erfolgreich war, zeigt nvidia-smi innerhalb des Docker-Containers die NVIDIA-GPU an. Bei unserem Testsystem sollte hier die RTX 3060 mit 12 GB VRAM und dem installierten NVIDIA-Treiber 595.99.02 erscheinen.

Das --rm sorgt dafür, dass der Testcontainer nach dem erfolgreichen Test automatisch wieder entfernt wird.

Wenn die GPU angezeigt wird, ist die komplette GPU-Anbindung erfolgreich:

Proxmox → LXC → NVIDIA-Treiber → NVIDIA Container Toolkit → Docker → RTX 3060

Damit ist die NVIDIA-GPU für Docker verfügbar und wir können mit der Einrichtung von llama.cpp fortfahren.

8

Backup des Containers erstellen

Bevor wir mit den nächsten Schritten fortfahren, richten wir den automatischen Start des Containers ein und erstellen ein vollständiges Backup.

Damit haben wir einen festen Ausgangspunkt für die weiteren Schritte. Falls wir später noch einmal von vorne beginnen möchten, kann der Container aus diesem Backup wiederhergestellt werden. Die bereits durchgeführte Einrichtung von NVIDIA, der GPU-Durchreichung und Docker muss dadurch nicht erneut durchgeführt werden.

8.1 Automatischen Start aktivieren

  • Wähle in der Proxmox-Weboberfläche den Container 101 aus.
  • Öffne den Bereich Options.
  • Doppelklicke auf Start at boot, setze den Haken und bestätige mit OK.

Der Container startet nun automatisch, sobald der Proxmox-Host hochgefahren ist. Dass die NVIDIA-Geräte dann schon bereitstehen, sorgt der Dienst nvidia-init.service aus Schritt 1.6.

8.2 Backup erstellen

Öffne beim Container den Bereich Backup und klicke auf Backup now.

Verwende folgende Einstellungen:

Storage: gewünschter Backup-Speicher "local"
Compression: ZSTD
Mode: Stop
Notification: Use global settings
Notes: Ausgangszustand nach NVIDIA GPU, LXC und Docker Einrichtung

Klicke anschließend auf Backup und warte, bis die Sicherung erfolgreich abgeschlossen wurde.

Damit haben wir einen festen Ausgangspunkt für die weiteren Abschnitte.

9

Wartung und häufige Probleme

Nach Updates

Kernel-Update auf dem Host: DKMS baut das NVIDIA-Modul automatisch neu, sofern die Kernel-Header vorhanden sind. Prüfe nach dem Neustart auf dem Host:

nvidia-smi
dkms status

Treiber-Update: Host und Container müssen exakt dieselbe Treiberversion haben. Wird nur eine Seite aktualisiert, funktioniert die GPU im Container nicht mehr. Ersetze VERSION durch die neue Versionsnummer:

# Auf dem Host
pct stop 101
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 --dkms
reboot

# Nach dem Neustart, wieder auf dem Host
pct push 101 /root/NVIDIA-Linux-x86_64-VERSION.run /root/NVIDIA-Linux-x86_64-VERSION.run
pct start 101
pct enter 101

# Im Container
chmod +x /root/NVIDIA-Linux-x86_64-VERSION.run
/root/NVIDIA-Linux-x86_64-VERSION.run --no-kernel-module
nvidia-smi

Lösche alte .run-Dateien in /root, oder nutze wie hier den vollständigen Dateinamen. Sonst trifft NV* mehrere Dateien.

Häufige Probleme

Host: "NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver"
Das Kernelmodul ist nicht geladen. Prüfe auf dem Host:

dkms status
lsmod | grep nvidia
dmesg | grep -i nvidia

Typische Ursachen: fehlende Kernel-Header, vergessener Neustart nach der Installation oder aktives Secure Boot.

Container startet nicht: "Device /dev/nvidiactl does not exist"
Der Dienst aus Schritt 1.6 läuft nicht oder zu spät. Prüfe auf dem Host:

systemctl status nvidia-init.service
ls -l /dev/nvidia*

Container: "Failed to initialize NVML: Driver/library version mismatch"
Host und Container haben unterschiedliche Treiberversionen. Vergleiche:

# Auf dem Host
cat /proc/driver/nvidia/version

# Im Container
ls /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.*

Die Versionsnummer muss übereinstimmen. Installiere sonst im Container die passende .run-Datei neu.

Geräte fehlen im Container (/dev/nvidia*)
Kontrolliere, ob die Geräte auf dem Host existieren und in /etc/pve/lxc/101.conf eingetragen sind. Fehlt /dev/nvidia-uvm, prüfe auf dem Host mit lsmod | grep nvidia_uvm, ob das Modul geladen ist.

Der Docker-GPU-Test schlägt fehl
Teste zuerst nvidia-smi direkt im Container. Funktioniert das, prüfe:

grep '^no-cgroups' /etc/nvidia-container-runtime/config.toml
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker

Danach muss in der Konfigurationsdatei weiterhin no-cgroups = true stehen (Schritt 7.4).

Der Container startet nach einem Host-Neustart nicht automatisch
Prüfe, ob bei Options → Start at boot der Haken gesetzt ist (Schritt 8.1) und ob nvidia-init.service läuft.

10

Fazit & Ausblick

Mit dieser Anleitung haben wir Schritt für Schritt das Fundament für einen Local-AI-Server geschaffen.

Der Proxmox VE Host wurde für eine NVIDIA-GPU vorbereitet und die Grafikkarte für die Verwendung in einem unprivilegierten LXC-Container eingerichtet. Anschließend wurden Docker und die NVIDIA Container Toolkit-Umgebung im Container eingerichtet und die GPU innerhalb des Containers erfolgreich für GPU-beschleunigte Anwendungen verfügbar gemacht.

Damit steht jetzt eine saubere Grundlage für die nächsten Schritte zur Verfügung.

Die Vorteile dieser Architektur:

  • Performance: Der LXC-Container greift direkt auf die NVIDIA-GPU des Hosts zu. Im Vergleich zu einer vollständigen virtuellen Maschine entsteht dabei nur sehr wenig zusätzlicher Overhead.
  • Isolation: Der Container bleibt unprivilegiert. Gleichzeitig können Anwendungen innerhalb des Containers die bereitgestellte GPU für rechenintensive KI-Workloads nutzen.
  • Flexibilität: Docker ermöglicht es, unterschiedliche KI-Anwendungen und Modelle unabhängig voneinander zu betreiben und später einfach auszutauschen oder zu erweitern.

Ausblick: Multi-GPU

Der hier gezeigte Aufbau lässt sich grundsätzlich auch auf Systeme mit mehreren NVIDIA-GPUs erweitern.
Die GPUs werden vom NVIDIA-Treiber fortlaufend nummeriert:

/dev/nvidia0 → erste GPU
/dev/nvidia1 → zweite GPU
/dev/nvidia2 → dritte GPU

Anwendungen wie llama.cpp können mehrere GPUs nutzen, um größere Modelle auf den verfügbaren VRAM mehrerer Grafikkarten zu verteilen. Wie genau die GPUs eingesetzt werden, hängt dabei von der jeweiligen Anwendung und dem verwendeten Modell ab.

Eine NVIDIA-GPU in einem anderen Rechner kann dagegen nicht einfach als /dev/nvidia1 über das Netzwerk eingebunden werden. Für verteilte Inferenz sind andere Verfahren und entsprechende Softwarelösungen erforderlich.

Wie geht es weiter?
Der Proxmox-Host und der LXC-Container sind jetzt für die nächsten Local-AI-Workloads vorbereitet.
Im nächsten Schritt geht es darum, die eigentliche KI-Software bereitzustellen.
In meinem nächsten Beitrag geht es zunächst um die Einrichtung von llama.cpp und den Betrieb verschiedener GGUF-Modelle direkt im vorbereiteten LXC-Container.

Weiter mit Teil 3: llama.cpp mit Docker und CUDA

← Zurück zu den Local AI-Anleitungen