How to Set Up a Media Server with Jellyfin or Plex: A Complete Self-Hosting Guide
Both Jellyfin and Plex can be deployed as containerized media servers using Docker Compose with LinuxServer.io images, requiring only a docker-compose.yml file, persistent volumes for configuration and media libraries, and exposing ports 8096 for Jellyfin or 32400 for Plex.
The Self-Hosting-Guide repository by mikeroyal provides comprehensive documentation for deploying media servers using modern containerization practices. Whether you choose Jellyfin for its fully open-source AGPL license or Plex for its polished ecosystem, both solutions follow a similar Docker-based architecture that isolates the application from the host operating system while maintaining persistent data across updates.
Choosing Between Jellyfin and Plex
Your selection depends on licensing philosophy and specific feature requirements.
Jellyfin operates under the AGPL license, offering a fully open-source stack with no feature paywalls or telemetry. According to the README.md Jellyfin entry, it emphasizes privacy-first design and compatibility with companion tools like the Swiftfin client for Apple devices, Jellyseerr for media request management, and Intro Skipper for automated detection of opening sequences.
Plex provides a proprietary-core platform with a free tier and optional Plex Pass subscriptions. As documented in the README.md Plex Media Server section, Plex delivers a polished user interface, broad device support via official apps, and integrates with analytics tools like Tautulli for viewing statistics, Plex DupeFinder for duplicate removal, and Prometheus Exporter for metrics monitoring.
Prerequisites and Architecture
The guide recommends a standardized container architecture regardless of which server you choose.
- Docker Host: Any Linux server (bare-metal, VM, or Raspberry Pi) with Docker Engine and Docker Compose installed.
- Persistent Volumes: Mount host directories for configuration metadata, transcoding cache, and media files to ensure data survives container recreation.
- Network Ports: Reserve specific TCP ports for web interfaces and auxiliary services.
Create a dedicated project directory structure before deploying:
mkdir -p ~/media-server/{jellyfin/config,jellyfin/cache,plex/config,media}
cd ~/media-server
Jellyfin Docker Compose Configuration
Deploy Jellyfin using the linuxserver/jellyfin image. The container exposes port 8096 for HTTP traffic and 8920 for HTTPS.
version: "3.8"
services:
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
ports:
- "8096:8096"
- "8920:8920"
volumes:
- ./jellyfin/config:/config
- ./jellyfin/cache:/cache
- ./media:/media
restart: unless-stopped
The PUID and PGID values must match your host user IDs to prevent permission conflicts with mounted media libraries.
Plex Docker Compose Configuration
For Plex, use the linuxserver/plex image with the VERSION=docker environment variable to ensure Docker-compatible updates.
version: "3.8"
services:
plex:
image: lscr.io/linuxserver/plex:latest
container_name: plex
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- VERSION=docker
ports:
- "32400:32400"
- "3005:3005"
- "8324:8324"
- "32469:32469"
volumes:
- ./plex/config:/config
- ./media:/media
restart: unless-stopped
Port 32400 serves the web interface and primary streaming traffic, while ports 3005, 8324, and 32469 handle DLNA discovery and Plex Companion features.
Securing with a Reverse Proxy
The README.md Caddy section recommends terminating HTTPS at a reverse proxy rather than exposing containers directly to the internet. Deploy Caddy alongside your media server:
version: "3.8"
services:
caddy:
image: caddy:latest
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
volumes:
caddy_data:
caddy_config:
Create a Caddyfile to route domain traffic to Jellyfin:
jellyfin.example.com {
reverse_proxy jellyfin:8096
tls your@email.com
}
Replace jellyfin.example.com with your registered domain and ensure DNS A-records point to your host IP address.
Essential Companion Tools
Extend functionality with ecosystem-specific utilities documented in the Media Server section of mikeroyal/Self-Hosting-Guide.
Jellyfin Ecosystem:
- Swiftfin: Native Apple device client with enhanced UI capabilities
- Jellyseerr: Request management and user discovery platform
- Intro Skipper: Automated detection and skipping of opening sequences
Plex Ecosystem:
- Tautulli: Detailed analytics and notification system
- Plex DupeFinder: Identifies and removes duplicate library entries
- Prometheus Exporter: Metrics collection for monitoring dashboards
Maintenance and Backup Strategy
Protect your metadata and configuration by implementing automated backups. The guide suggests using Restic or Borg to snapshot the ./config volumes regularly, preserving library metadata, user watch states, and plugin configurations that would be time-consuming to reconstruct.
Enable automated image updates via Watchtower or schedule docker compose pull followed by docker compose up -d to apply security patches without manual intervention.
Summary
- Both Jellyfin and Plex deploy identically via Docker Compose using LinuxServer.io images documented in the mikeroyal/Self-Hosting-Guide.
- Jellyfin provides a fully open-source AGPL stack accessible on ports
8096(HTTP) and8920(HTTPS), while Plex uses proprietary licensing with port32400as the primary web interface. - Persistent volumes for
./configand./mediadirectories prevent data loss during container updates and allow version rollbacks. - Reverse proxy deployment with Caddy enables secure HTTPS access without modifying container network settings or exposing ports directly.
- Companion tools like Jellyseerr (Jellyfin) and Tautulli (Plex) extend functionality beyond basic streaming into media management and analytics.
Frequently Asked Questions
Which media server is better for privacy-conscious users?
Jellyfin is the superior choice for privacy according to the Self-Hosting-Guide source, as it operates under the AGPL license with no proprietary components or mandatory telemetry. All metadata scraping and user authentication occur locally without external account dependencies, whereas Plex requires account creation even for local streaming and maintains some cloud connectivity.
Can I run Jellyfin and Plex simultaneously on the same Docker host?
Yes, you can deploy both services simultaneously by assigning unique container names and ensuring port mappings do not conflict. Jellyfin uses ports 8096 and 8920, while Plex requires 32400, 3005, 8324, and 32469, allowing both stacks to coexist provided they mount separate configuration volumes to prevent data corruption.
How do I enable hardware transcoding in these Docker containers?
Configure hardware transcoding by passing device nodes through to the container. For Intel QuickSync, add /dev/dri:/dev/dri to the volumes section of your docker-compose.yml. NVIDIA GPU support requires the NVIDIA Container Toolkit and corresponding environment variables. Both LinuxServer.io images support these configurations, though you must adjust the PUID and PGID environment variables to ensure the container user has permission to access video devices.
What is the recommended backup strategy for my media server configuration?
The guide recommends using Restic or Borg to create incremental backups of the ./config directories mounted in your containers. These volumes contain irreplaceable metadata, poster artwork, and user viewing statistics. Exclude the ./media directory from these backups if you already maintain separate backups of your media files, as they consume significant storage space and can be re-ripped from source if necessary.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →