How to Self-Host Jellyfin on Proxmox LXC — Complete Media Server Guide 2026
homelab

How to Self-Host Jellyfin on Proxmox LXC — Complete Media Server Guide 2026

Ricardo Gil
August 31, 2026
10 min read
#jellyfin #proxmox #lxc #self-hosting #media-server

Jellyfin is the fully open-source, zero-subscription alternative to Plex — and if you're already running Proxmox, an LXC container is the cleanest way to host it. No Docker overhead, no VM memory waste, and direct hardware transcoding access if your CPU supports it. This guide walks through the complete setup: container creation, Jellyfin installation, media bind mounts, Intel Quick Sync hardware transcoding, and a reverse proxy with HTTPS.

Why Jellyfin on LXC Instead of Docker or a VM?

LXC containers on Proxmox give you near-bare-metal performance with minimal overhead. For Jellyfin specifically, that matters when you're dealing with hardware transcoding — an LXC can access the host's iGPU devices directly via device passthrough, while a full VM adds a virtualization layer that complicates GPU sharing and burns extra memory. Docker works fine for Jellyfin, but if you're already managing your homelab through Proxmox, keeping everything as LXC containers gives you a consistent operational model: one backup strategy (PBS), one snapshot tool, one config format.

LXC snapshots are also fast enough to be practical — you can snapshot the entire Jellyfin container before an upgrade, roll back in 10 seconds if something breaks, and delete the snapshot once you're confident. That workflow is much cleaner than managing Docker volume backups alongside container state.

What You'll Need

  • Proxmox VE 8.x or 9.x on your homelab node
  • The Debian 12 LXC template downloaded in Proxmox (available in the template library under local storage)
  • A storage volume for your media — a ZFS pool, NFS mount, or a large local disk accessible from the Proxmox host
  • Optional but recommended: a CPU with Intel Quick Sync (8th gen or newer) for hardware transcoding

I run Jellyfin on a Beelink EQ12 Mini PC (~$189) powered by an Intel N100. The N100's Intel UHD Graphics handles 4K HEVC transcoding at under 15W — absurd value for a media server running 24/7. Pair it with 32GB of DDR4 RAM (~$59) so Proxmox has headroom to run Jellyfin alongside your other containers without memory pressure.

Step 1 — Create the LXC Container

In the Proxmox web UI, click Create CT and use these settings:

  • Hostname: jellyfin
  • Template: debian-12-standard (latest available)
  • Disk: 16 GB — Jellyfin's metadata, thumbnails, and transcode cache stay manageable at this size
  • CPU: 4 cores minimum; 6–8 if you're planning simultaneous streams with software fallback
  • Memory: 2048 MB RAM, 512 MB swap
  • Network: assign a static IP on vmbr0 — you don't want Jellyfin's IP drifting
  • Unprivileged: Yes — we'll handle the device passthrough and UID mapping explicitly

Or create it from the Proxmox host shell — faster when you're already SSH'd in:

bash
pct create 200 local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \
  --hostname jellyfin \
  --cores 4 \
  --memory 2048 \
  --swap 512 \
  --rootfs local-lvm:16 \
  --net0 name=eth0,bridge=vmbr0,ip=192.168.1.200/24,gw=192.168.1.1 \
  --unprivileged 1 \
  --features nesting=1

pct start 200
pct enter 200

The nesting=1 feature flag enables kernel capabilities the container needs. Substitute your actual gateway and desired static IP.

Step 2 — Install Jellyfin

Jellyfin provides an official Debian repository. Inside the container shell:

bash
apt update && apt upgrade -y
apt install -y curl apt-transport-https gnupg2

# Add the Jellyfin GPG key
curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key \
  | gpg --dearmor -o /usr/share/keyrings/jellyfin-archive-keyring.gpg

# Add the Debian Bookworm repository
echo "deb [signed-by=/usr/share/keyrings/jellyfin-archive-keyring.gpg] \
  https://repo.jellyfin.org/debian bookworm main" \
  | tee /etc/apt/sources.list.d/jellyfin.list

apt update && apt install -y jellyfin
systemctl enable --now jellyfin
systemctl status jellyfin

Jellyfin's web UI is now live at http://<container-ip>:8096. Don't run through the setup wizard yet — mount your media storage first so you can point Jellyfin at your library immediately during first-run.

Step 3 — Mount Your Media Storage

The right approach on Proxmox is a bind mount from the host into the container, rather than mapping a network share directly inside the LXC. This keeps NFS/SMB mounting centralized on the host and means the container sees a clean local-style filesystem path.

Run this on the Proxmox host (not inside the container):

bash
# Stop the container before modifying mounts
pct stop 200

# Bind-mount your media directory into the container
# Replace /mnt/media with your actual media path on the Proxmox host
pct set 200 -mp0 /mnt/media,mp=/media,ro=0

pct start 200

Inside the container, /media now maps to the host's /mnt/media. You can add more mount points (-mp1, -mp2) for separate movie and TV roots if your storage is split across volumes.

One gotcha with unprivileged containers: UID mapping. The jellyfin user inside the container runs as UID 104, which maps to a higher UID on the host. The simplest fix is making your media world-readable:

bash
# On the Proxmox host
chmod -R o+r /mnt/media

For a more locked-down setup, inspect the actual mapped UID and set ownership precisely — but for a homelab, world-readable media is acceptable.

Step 4 — First-Run Configuration

Open http://<container-ip>:8096 and work through the wizard:

  1. Admin account — create a strong password; this account manages all users and libraries
  2. Add media libraries — point them at /media/Movies, /media/TV, /media/Music as appropriate; select the correct content type for each so Jellyfin uses the right metadata scraper
  3. Metadata language — set your preferred language; Jellyfin uses TMDB and TheTVDB by default
  4. Remote access — leave at default for now; configure the reverse proxy next

After finishing the wizard, Jellyfin will scan your library and pull metadata. A large library (1000+ items) takes 20–40 minutes for the initial scan. You can watch progress under Dashboard → Activity Log.

Step 5 — Intel Quick Sync Hardware Transcoding

This is where Proxmox LXC earns its place over Docker for a Jellyfin setup. Hardware transcoding lets Jellyfin offload HEVC/H.264 decode and encode to the CPU's iGPU, dropping CPU usage from 100% to under 10% for a 4K stream.

First, verify the device nodes exist on the Proxmox host:

bash
ls -la /dev/dri/
# Expected output: card0  renderD128

Stop the container, then edit its config at /etc/pve/lxc/200.conf on the host:

bash
pct stop 200

cat >> /etc/pve/lxc/200.conf << 'EOF'
lxc.cgroup2.devices.allow: c 226:* rwm
lxc.cgroup2.devices.allow: c 29:0 rwm
lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
EOF

pct start 200

Inside the container, confirm the device is visible and add Jellyfin to the required groups:

bash
ls -la /dev/dri/
# Should show renderD128

usermod -aG render,video jellyfin
systemctl restart jellyfin

In the Jellyfin web UI, go to Dashboard → Playback → Transcoding and configure:

  • Hardware acceleration: Intel Quick Sync Video (QSV)
  • Hardware encoding: Enable H.264 and HEVC encoding
  • Hardware decoding: Enable H.264, HEVC, VP9, AV1 — check all your iGPU supports
  • Throttle transcodes when the CPU is busy: Enable for 24/7 stability

On an N100 or any 12th-gen+ Intel chip, you'll transcode 4K HEVC → 1080p H.264 in real-time while consuming under 15% of one CPU core. Jellyfin has zero paywall for hardware transcoding — unlike Plex, which locks Quick Sync behind Plex Pass.

Step 6 — HTTPS via Reverse Proxy

For LAN-only access, port 8096 over HTTP is fine. For external access or a clean subdomain, put Jellyfin behind a reverse proxy. If you already run Traefik or Nginx Proxy Manager on Proxmox (from other guides on this site), this is a one-config addition.

For a bare Nginx configuration on a dedicated reverse proxy LXC:

bash
server {
    listen 443 ssl http2;
    server_name jellyfin.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/jellyfin.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/jellyfin.yourdomain.com/privkey.pem;

    # Buffer size for video streaming
    proxy_buffering off;

    location / {
        proxy_pass         http://192.168.1.200:8096;
        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        # WebSocket support — required for Jellyfin
        proxy_http_version 1.1;
        proxy_set_header   Upgrade    $http_upgrade;
        proxy_set_header   Connection "upgrade";
    }
}

In Jellyfin's Dashboard → Networking, set your base URL to https://jellyfin.yourdomain.com and add your proxy's IP to the Known Proxies list so request headers are trusted correctly.

Step 7 — Backups with Proxmox Backup Server

Jellyfin's value is in its metadata — watch history, ratings, and the posters/artwork it's scraped from TMDB. Re-scraping a large library from scratch takes hours and loses watch progress across all users. Back it up.

If you're running Proxmox Backup Server, just include CT 200 in your PBS backup job and it's handled automatically at the container level. For a lighter manual approach:

bash
# Inside the Jellyfin container
tar -czf /tmp/jellyfin-backup-$(date +%F).tar.gz \
  /var/lib/jellyfin \
  /etc/jellyfin

# Pull the archive to the host from outside the container
pct pull 200 /tmp/jellyfin-backup-2026-08-31.tar.gz /backup/jellyfin/

The /var/lib/jellyfin directory contains all metadata, images, and user data. The Jellyfin binary and config in /etc/jellyfin round out a full restore set.

Performance and Tuning Notes

A few practical details that make a real difference:

  • Transcoding temp path: Move it to your fastest storage. In Dashboard → Transcoding, point the temp directory at a path backed by a fast NVMe. A WD Black 2TB NVMe (~$129) as your Proxmox OS and container disk handles simultaneous transcodes without I/O contention.
  • Network throughput: 4K HEVC direct play peaks around 80 Mbps. A 1G LAN is fine, but if you're streaming to multiple clients simultaneously from a busy node, a TP-Link 2.5G USB Ethernet adapter (~$29) eliminates that as a variable.
  • Library scan schedule: Configure a scheduled scan (nightly at 3am) rather than relying purely on real-time filesystem monitoring. File watchers inside LXC containers can occasionally miss events depending on the underlying storage backend.
  • Segment container CPU: If you're running other workloads on the same Proxmox node, set a CPU limit on the Jellyfin container (pct set 200 --cpulimit 4) so a busy transcode job doesn't starve your other services.

What to Set Up Next

With Jellyfin running, the natural additions are:

  • Jellyseerr — a request management UI (similar to Overseerr) that lets users request movies and TV shows. Runs as another LXC and integrates with Jellyfin via API.
  • Radarr + Sonarr + Prowlarr — automated media acquisition stack. Each runs cleanly as a separate lightweight LXC and drops new files into your bind-mounted media directory where Jellyfin picks them up automatically.
  • Jellyfin on mobile — the official Jellyfin apps for iOS and Android are free and support offline downloads, unlike the Plex mobile apps that require Plex Pass.

The full stack — Proxmox LXC, Jellyfin, hardware transcoding, PBS backups — runs comfortably on the hardware mentioned above and totals under $300 if you're starting fresh. If you're already running Proxmox for other services, the incremental cost is a few minutes of config time.

📬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article