Proxmox
camera.ui läuft auf Proxmox VE in einem LXC-Container, der Docker beherbergt. Ein Befehl auf dem Proxmox-Host richtet alles ein: Container, Docker und camera.ui.
Warum ein LXC und keine VM?
Ein LXC kann die iGPU teilen: /dev/dri bleibt gleichzeitig für den Host und andere Container nutzbar, während eine VM mit PCIe-Passthrough die GPU monopolisiert. Zusammen mit dem geringeren Overhead ist das das Standard-Muster für NVRs auf Proxmox. Für NVIDIA-Karten ist eine VM die bessere Wahl (siehe unten).
Schnellstart
Auf dem Proxmox-Host (als root) ausführen:
curl -fsSLO https://raw.githubusercontent.com/cameraui/docker/main/proxmox/install-cameraui-lxc.sh
bash install-cameraui-lxc.shDas Script lädt das Ubuntu-24.04-LXC-Template, erstellt einen unprivilegierten Container mit Nesting (der empfohlene Weg für Docker auf Proxmox, da privilegierte Container auf aktuellen Proxmox-Versionen Dockers AppArmor-Profil nicht mehr laden können), installiert Docker darin, deployt camera.ui via Docker Compose und gibt die URL der Web-UI aus. Getestet mit Proxmox VE 9.
Alles ist über Umgebungsvariablen einstellbar:
| Variable | Default | Bedeutung |
|---|---|---|
CTID | nächste freie ID | Container-ID |
CT_HOSTNAME | cameraui | Container-Hostname |
CORES / RAM_MB / DISK_GB | 4 / 4096 / 16 | Container-Ressourcen |
BRIDGE | vmbr0 | Netzwerk-Bridge (Container bekommt seine IP per DHCP) |
STORAGE | auto-detect | rootfs-Storage (bevorzugt local-lvm, local-zfs, local, sonst den ersten aktiven Storage, der ein Container-rootfs aufnehmen kann) |
TEMPLATE_STORAGE | local | Storage, auf den das LXC-Template geladen wird (braucht Content-Typ „Container-Template“) |
FLAVOR | cpu | cpu, intel oder amd (wählt den Image-Flavor); nvidia ist experimentell |
GPU_PASSTHROUGH | 1 wenn Flavor ≠ cpu | reicht /dev/dri in den Container |
TZ | Zeitzone des Hosts | Zeitzone im Container |
Beispiel für eine Intel-Maschine: FLAVOR=intel bash install-cameraui-lxc.sh
Shell im Container öffnen
Das Script legt den Container ohne Root-Passwort an, über die Proxmox-Konsole oder SSH kommst du also nicht hinein. Nimm stattdessen die Shell des Hosts:
pct enter <CTID>Damit landest du in einer Root-Shell im Container. Für einzelne Befehle musst du gar nicht erst hineinwechseln:
pct exec <CTID> -- docker logs camerauiWenn du dich lieber wie gewohnt anmelden möchtest, vergib einmal ein Passwort. Danach funktionieren Konsole und SSH:
pct exec <CTID> -- passwdHardware-Beschleunigung
- Intel / AMD iGPU.
FLAVOR=intel(oderamd) setzen. Das Script reicht den GPU-Render-Node über Proxmox' Device-Passthrough in den Container und verdrahtet ihn bis zu Docker durch. Sonst nichts zu konfigurieren; die Details stehen auf der Seite Hardware-Beschleunigung. - NVIDIA. Nutze eine VM mit PCIe-Passthrough statt eines LXC. In der VM hast du ein normales Linux und folgst dem Standard-Docker-Setup mit dem
nvidia-Flavor. Ein LXC würde erfordern, den NVIDIA-Treiber auf dem Proxmox-Host und die Userspace-Bibliotheken im Container dauerhaft versionsgleich zu halten. Eine VM vermeidet das komplett, und Proxmox' VM-Passthrough ist ausgezeichnet. Der Trade-off: Die VM monopolisiert die Karte. Brauchen andere Dienste auf dem Host dieselbe GPU (Ollama, Jellyfin), siehe NVIDIA im LXC unten. - KI-Beschleuniger (Coral, Hailo). Gleiches Muster wie überall: den Host-Treiber auf dem Proxmox-Host installieren, dann den Device-Node (
/dev/apex_0,/dev/hailo0) in den Container reichen.
NVIDIA im LXC (experimentell)
FLAVOR=nvidia teilt die Karte zwischen dem Container und anderen Diensten auf dem Host, was eine VM nicht kann. Der Haken ist eine harte Versionskopplung: Die NVIDIA-Userspace-Bibliotheken im Container müssen exakt zum Kernel-Treiber des Hosts passen, nach jedem Treiber-Update.
Voraussetzung ist ein funktionierender NVIDIA-Treiber auf dem Proxmox-Host (.run-Installer mit --dkms plus pve-headers; nvidia-smi auf dem Host muss funktionieren), und die installierte Treiberversion muss auf download.nvidia.com existieren. Dann:
FLAVOR=nvidia bash install-cameraui-lxc.shDas Script reicht alle /dev/nvidia*-Device-Nodes in den Container, installiert den passenden Userspace-Treiber (--no-kernel-module) plus das NVIDIA Container Toolkit (mit no-cgroups=true, weil ein unprivilegierter Container keine Device-Cgroups verwalten kann) und registriert einen Sync-Service, der nach Host-Treiber-Updates beim Boot den passenden Userspace nachinstalliert. Verifizieren mit:
pct exec <CTID> -- docker exec cameraui nvidia-smiExperimentell
Dieser Weg hängt an NVIDIAs Installer-Archiv und daran, dass der Host-Treiber gesund bleibt; nach einem Host-Treiber-Update braucht der Container einen Reboot zum Nachsynchronisieren. Wenn es bricht, funktioniert der VM-Weg immer. Reports und Fixes sind im docker-Repo willkommen.
Aufnahmen auf einer dedizierten Platte oder einem NAS
Aufnahmen landen standardmäßig auf dem eigenen Volume des Containers. Für eine größere Platte, ein NAS-Share oder einen zusammengefassten Pool reichst du diesen Speicher in den Container und setzt den NVR-Speicherpfad darauf.
Unprivilegierte Container können NFS/CIFS-Shares nicht selbst mounten. Mounte das Share auf dem Proxmox-Host und reiche es als Mountpoint in den Container:
pct set <CTID> -mp0 /mnt/nas/recordings,mp=/mnt/recordingsSetze dann den NVR-Speicherpfad auf /mnt/recordings (Einstellungen → Aufnahmen → Speicher), oder siehe den Speicher-Abschnitt der Docker-Seite.
FUSE-Mounts (mergerfs, rclone) brauchen Sonderbehandlung
Ein FUSE-Mount (etwa ein mergerfs-Pool, der mehrere Platten zusammenfasst) propagiert nicht wie ein normales Dateisystem in einen (unprivilegierten) Container. Ist der FUSE-Mount nicht vor dem Container-Start auf dem Host aktiv, sieht der Container den leeren Mountpoint auf der Root-Disk des Hosts statt den Pool. Aufnahmen landen dann auf der kleinen OS-Platte und werden innerhalb von Minuten wieder rotiert, obwohl der Pool Terabytes frei hat.
Mounte den Pool auf dem Host vor dem Container-Start (z.B. per fstab-Eintrag oder systemd-Unit mit Before=pve-container@<CTID>.service) und stelle sicher, dass der Mount in den Container geteilt wird. Danach immer aus dem Container heraus verifizieren.
Speichergröße verifizieren
Nach dem Setzen eines eigenen Speicherpfads prüfen, ob der Container wirklich das volle Volume sieht. Dieser eine Check fängt fast jedes Mount-Problem ab:
pct exec <CTID> -- df -h /mnt/recordingsDie angezeigte Größe muss zu deiner echten Platte oder deinem Pool passen. Zeigt sie stattdessen die kleine Container-Root-Größe, ist der Mount nicht propagiert. Dann die Schritte oben erneut prüfen. Der NVR loggt seinen aufgelösten Speicher samt Größe außerdem bei jedem Start und zeigt in Einstellungen → Aufnahmen eine Warnung, wenn das Volume unerwartet klein ist.
Verifizieren
Bei jedem Start loggt der Container, welche Devices tatsächlich angekommen sind. Siehe Aus dem Container verifizieren. Die camera.ui-UI ist unter https://<container-ip>:3443 erreichbar (das Script gibt die IP am Ende aus; der Container taucht außerdem mit seinem Hostnamen in der Geräteliste deines Routers auf).