# How to Set Up a Media Server with Jellyfin or Plex: A Complete Self-Hosting Guide

> Learn how to set up a media server with Jellyfin or Plex using Docker Compose. This guide provides a simple, complete self-hosting solution for your media.

- Repository: [Michael Royal/Self-Hosting-Guide](https://github.com/mikeroyal/Self-Hosting-Guide)
- Tags: how-to-guide
- Published: 2026-06-17

---

**Both Jellyfin and Plex can be deployed as containerized media servers using Docker Compose with LinuxServer.io images, requiring only a [`docker-compose.yml`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/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`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/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`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/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.

1. **Docker Host**: Any Linux server (bare-metal, VM, or Raspberry Pi) with Docker Engine and Docker Compose installed.
2. **Persistent Volumes**: Mount host directories for configuration metadata, transcoding cache, and media files to ensure data survives container recreation.
3. **Network Ports**: Reserve specific TCP ports for web interfaces and auxiliary services.

Create a dedicated project directory structure before deploying:

```bash
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.

```yaml
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.

```yaml
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`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/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:

```yaml
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:

```caddy
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) and `8920` (HTTPS), while **Plex** uses proprietary licensing with port `32400` as the primary web interface.
- **Persistent volumes** for `./config` and `./media` directories 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`](https://github.com/mikeroyal/Self-Hosting-Guide/blob/main/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.