Proxmox VE LXC Deployment (iGPU passthrough)
Recommended path: PVE host → privileged LXC container → docker inside the container → SkyView image. Don't install docker directly on the PVE host (Proxmox officially advises against it; it clashes with PVE's iptables / apt). LXC is namespace-isolated with near-zero performance overhead, and /dev/dri passthrough feels almost identical to running docker on the host.
1. Supported hardware & recommended variant
| Hardware | Recommended variant | iGPU status |
|---|---|---|
| N100 / N305 / N355 mini PC | openvino | Alder Lake-N iGPU, /dev/renderD128 available |
| J4125 / J4105 old NUC | openvino | Apollo Lake iGPU, /dev/renderD128 available |
| i3-i7 11th gen+ + Iris Xe | openvino | Best value pick |
| NVIDIA GPU PVE host | cuda or trt | Requires installing the NVIDIA driver on the PVE host + passing /dev/nvidia* to the LXC |
2. Prerequisites (on the PVE host)
- 1
Confirm the host has /dev/dri
Run
ls -la /dev/dri/in the PVE shell; you should see card0/card1 + renderD128; otherwise the PVE kernel hasn't loaded i915, so runmodprobe i915first - 2
Download the Debian 12 template
PVE Web UI → local → CT Templates → Templates button → find and download debian-12-standard (or
pveam download local debian-12-standard_12.x_amd64.tar.zst) - 3
Find the render/video group GIDs
Run
getent group renderandgetent group videoin the PVE shell and note the GIDs (default render=104, video=44); you'll need them for pct set later
3. Create the LXC container
# In the PVE host shell: create a vmid=101 container, 4 cores, 4G RAM, 40G disk
pct create 101 local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst \
--hostname yunkan \
--cores 4 --memory 4096 --swap 1024 \
--rootfs local-lvm:40 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp,firewall=0 \
--unprivileged 0 \
--features nesting=1,keyctl=1 \
--onboot 1
pct start 101Must be privileged + nesting=1 + keyctl=1
--unprivileged 0 = privileged LXC, the simplest choice for home use (running docker in an unprivileged container needs 90+ lines of lxc.conf tuning). nesting=1 lets you run docker inside the container, and keyctl=1 lets docker overlayfs work.4. Pass the iGPU through to the LXC
# On the PVE host: pass renderD128 and card1 through to vmid=101
pct set 101 -dev0 /dev/dri/renderD128,gid=104 # render group
pct set 101 -dev1 /dev/dri/card1,gid=44 # video group
# Reboot the container for the dev passthrough to take effect
pct reboot 101
# Verify: enter the container and check that /dev/dri exists
pct exec 101 -- ls -la /dev/dri/5. Install docker inside the LXC + run SkyView
# Enter the LXC
pct enter 101
# Install docker
curl -fsSL https://get.docker.com | sh
# Run the SkyView one-line script (auto-selects the openvino variant because it detects /dev/dri)
curl -fsSL https://cdn.yun-kan.com/yunkan-install.sh | bashWhen the script finishes it gives an LXC IP + port (e.g. http://10.0.0.148:23406/). Open it from any machine on the same subnet to enter the Setup wizard.
6. Upgrading
Upgrades are done inside the LXC (pct enter 101), exactly like a regular Linux host — no LXC-specific steps. Prefer method A (one-click upgrade from the web console, no command line needed); use method B / C when you want to pin a specific version or prefer the command line.
Option A: one-click web upgrade (recommended)
Open Web Admin → Settings → System upgrade and click Upgrade. The system pulls the new image and recreates the main container automatically (a short-lived worker container appears during the switch and removes itself when done). If the new version fails to start, it automatically rolls back to the previous one — no command line involved. The docker socket works normally inside LXC, so this path is fully supported.
Option B: command-line upgrade
Use this when you want to control the timing yourself or pin a specific version. Enter the LXC and run in the deployment directory (default ~/skyview):
pct enter 101
cd ~/skyview
# Upgrade to the latest image for the current tag (default latest) and rebuild
docker compose -p yunkan -f compose.yml up -d --pull alwaysTo pin a specific version, change the image tag in the compose first, then rebuild (keep the variant unchanged — see the warning below):
cd ~/skyview
# Replace 0.9.9 with your target version
sed -i 's|image: .*/yunkan-.*|image: registry.cn-hangzhou.aliyuncs.com/yunkan/yunkan-openvino:0.9.9|' compose.yml
docker compose -p yunkan -f compose.yml up -d --pull always --force-recreateDon't switch variants by mistake during an upgrade
openvino / cpu / cuda / trt) must match the original — an LXC + iGPU passthrough install uses openvino, and mistyping it as cpu loses hardware acceleration. If unsure, run docker ps to see whether the current image name contains -openvino or -cpu. The data/ and recordings/ volumes are cross-version compatible, DB migration runs automatically when the new container starts, and upgrading doesn't lose data.Option C: re-run the install script
The one-line installer is idempotent: re-running it re-pulls the image, regenerates the compose file and recreates the container. Ideal for refreshing an older install to the latest standard layout (it also retires the legacy yunkan-updater helper container):
pct enter 101
curl -fsSL https://cdn.yun-kan.com/yunkan-install.sh | bash7. Backup / restore
- LXC snapshot: before upgrading,
pct snapshot 101 pre-upgrade-$(date +%Y%m%d); if something breaks,pct rollback 101 <snapshot-name>rolls the whole container back instantly - LXC backup:
vzdump 101 --storage localbacks up the entire container (including the docker volume) via PVE's standard backup; or Web UI → select 101 → Backup - Restore:
pct restore <new-vmid> <backup-file>restores from a backup - ⚠️ Don't destroy + create to rebuild: rebuilding the LXC changes
/etc/machine-id, so the license fingerprint drifts → it consumes a new slot in a loop. To reset, always usepct restorefrom a backup; never create a new container
8. FAQ
/dev/dri doesn't appear inside the LXC
pct reboot 101; if it still fails, pct config 101 | grep dev to see whether the config was written.docker run reports a keyctl error
--features keyctl=1 when creating the container. Add it: pct set 101 --features nesting=1,keyctl=1, then pct reboot 101.Manage all your LXCs centrally