i5-7500 backend → Lenovo Legion S7 (Proxmox + Ubuntu LXC)
Proxmox VE 8.x Ubuntu 24.04 LXC RTX 30 NVENC DUMB stackBIOS (F2 on POST):
Enable SVM Mode (AMD virtualization / IOMMU)
Set GPU Mode → Discrete (disables Optimus)
Flash + install Proxmox VE 8.x ISO to NVMe:
Hostname: swainstation-backend | IP: 10.0.0.228 | Gateway: 10.0.0.1
SSH in:
ssh root@10.0.0.228
apt update && apt install -y pve-headers
apt install -y nvidia-driver nvidia-smi
reboot
After reboot — verify and note device major numbers (needed for LXC config):
nvidia-smi
ls -la /dev/nvidia*
cat /proc/devices | grep nvidia
nvidia-uvm — it varies by kernel. You'll need it in Phase 3.pveam update
pveam download local ubuntu-24.04-standard_*.tar.zst
pct create 100 local:vztmpl/ubuntu-24.04-standard_*.tar.zst \
--hostname dumb-stack \
--memory 8192 \
--cores 6 \
--rootfs local-lvm:60 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--unprivileged 0 \
--features nesting=1,fuse=1
Add to /etc/pve/lxc/100.conf — replace 507 with actual nvidia-uvm major from Phase 2:
lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 507:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
pct start 100
pct enter 100
# Docker
apt update && apt install -y curl ca-certificates rsync fuse3
curl -fsSL https://get.docker.com | sh
# nvidia-container-toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt update && apt install -y nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker
# Verify
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
# Create user matching i5 PUID
useradd -u 1000 -m jasper
rsync -av /home/jasper/docker/DUMB/ jasper@10.0.0.228:/home/jasper/docker/DUMB/
rsync -av /home/jasper/docker/jellyseerr/ jasper@10.0.0.228:/home/jasper/docker/jellyseerr/
rsync -av /home/jasper/docker/caddy/ jasper@10.0.0.228:/home/jasper/docker/caddy/
rsync -av /home/jasper/docker/homepage/ jasper@10.0.0.228:/home/jasper/docker/homepage/
rsync -av /home/jasper/docker/docker-compose.yml jasper@10.0.0.228:/home/jasper/docker/
docker-compose.yml
| Change | Old | New |
|---|---|---|
| Homepage allowed hosts | 10.0.0.227:3001 | 10.0.0.228:3001 |
| group_add | - "109" (Intel render group) | remove entirely |
| devices | /dev/dri:/dev/dri | remove (add back if ffmpeg needs it) |
| LIBVA env vars | LIBVA_DRIVERS_PATH, LIBVA_DRIVER_NAME | remove both |
| NVIDIA runtime | (not present) | add runtime: nvidia + NVIDIA_VISIBLE_DEVICES=all |
dumb_config.json — jellyfin env block
Remove: LIBVA_DRIVERS_PATH and LIBVA_DRIVER_NAME: iHD
Keep: JELLYFIN_FFMPEG: /usr/lib/jellyfin-ffmpeg/ffmpeg
homepage/config/services.yaml — update these hrefs to 10.0.0.228:
| Service | Old href | New href |
|---|---|---|
| Sonarr | 10.0.0.227:8989 | 10.0.0.228:8989 |
| Radarr | 10.0.0.227:7878 | 10.0.0.228:7878 |
| Prowlarr | 10.0.0.227:9696 | 10.0.0.228:9696 |
| Decypharr | 10.0.0.227:8282 | 10.0.0.228:8282 |
| DUMB UI | 10.0.0.227:3005 | 10.0.0.228:3005 |
Caddyfile — no changes needed (uses Docker service names, not IPs).
CPU governor:
cat > /etc/systemd/system/cpu-performance.service << 'EOF'
[Unit]
Description=Set CPU governor to performance
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now cpu-performance.service
DNS (point to Pi-hole on i5):
echo "DNSStubListener=no" >> /etc/systemd/resolved.conf
systemctl restart systemd-resolved
printf "nameserver 10.0.0.227\nnameserver 75.75.75.75\n" > /etc/resolv.conf
chattr +i /etc/resolv.conf
cd /home/jasper/docker && docker compose up -d
Verify before cutover:
http://10.0.0.228:8096 — Jellyfin loadshttp://10.0.0.228:8989 — Sonarr loadshttp://10.0.0.228:3001 — Homepage loadsDUMB/data/jellyfin/log/FFmpeg.*.log for h264_nvencRouter port forwarding (xFi app):
| Port | Was → Now | Notes |
|---|---|---|
| 80, 443 | 10.0.0.227 → 10.0.0.228 | Caddy / HTTPS |
| 22 | stays → 10.0.0.227 | SSH to i5 |
| 2222 (optional) | new → 10.0.0.228:22 | SSH to laptop |
| 19132, 25500-25600 | stays → 10.0.0.227 | Crafty / Minecraft |
Update jmp-autoconnect.sh on i5 — change Jellyfin backend URL:
# /home/jasper/jmp-autoconnect.sh
# change: http://10.0.0.227:8096/web/index.html
# to: http://10.0.0.228:8096/web/index.html
Stop migrated services on i5:
cd /home/jasper/docker
docker compose stop DUMB jellyseerr caddy homepage
DuckDNS — leave script on i5. It updates to the house's public IP which hasn't changed.
https://jellyfin.comfums.duckdns.org loads and plays videohttps://requests.comfums.duckdns.org loads Jellyseerrh264_nvenc encoderdig google.com @10.0.0.227)