Skip to main content
Back to Category

Jellyfin Setup: Self-Hosted Media Server

Jellyfin Docker installation, media library configuration, hardware transcoding, user management, remote access, Nginx reverse proxy and client applications.

Read time: 14 min Self-Hosting
jellyfinmedia serverself-hostingdockerstreamingtranscoding

Table of Contents

Jellyfin Setup: Self-Hosted Media Server

Jellyfin is a free and open-source media server that lets you manage and stream your movies, TV shows, music, and photos from your own server. Unlike Plex and Emby, it is completely free and requires no subscription. You can access your media from all your devices and share it with friends.

What is Jellyfin?

Jellyfin started as an open-source fork of Emby and has grown into an independent project. Key features:

  • Completely Free: No subscription or premium features
  • Multi-Platform: Web, Android, iOS, Roku, Apple TV, Fire TV
  • Hardware Transcoding: Intel QSV, NVIDIA NVENC, AMD AMF support
  • Live TV: DVR and IPTV support
  • Multi-User: Share with family and friends
  • Metadata: Automatic movie/show info and poster downloads

System Requirements

  • Server with Docker and Docker Compose installed
  • Minimum 2 GB RAM (4 GB recommended)
  • Sufficient disk space (for media files)
  • Compatible GPU for hardware transcoding (optional)

Installation with Docker

Creating docker-compose.yml

hljs yaml
version: '3.8'

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    user: "1000:1000"
    environment:
      - JELLYFIN_PublishedServerUrl=https://jellyfin.example.com
    volumes:
      - ./config:/config
      - ./cache:/cache
      - /mnt/media/movies:/media/movies:ro
      - /mnt/media/tvshows:/media/tvshows:ro
      - /mnt/media/music:/media/music:ro
    ports:
      - "127.0.0.1:8096:8096"
    # For hardware transcoding (Intel)
    devices:
      - /dev/dri:/dev/dri
hljs bash
# Start the container
docker compose up -d

# Check logs
docker logs jellyfin -f

Mounting media directories as :ro (read-only) is recommended for security. Jellyfin doesn't need to modify media files.

Media Directory Structure

/mnt/media/
├── movies/
│   ├── Inception (2010)/
│   │   └── Inception (2010).mkv
│   └── The Matrix (1999)/
│       └── The Matrix (1999).mp4
├── tvshows/
│   └── Breaking Bad/
│       ├── Season 01/
│       │   ├── S01E01.mkv
│       │   └── S01E02.mkv
│       └── Season 02/
└── music/
    └── Artist/
        └── Album/
            └── 01 - Track.flac

Initial Configuration

After installation, go to http://SERVER_IP:8096:

  1. Select your language
  2. Create an admin account
  3. Add media libraries:
    • Type: Movies, TV Shows, Music, Photos
    • Folder: /media/movies, /media/tvshows, etc.
  4. Select metadata language
  5. Complete the setup

Library Management

Metadata Providers

Dashboard → Libraries → [Library] → Edit

For Movies:
- TheMovieDb (TMDB) - recommended
- IMDb
- The Open Movie Database

For TV Shows:
- TheTVDB - recommended
- TheMovieDb

Library Scanning

hljs bash
# Trigger manual scan (via API)
curl -X POST "http://localhost:8096/Library/Refresh" \
  -H "X-Emby-Token: API_TOKEN"

# Scheduled scan: Dashboard → Scheduled Tasks

Hardware Transcoding

Intel Quick Sync (QSV)

hljs yaml
# docker-compose.yml
services:
  jellyfin:
    devices:
      - /dev/dri:/dev/dri
    group_add:
      - "109"  # render group
hljs bash
# Verify Intel GPU is available
ls /dev/dri
# Output: card0  renderD128

# Get render group ID
stat -c '%g' /dev/dri/renderD128

Enable in Jellyfin:

Dashboard → Playback → Transcoding
→ Hardware acceleration: Intel QuickSync (QSV)
→ Enable: H.264, H.265, VP9

NVIDIA GPU

hljs yaml
# docker-compose.yml
services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=all
hljs bash
# Install NVIDIA Container Toolkit
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  tee /etc/apt/sources.list.d/nvidia-docker.list
apt update && apt install -y nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
systemctl restart docker

User Management

Creating Users

Dashboard → Users → New User
- Username and password
- Library access permissions
- Parental controls (content rating)
- Remote access permission

Parental Controls

User Settings → Parental Controls
- Maximum content rating: G, PG, PG-13, R
- Block access to specific libraries
- PIN protection

Remote Access and Nginx Proxy

Nginx Configuration

hljs nginx
server {
    listen 80;
    server_name jellyfin.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name jellyfin.example.com;

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

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    location / {
        proxy_pass http://127.0.0.1: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;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_buffering off;
        proxy_read_timeout 3600;
    }
}

Client Applications

  • Web: https://jellyfin.example.com
  • Android: Jellyfin from Google Play
  • iOS: Jellyfin from App Store
  • Kodi: Jellyfin for Kodi plugin
  • Roku: Jellyfin channel
  • Apple TV: tvOS app

Backup

hljs bash
# Backup Jellyfin configuration
tar -czf jellyfin-config-$(date +%Y%m%d).tar.gz ./config/

# Automated backup
cat > /etc/cron.weekly/jellyfin-backup << 'EOF'
#!/bin/bash
tar -czf /backups/jellyfin-$(date +%Y%m%d).tar.gz /opt/jellyfin/config/
find /backups -name "jellyfin-*.tar.gz" -mtime +60 -delete
EOF
chmod +x /etc/cron.weekly/jellyfin-backup

You can use hardware transcoding on REXE dedicated servers. Our servers with Intel or NVIDIA GPUs are ideal for 4K content.