Jellyfin Media Server Installation on Linux

Jellyfin is a free and open-source media server that lets you stream video, music, and photos from your Linux server to any device without subscriptions or usage tracking. With support for hardware transcoding via FFmpeg, a rich library of client apps, and active community development, Jellyfin is a compelling alternative to Plex for self-hosted media streaming.

Prerequisites

  • Ubuntu 20.04+, Debian 11+, or CentOS/Rocky 8+
  • Minimum 2 GB RAM, 4+ GB recommended for transcoding
  • Sufficient storage for your media library
  • Root or sudo access
  • For hardware transcoding: compatible GPU (Intel, NVIDIA, or AMD)

Installing Jellyfin

Ubuntu/Debian (repository method):

# Install dependencies
sudo apt install -y curl gnupg apt-transport-https

# Add Jellyfin repository
curl -fsSL https://repo.jellyfin.org/install-debuntu.sh | sudo bash

# Install Jellyfin
sudo apt install -y jellyfin

# Enable and start
sudo systemctl enable --now jellyfin

# Check status
sudo systemctl status jellyfin

CentOS/Rocky Linux:

# Add the Jellyfin repository
sudo tee /etc/yum.repos.d/jellyfin.repo <<'EOF'
[jellyfin]
name=Jellyfin Repository
baseurl=https://repo.jellyfin.org/releases/server/centos/stable/
gpgcheck=1
gpgkey=https://repo.jellyfin.org/jellyfin_team.gpg.key
enabled=1
EOF

sudo dnf install -y jellyfin
sudo systemctl enable --now jellyfin

Docker installation:

docker run -d \
  --name jellyfin \
  -p 8096:8096 \
  -p 8920:8920 \
  -v /opt/jellyfin/config:/config \
  -v /opt/jellyfin/cache:/cache \
  -v /path/to/media:/media:ro \
  --restart unless-stopped \
  jellyfin/jellyfin

Initial Setup and Library Configuration

Access the web interface at http://your-server-ip:8096 and follow the wizard:

  1. Select display language
  2. Create an administrator account
  3. Add media libraries

Organize your media directory:

# Recommended directory structure
sudo mkdir -p /media/{movies,tvshows,music,photos}

# Set permissions for Jellyfin to read media
sudo chown -R jellyfin:jellyfin /media/
# Or add jellyfin user to your media group
sudo usermod -aG your-media-group jellyfin

Add a library via the web UI:

  1. Go to Dashboard > Libraries > Add Media Library
  2. Select content type (Movies, TV Shows, Music, etc.)
  3. Add the folder path (e.g., /media/movies)
  4. Configure metadata providers and click OK

Manually trigger a library scan:

# Via the web UI: Dashboard > Libraries > Scan All Libraries
# Or via API
curl -X POST "http://localhost:8096/Library/Refresh" \
  -H "X-Emby-Token: YOUR_API_KEY"

Hardware Transcoding

Hardware transcoding dramatically reduces CPU usage when streaming to devices that can't play source formats.

Intel VAAPI (integrated graphics):

# Verify the render device exists
ls /dev/dri/
# renderD128  card0

# Add jellyfin user to the video/render group
sudo usermod -aG render,video jellyfin

# Install Intel media drivers
sudo apt install -y intel-media-va-driver-non-free vainfo

# Verify VAAPI works
vainfo

NVIDIA NVENC:

# Install NVIDIA drivers and CUDA
sudo apt install -y nvidia-driver-535

# Verify GPU is detected
nvidia-smi

# Add jellyfin user to video group
sudo usermod -aG video jellyfin

Enable hardware transcoding in Jellyfin:

  1. Go to Dashboard > Playback > Transcoding
  2. Select your hardware acceleration method (VAAPI, NVENC, etc.)
  3. For VAAPI, set the device to /dev/dri/renderD128
  4. Enable hardware decoding for supported codecs
  5. Click Save

User Management

# All user management is done via web UI: Dashboard > Users
# Create a new user:
# 1. Dashboard > Users > Add User
# 2. Set username and password
# 3. Configure library access permissions
# 4. Set max streaming bitrate if needed

Configure user permissions via API:

API_KEY="your-api-key"  # From Dashboard > API Keys

# List all users
curl -s "http://localhost:8096/Users" \
  -H "X-Emby-Token: ${API_KEY}" | jq '.[].Name'

# Get a user ID
USER_ID=$(curl -s "http://localhost:8096/Users" \
  -H "X-Emby-Token: ${API_KEY}" | jq -r '.[] | select(.Name=="username") | .Id')

Remote Access Configuration

Configure Jellyfin for external access:

  1. Go to Dashboard > Networking
  2. Set Public HTTPS port: 8920 (or 443 if using reverse proxy)
  3. Set Local HTTP port: 8096
  4. Enable Allow remote connections to this server

Nginx reverse proxy:

# /etc/nginx/sites-available/jellyfin
server {
    listen 80;
    server_name jellyfin.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    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;

    # Security headers
    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;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 600s;
    }
}
sudo ln -s /etc/nginx/sites-available/jellyfin /etc/nginx/sites-enabled/
sudo certbot --nginx -d jellyfin.example.com
sudo systemctl reload nginx

Client Apps

Jellyfin has official and community clients for all major platforms:

  • Web: Built-in at http://your-server:8096
  • Android: Jellyfin for Android (Google Play / F-Droid)
  • iOS: Jellyfin Mobile (App Store)
  • TV: Jellyfin for Android TV, Fire TV, Roku
  • Desktop: Jellyfin Media Player (cross-platform)
  • Kodi: Jellyfin for Kodi plugin

Troubleshooting

Transcoding fails or is slow:

# Check FFmpeg logs in Jellyfin
# Dashboard > Logs > Select a transcoding session log

# Verify hardware acceleration is working
sudo -u jellyfin vainfo   # for VAAPI
sudo -u jellyfin nvidia-smi  # for NVENC

# Fallback to software transcoding temporarily
# Dashboard > Playback > Transcoding > disable hardware acceleration

Media not showing in library:

# Check Jellyfin can read the files
sudo -u jellyfin ls /media/movies/

# Check file naming conventions (Jellyfin uses TheMovieDB format)
# Movies: MovieName (Year)/MovieName (Year).mkv
# TV: SeriesName/Season 01/SeriesName - S01E01.mkv

# Force rescan
sudo systemctl restart jellyfin

High memory usage:

# Limit transcoding threads
# Dashboard > Playback > Transcoding > Thread count

# Check memory usage
sudo journalctl -u jellyfin | grep -i "memory\|oom"
free -h

Conclusion

Jellyfin delivers a fully self-hosted media streaming experience with hardware transcoding support, multi-user management, and a wide ecosystem of client apps — all without subscription fees or data collection. By enabling hardware acceleration with Intel VAAPI or NVIDIA NVENC and placing the server behind an Nginx reverse proxy with TLS, you get a production-ready media server that handles multiple simultaneous streams efficiently on modest VPS hardware.