← Back to DevBytes

How to Set Up a Home Media Server with Jellyfin

What Is Jellyfin

Jellyfin is a free, open-source media server that lets you stream your personal collection of movies, TV shows, music, and live TV to any device. It is a fully self-hosted alternative to Plex and Emby, built from the ground up without any paywalls, tracking, or external dependencies. You control every aspect of your media library, from metadata management to user accounts and transcoding settings.

Jellyfin is built on the .NET Core framework and ships as a lightweight server application that you install on a home server, NAS, old laptop, or even a Raspberry Pi. Once running, it indexes your media folders, fetches metadata from sources like TMDB and TVDB, and presents a polished web interface that works across browsers, smart TVs, smartphones, and set-top boxes.

Why Run Your Own Media Server

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Running your own media server gives you complete ownership over your content. Streaming services rotate titles, impose region restrictions, and compress quality to save bandwidth. With a home media server, your 4K Blu-ray rips stay in full quality, your curated collections never disappear, and you can watch anything you own on any device in your household — even when the internet goes down.

Jellyfin specifically matters because it is fully open-source under the GPL license. There are no premium features locked behind a subscription, no user analytics phoning home, and no centralized authentication servers that could go offline. For developers and self-hosting enthusiasts, this means complete transparency, full API access, and the ability to extend functionality through a rich plugin ecosystem.

Prerequisites and Hardware Considerations

Before installing Jellyfin, assess what hardware you have and what you need. The minimum requirements are modest, but transcoding — converting video formats on the fly to suit a client device — changes the equation significantly.

If you plan to stream primarily to modern devices that support the codecs your media uses (direct play), a Raspberry Pi 4 can serve as a capable Jellyfin server. If you need to transcode 4K HDR content for older clients, invest in a machine with hardware acceleration support.

Installation Methods

Option 1: Native Package Installation on Linux (Ubuntu/Debian)

This method installs Jellyfin directly on the system. It is straightforward and gives you full access to hardware acceleration without Docker abstraction layers.

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

# Add Jellyfin repository
curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg

echo "deb [arch=$(dpkg --print-architecture)] https://repo.jellyfin.org/$(awk -F'=' '/^ID=/{ print $NF }' /etc/os-release) $(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release) main" | sudo tee /etc/apt/sources.list.d/jellyfin.list

# Install Jellyfin
sudo apt update && sudo apt install -y jellyfin

# Enable and start the service
sudo systemctl enable jellyfin
sudo systemctl start jellyfin

# Check status
sudo systemctl status jellyfin

Once installed, Jellyfin listens on port 8096 by default. Open http://your-server-ip:8096 in a browser to begin setup.

Option 2: Docker Compose Installation

Docker offers isolation, easy updates, and portability. This is the recommended approach for most homelab setups, especially when combining Jellyfin with a reverse proxy and other services.

version: "3.8"

services:
  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    ports:
      - "8096:8096"   # HTTP web UI
      - "8920:8920"   # HTTPS (optional)
    volumes:
      - ./jellyfin/config:/config
      - ./jellyfin/cache:/cache
      - /mnt/media/movies:/media/movies:ro
      - /mnt/media/tv:/media/tv:ro
      - /mnt/media/music:/media/music:ro
    environment:
      - TZ=America/New_York
      - JELLYFIN_PUBLISHED_SERVER_URL=http://your-server-ip:8096
    devices:
      - /dev/dri:/dev/dri   # For Intel Quick Sync hardware acceleration
    group_add:
      - "44"   # video group ID for /dev/dri access (check with `getent group video`)

Place this file in a directory, then run:

docker-compose up -d

Verify the container is running with docker ps. Access the web interface at http://your-server-ip:8096.

Initial Setup Walkthrough

When you first open Jellyfin, a setup wizard guides you through essential configuration. Here is what to pay attention to at each step.

1. Create the Admin User

Set a strong username and password for the administrator account. This account has full control over server settings, user management, and library permissions. You can create additional non-admin users later for family members.

2. Configure Media Libraries

This is where you tell Jellyfin where your media lives. For each library type (Movies, Shows, Music), point Jellyfin to the mounted volume or directory containing that media. The folder structure matters — Jellyfin recognizes media more reliably when you follow standard naming conventions.

Example directory structure:

/mnt/media/movies/
  ├── Inception (2010)/
  │   └── Inception (2010).mkv
  ├── The Matrix (1999)/
  │   └── The Matrix (1999).mkv

/mnt/media/tv/
  ├── Breaking Bad/
  │   ├── Season 1/
  │   │   ├── Breaking Bad - S01E01 - Pilot.mkv
  │   │   └── Breaking Bad - S01E02 - Cat's in the Bag.mkv
  │   └── Season 2/
  │       └── Breaking Bad - S02E01 - Seven Thirty-Seven.mkv

For each library, select the content type, choose metadata providers (TMDB and TVDB are default and work well), and enable chapter image extraction if desired. Jellyfin scans the folders and begins populating artwork, descriptions, and cast information.

3. Configure Metadata Languages and Providers

Set your preferred language for metadata and artwork. You can prioritize metadata downloaders — for example, place TMDB above TVDB if you prefer their episode ordering. Enable Open Subtitles or other subtitle plugins if you want automatic subtitle fetching.

4. Enable Hardware Acceleration (Optional but Recommended)

Navigate to Dashboard > Playback > Transcoding. Choose the appropriate hardware acceleration method:

Check the box for "Enable hardware decoding for" the relevant codecs (H.264, HEVC, MPEG2, etc.) and save. To verify it works, play a media file that requires transcoding and check the dashboard for "(HW)" indicators next to the transcoding stream.

User Management and Permissions

Jellyfin lets you create individual user accounts with fine-grained access control. This is useful for households where children should see only certain content, or where you want to keep watch history separate.

# Creating a user via the Jellyfin API (useful for automation scripts)
curl -X POST "http://localhost:8096/Users/New" \
  -H "Content-Type: application/json" \
  -H "Authorization: MediaBrowser Token=YOUR_ADMIN_API_KEY" \
  -d '{
    "Name": "FamilyAccount",
    "Password": "secure-password-here",
    "Enabled": true,
    "EnableUserPreferenceAccess": true,
    "EnableRemoteAccess": true
  }'

From the web dashboard, you can then assign library access per user — restrict certain libraries to adults only, or grant read-only access to specific folders. Parental rating filters are also available based on content metadata.

Client Applications and Remote Access

Jellyfin works across a wide range of client devices:

For remote access outside your home network, you have several options:

Setting Up Nginx Reverse Proxy

This example configures Nginx with SSL (using Let's Encrypt) and optimizes connection handling for streaming:

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

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

    client_max_body_size 100M;

    location / {
        proxy_pass http://localhost: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_set_header X-Forwarded-Host $host;

        # WebSocket support for Jellyfin live updates
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Increase timeout for streaming
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
    }
}

After configuring the reverse proxy, update the JELLYFIN_PUBLISHED_SERVER_URL environment variable (or the "Published Server URL" in Dashboard > Networking) to match your public HTTPS URL.

Automating Media Organization

Keeping a clean media library structure manually becomes tedious. The Sonarr, Radarr, and Bazarr stack automates TV show management, movie management, and subtitle fetching respectively. They integrate directly with Jellyfin to notify the server when new content arrives.

Docker Compose Integration Example

# Add these services to your existing docker-compose.yml

  sonarr:
    image: linuxserver/sonarr:latest
    container_name: sonarr
    restart: unless-stopped
    ports:
      - "8989:8989"
    volumes:
      - ./sonarr/config:/config
      - /mnt/media/tv:/media/tv
      - /mnt/downloads:/downloads
    environment:
      - TZ=America/New_York

  radarr:
    image: linuxserver/radarr:latest
    container_name: radarr
    restart: unless-stopped
    ports:
      - "7878:7878"
    volumes:
      - ./radarr/config:/config
      - /mnt/media/movies:/media/movies
      - /mnt/downloads:/downloads
    environment:
      - TZ=America/New_York

In Sonarr/Radarr settings, under Connect, add a Jellyfin connection with your server URL and API key. When a download completes, the application renames and moves the file to your media folder and tells Jellyfin to refresh that library automatically.

Best Practices for a Production Home Server

Troubleshooting Common Issues

Media Not Appearing in Library

Check file permissions. Jellyfin runs as the jellyfin user on native installations or as the configured user in Docker. Ensure the user has at least read access to your media directories:

# Check permissions on media mount
ls -la /mnt/media/movies

# Fix read permissions recursively
sudo chmod -R a+r /mnt/media/movies
sudo chmod -R a+r /mnt/media/tv

Also verify your folder structure matches Jellyfin's expected conventions. Misnamed files are often ignored or matched incorrectly.

Transcoding Performance Issues

If playback stutters or the server CPU spikes, check whether hardware acceleration is actually working. In the Jellyfin dashboard during playback, look for the "(HW)" tag next to the transcode info. If absent, verify:

# Check if /dev/dri is available inside the container (Docker)
docker exec jellyfin ls -la /dev/dri

# Verify VAAPI support on the host
vainfo

# Check Intel GPU usage during transcoding
intel_gpu_top

If VAAPI fails, ensure the renderD128 device is passed through and the container has the correct group permissions (video group, typically GID 44).

Reverse Proxy WebSocket Errors

If the web interface loads but content fails to play or shows spinner indefinitely, WebSocket connections are likely being blocked. Ensure your proxy configuration includes the Upgrade and Connection headers as shown in the Nginx example above.

Conclusion

Setting up Jellyfin transforms your scattered media collection into a polished, Netflix-like streaming service that you fully control. From a simple single-machine installation to a Dockerized homelab stack with automated media pipelines, hardware-accelerated transcoding, and secure remote access, Jellyfin adapts to your technical comfort level and hardware constraints. The open-source nature means you never lose access to your data or features, and the active community ensures continuous improvement. Start with the basics — install, add a library, and play something — then layer on automation, monitoring, and remote access as your needs grow. The result is a media server that serves you exactly the way you want, on every screen you own, with no monthly fees and no compromises.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles