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:
- Select display language
- Create an administrator account
- 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:
- Go to Dashboard > Libraries > Add Media Library
- Select content type (Movies, TV Shows, Music, etc.)
- Add the folder path (e.g.,
/media/movies) - 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:
- Go to Dashboard > Playback > Transcoding
- Select your hardware acceleration method (VAAPI, NVENC, etc.)
- For VAAPI, set the device to
/dev/dri/renderD128 - Enable hardware decoding for supported codecs
- 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:
- Go to Dashboard > Networking
- Set Public HTTPS port: 8920 (or 443 if using reverse proxy)
- Set Local HTTP port: 8096
- 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.


