Plex raised prices, removed the lifetime pass as a purchase option, and pushed cloud-dependent features harder than ever. If you’re running a homelab media server, now is the time to switch to Jellyfin — a fully open-source, free, self-hosted alternative with no subscriptions, no phoning home, and complete control over your library.
This guide walks through the full migration from Plex to Jellyfin in Docker on a Linux homelab: setting up the stack, configuring hardware transcoding with Intel QuickSync or NVIDIA NVENC, exposing it securely through Traefik, and integrating it with Sonarr, Radarr, and the rest of the arrs ecosystem.
Why Jellyfin Over Plex in 2026
| Feature | Plex | Jellyfin |
|---|---|---|
| License | Proprietary (subscription) | GPL 2.0 / AGPL 3.0 |
| Cost | $120/yr or legacy lifetime | Free |
| Hardware transcoding | Plex Pass required | Built-in, no paywall |
| Intro skip | Plex Pass required | Free + plugin |
| Client support | Wide (native apps) | Wide (web, Android TV, Roku, LG, Samsung) |
| Offline mode | Requires cloud auth | Fully offline capable |
| Docker support | Official image | Official + linuxserver images |
| Remote access | Relay/prerequisite auth | Direct or reverse proxy |
The bottom line: Jellyfin gives you everything Plex charges for — and without sending metadata or authentication through Jellyfin’s servers.
Prerequisites
- Docker and Docker Compose v2 installed on the host
- Media files on a mounted volume (local, NFS, or NAS)
- (Optional) Intel iGPU or NVIDIA GPU for transcoding
- (Optional) Traefik or Nginx for secure remote access
dockeruser in therenderandvideogroups for GPU access
Step 1: Jellyfin Docker Compose Setup
Create a project directory and compose file:
|
|
|
|
Key decisions:
network_mode: hostavoids container networking overhead for UPnP/DLNA and simplifies hardware transcoding device access. Use a bridge network with Traefik if you need per-service networking (shown in Step 5).- Volume mounts: bind-mount your media read-only (
:ro) to prevent accidental deletion or modification from Jellyfin. - Device passthrough:
/dev/driexposes Intel or AMD iGPUs. For NVIDIA, usenvidia-container-toolkit. group_addensures the container process can access DRI render nodes. Checkgetent group videoandgetent group renderon your host for the correct GIDs.
Start the container:
|
|
Access Jellyfin at http://homeserver.local:8096 and complete
the initial setup wizard — choose your language, create the admin
account, and point to your media folders.
NVIDIA GPU Transcoding Setup
If you use an NVIDIA GPU instead of Intel QuickSync:
|
|
|
|
Enable NVIDIA NVENC in Jellyfin Admin → Playback → Transcoding → Hardware acceleration: select NVIDIA NVENC.
Step 2: Hardware Transcoding Configuration
Log into Jellyfin at http://homeserver.local:8096, go to
Administration → Dashboard → Playback → Transcoding.
For Intel QuickSync (QSV):
- Hardware acceleration: Intel QuickSync (QSV)
- Enable:
H.264,HEVC,VC1,MPEG2,VP9,AV1(if supported) - Enable: Allow encoding in HEVC format
- Enable: Allow subtitle extraction on the fly
- Enable: Enable VPP tone mapping (HDR → SDR conversion)
- Enable: Deinterlacing (hardware)
- Prefer OS native DXVA: unchecked (Linux)
For NVIDIA NVENC:
- Hardware acceleration: NVIDIA NVENC
- Enable:
H.264 (NVENC),HEVC (NVENC),AV1 (NVENC) - Check Enable hardware encoding
- Set Thread count to
0(auto) - Enable Tone mapping (NVENC handles HDR → SDR)
Verify transcoding works:
|
|
You should see lines like:
[INF] [1080p/H264] DirectPlay
[INF] [4K/HDR] Transcoding to 1080p H264 — encoder: QSV h264_qsv
If transcoding falls back to software, check:
- Container user has
videoandrendergroup membership /dev/driexists inside the container:ls -la /dev/dri- Intel GPU drivers are installed:
sudo apt install intel-media-va-driver-non-free - Verify VA-API:
sudo vainfo
Step 3: Transferring Watch History from Plex (Optional)
Jellyfin doesn’t import Plex data natively, but third-party tools make the migration painless.
Option A: jellywatch.app (Automated)
jellywatch.app provides a web-based tool that exports your Plex watch state and imports it directly into Jellyfin. It handles:
- Watched/unwatched status per user
- Ratings and review data
- Playlist migration
- Collection metadata
This is the easiest option for most users — ~10 minutes for a large library.
Option B: Plex-Trakt-Sync + Trakt (Manual)
If you already use Trakt:
|
|
Then set up the Jellyfin Trakt plugin in Admin Dashboard → Plugins → Catalog → Trakt. Configure your Trakt credentials and it backfills Jellyfin playback history from Trakt.
Option C: Direct Database Migration (Advanced)
For users comfortable with SQLite:
|
|
This copies directly at the database level — fast but comes with no warranty. Always back up both databases first.
Step 4: Arrs Integration (Sonarr / Radarr)
Jellyfin connects to Sonarr and Radarr through its API — no special plugin required.
In Sonarr (and similarly for Radarr):
- Settings → Media Management → Import Lists
- Add → Jellyfin
- Fill in:
- Server URL:
http://homeserver.local:8096 - API Key: from Jellyfin Admin Dashboard → API Keys
- Server URL:
- Test connection
Why this matters: Sonarr/Radarr can automatically scan and import new media when Jellyfin refreshes — but more importantly, the two-way integration means Sonarr removes episodes from Jellyfin’s “Continue Watching” when they’re deleted.
Recommended arrs stack:
|
|
Step 5: Traefik Reverse Proxy for Remote Access
Running on network_mode: host your media server is confined to
internal access. To expose Jellyfin securely through Traefik on
a bridge network, create a separate compose file with proper
networking:
|
|
Key details:
- WebSocket routing is required for Jellyfin’s real-time
playback sync and live TV features. Without the separate
jellyfin-wsrouter, WebSocket connections fail. JELLYFIN_PublishedServerUrlmust match your external hostname for client redirects to work correctly.- Rate limiting via
rateLimit@fileprevents the login endpoint from being brute-forced remotely.
If you run the Traefik setup, set internal_networks in
CrowdSec or your firewall rules to only allow LAN IPs
access to port 8096 directly (avoid exposing the backend
port remotely — always route through Traefik).
Step 6: Client Migration
Jellyfin has clients for virtually every platform:
| Platform | Client |
|---|---|
| Android TV / Fire TV | Jellyfin for Android TV (Play Store or direct APK) |
| Apple TV | Swiftfin (App Store) |
| LG WebOS | Jellyfin for WebOS (developer mode) |
| Samsung Tizen | Jellyfin for Tizen (developer mode) |
| Roku | Jellyfin for Roku (private channel) |
| Web Browser | https://media.yourdomain.com (direct) |
| iOS | Swiftfin or Jellyfin Mobile (App Store) |
| Kodi | Jellyfin for Kodi plugin |
| Game Consoles | PS4/5 via browser, Xbox via browser or UWP |
Most clients support Direct Play when on the same network, and gracefully fall back to transcoding over remote connections.
Post-Migration Checklist
- Verify playback: Test 4K HDR → 1080p SDR transcoding
- Check remote access: Login from external network
- Test mobile clients: Install Swiftfin on iOS/Android
- Configure backups: Back up
/opt/jellyfin/config - Set up intro skip: Install the “Scheduled Task” plugin from Admin → Plugins → Catalog → Intro Skipper
- Enable hardware acceleration exhaustively — test each codec you actually have in your library
- Disable or remove Plex once satisfied
Wrapping Up
Jellyfin is production-grade, actively maintained, and has matured significantly over the past few years. The Docker Compose setup takes under 15 minutes, hardware transcoding just works on modern Intel and NVIDIA hardware, and the arrs integration is seamless. With Plex’s lifetime pass effectively dead, there’s never been a better time to switch.
The full media stack — Jellyfin, Sonarr, Radarr, Prowlarr, qBittorrent — runs comfortably on a Proxmox LXC or VM with 4 vCPUs and 8 GB RAM, leaving hardware transcoding to the iGPU. Your future self will thank you for the subscription-free setup and the warm feeling of knowing your media server belongs entirely to you.