Home Media Server
Your own personal streaming service. Netflix, but you're in charge.
What is a home media server?
A home media server is a computer (or even a Raspberry Pi) that stores your media -- movies, TV shows, music, books -- and streams it to any device in your house. Your phone, your TV, your tablet, a friend's laptop. It's like running your own private streaming service.
You open an app that looks and feels like Netflix. You browse your library, pick something, and hit play. It streams from your server to your device. That's it.
But the really interesting part isn't the streaming -- it's the automation. The Linux homelab community has built an incredible ecosystem of tools that work together to automatically find, download, organize, rename, and serve your media. You tell the system what you want, and it handles the rest.
The big picture
There are a lot of moving parts in a fully automated media server. Here's how they all fit together:
┌─────────────────────────────────────────────────┐
│ Overseerr / Jellyseerr │
│ (request movies & TV shows) │
└──────────────────┬──────────────────────────────┘
│ sends requests to
▼
┌─────────────────────────────────────────────────┐
│ Sonarr / Radarr / Lidarr │
│ (media management & automation) │
└──────────┬──────────────────┬────────────────────┘
│ searches │ sends downloads to
▼ ▼
┌──────────────────┐ ┌──────────────────────────┐
│ Prowlarr │ │ SABnzbd / qBittorrent │
│ (indexers) │ │ (download clients) │
└──────────────────┘ └──────────┬───────────────┘
│ completed files
▼
┌──────────────────────────┐
│ Plex / Jellyfin │
│ (media server / UI) │
└──────────────────────────┘
Don't worry if this looks like a lot. Each piece has a specific job, and we'll walk through every one of them. Here's the short version:
- Plex or Jellyfin -- the front end. This is what you actually watch stuff on. Think of it as your personal Netflix app.
- Sonarr, Radarr, Lidarr -- the brains. These "*arr" apps manage your library. You tell them what you want, and they go find it.
- Prowlarr -- the search engine. It connects to indexers (sites that catalog available content) and feeds results to the arr apps.
- SABnzbd or qBittorrent -- the download clients. These actually pull the files down from Usenet or torrent sources.
- Overseerr or Jellyseerr -- the request system. A slick web UI where you (or your friends and family) can browse and request content.
Plex vs Jellyfin
The first decision you'll make is which media server software to use. There are two main options, and both are excellent.
Plex
Plex is the most popular media server. It's polished, well-supported, and has apps on virtually every platform -- smart TVs, Roku, Apple TV, Fire Stick, iOS, Android, web browsers, game consoles.
- Free tier is fully functional for local streaming
- Plex Pass ($5/month or $120 lifetime) adds hardware transcoding, offline sync, and a few extras
- Beautiful, Netflix-like interface with automatic metadata, posters, and descriptions
- Requires a Plex account (your media stays on your server, but the app phones home)
- Proprietary software -- you're trusting Plex Inc. to keep things working
- Has been adding ad-supported free content (movies, TV) that mixes in with your library -- some people find this annoying
Jellyfin
Jellyfin is the fully open-source alternative. No accounts, no subscriptions, no ads, no telemetry. Everything runs on your server and stays on your server.
- Completely free -- no premium tier, no feature gates
- No account required -- no dependency on an external service
- Open source and community-driven
- App support is growing but not as universal as Plex (web, Android, iOS, Roku, Fire TV -- but some apps are less polished)
- Interface is clean and functional, though not quite as refined as Plex
- Hardware transcoding works out of the box with no paywall
Docker: how you'll run everything
Almost every app in this guide runs in Docker. If you haven't used Docker before, here's the quick version: Docker lets you run applications in isolated containers. Each app gets its own little environment with exactly what it needs, and they don't interfere with each other.
Think of it like running each app in its own tiny virtual machine, except way lighter and faster.
Why Docker?
- Clean installs -- apps don't pollute your system with dependencies
- Easy updates -- pull the latest image and restart. Done.
- Reproducible -- your setup is defined in a file. You can rebuild it on a new machine in minutes.
- Isolation -- if one app breaks, it doesn't take down the others
Installing Docker
On most distros, you can install Docker and Docker Compose with your package manager:
# Ubuntu / Debian / Mint
sudo apt install docker.io docker-compose-v2
# Fedora
sudo dnf install docker docker-compose
# Arch
sudo pacman -S docker docker-compose
Then add your user to the docker group so you don't need sudo every time:
sudo usermod -aG docker $USER
Log out and back in for the group change to take effect. Verify it works:
docker run hello-world
Docker Compose basics
Docker Compose lets you define multiple containers in a single YAML file. Instead of running long docker run commands, you write a docker-compose.yml file and run docker compose up -d to start everything.
Here's a minimal example that runs Jellyfin:
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
ports:
- "8096:8096"
volumes:
- ./jellyfin/config:/config
- /path/to/your/media:/media
restart: unless-stopped
Key concepts:
- image -- which software to run (pulled from Docker Hub)
- ports -- maps a port on your machine to a port inside the container (host:container)
- volumes -- maps folders on your machine to folders inside the container. This is how apps access your media and persist their config.
- restart: unless-stopped -- auto-restart if the container crashes or your machine reboots
Common commands (for a full breakdown of every docker flag, check out wtflag.wtf):
# Start all containers in the background
docker compose up -d
# Stop everything
docker compose down
# View logs
docker compose logs -f
# Update all containers to latest versions
docker compose pull && docker compose up -d
# Restart a specific container
docker compose restart jellyfin
Setting up Plex
Add this to your docker-compose.yml:
services:
plex:
image: lscr.io/linuxserver/plex:latest
container_name: plex
network_mode: host
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- VERSION=docker
volumes:
- ./plex/config:/config
- /data/media/movies:/movies
- /data/media/tv:/tv
- /data/media/music:/music
restart: unless-stopped
Start it with docker compose up -d, then open http://your-server-ip:32400/web in a browser. You'll be walked through initial setup -- sign in with your Plex account, name your server, and point it at your media folders.
id in your terminal to find your user ID and group ID. This prevents permission issues with your media files.
Setting up Jellyfin
Add this to your docker-compose.yml:
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
ports:
- "8096:8096"
volumes:
- ./jellyfin/config:/config
- ./jellyfin/cache:/cache
- /data/media/movies:/movies
- /data/media/tv:/tv
- /data/media/music:/music
restart: unless-stopped
Start it with docker compose up -d, then visit http://your-server-ip:8096. Create your admin account, add your media libraries, and you're done. No external accounts needed.
Hardware transcoding
If you want your server to convert video formats on the fly (so older devices can play newer formats), you'll want hardware transcoding. This uses your CPU's or GPU's built-in video encoder instead of doing it in software (which is painfully slow).
For Intel CPUs with Quick Sync (most Intel CPUs from the last decade), add this to your container:
devices:
- /dev/dri:/dev/dri
For NVIDIA GPUs, you'll need the NVIDIA Container Toolkit installed, then add:
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
Jellyfin gives you hardware transcoding for free. Plex requires Plex Pass.
File organization
How you organize your media files matters. Both Plex and Jellyfin (and the arr apps) expect a specific folder structure to properly identify and match your content.
Recommended structure
/data/media/
├── movies/
│ ├── The Matrix (1999)/
│ │ └── The Matrix (1999).mkv
│ ├── Inception (2010)/
│ │ └── Inception (2010).mkv
│ └── ...
├── tv/
│ ├── Breaking Bad/
│ │ ├── Season 01/
│ │ │ ├── Breaking Bad - S01E01 - Pilot.mkv
│ │ │ ├── Breaking Bad - S01E02 - Cat's in the Bag.mkv
│ │ │ └── ...
│ │ ├── Season 02/
│ │ └── ...
│ └── ...
├── music/
│ ├── Artist Name/
│ │ ├── Album Name (Year)/
│ │ │ ├── 01 - Track Name.flac
│ │ │ └── ...
│ │ └── ...
│ └── ...
└── books/
├── Author Name/
│ ├── Book Title/
│ │ └── Book Title.epub
│ └── ...
└── ...
The hardlinks trick
One important concept: when the arr apps "import" a downloaded file, they can either copy it or create a hardlink. A hardlink is like having the same file in two places without using double the disk space. The download client sees the file in its download folder, and Plex sees it in the media folder, but it's only stored once on disk.
For hardlinks to work, your downloads folder and your media folder need to be on the same filesystem. A common setup:
/data/
├── downloads/
│ ├── complete/
│ └── incomplete/
└── media/
├── movies/
├── tv/
└── music/
Then in Docker, mount the entire /data directory so all containers can see both downloads and media:
volumes:
- /data:/data
The guide series
This guide is the overview. The rest of the series dives deep into each component:
- Home Media Server -- You are here. The big picture, Plex/Jellyfin setup, Docker basics.
- The *Arr Stack -- Sonarr, Radarr, Lidarr, Readarr, Prowlarr, and Bazarr. The automation layer.
- Download Clients -- Usenet (SABnzbd, NZBGet) and torrents (qBittorrent). How to actually acquire media.
- Indexers -- How the arr apps find content. Usenet indexers, torrent trackers, and Prowlarr.
- Overseerr & Jellyseerr -- The request system. Let friends and family request content through a beautiful UI.
Start with this page to get your media server running, then work through the rest as you're ready. Each guide builds on the previous one, but you can also jump to whichever part interests you most.
Hardware recommendations
You don't need a beastly server. Here's what works at different levels:
Just getting started
- Any old PC or laptop lying around
- 4 GB RAM minimum (8 GB recommended)
- An Intel CPU with Quick Sync for hardware transcoding (most Intel CPUs from the last 10 years)
- As much storage as you can get -- an external USB drive works fine to start
More serious setup
- A small form factor PC (Intel NUC, Lenovo Tiny, Dell Optiplex Micro) -- you can find used ones for very cheap
- 16 GB RAM
- An SSD for the OS and app configs
- Large HDDs for media storage (shucked external drives are the most cost-effective)
Going all out
- A dedicated server or NAS
- 32+ GB RAM
- Multiple large HDDs in a RAID or ZFS pool for redundancy
- A dedicated GPU for transcoding (or a modern Intel CPU with excellent Quick Sync)
- 10 Gbit networking if you're streaming 4K remuxes to multiple devices
Which Linux distro?
For a media server, you want something stable and low-maintenance. Popular choices:
- Ubuntu Server -- most tutorials online assume Ubuntu. Huge community. Easy to set up.
- Debian -- rock stable, minimal. Great if you want something that just runs and never breaks.
- Proxmox -- if you want to run virtual machines and containers. Lets you separate your media server from other projects.
- Unraid -- technically not a standard Linux distro, but very popular for NAS/media server use. GUI-driven, beginner-friendly, great community. Not free (one-time license).
If you're already running a Linux desktop, you can run the entire stack right on that machine too. Docker doesn't care what distro you're on.
Next steps
You've got the overview. Your media server (Plex or Jellyfin) is running. Now it's time to automate. Head to the *Arr Stack guide to set up Sonarr, Radarr, and the rest of the automation layer.