# 🎬 Jellyfin — Self-Hosted Media Server ![Jellyfin](https://img.shields.io/badge/Jellyfin-00A4DC?style=for-the-badge&logo=jellyfin&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) ![License](https://img.shields.io/badge/License-GPL--2.0-blue?style=for-the-badge) --- ## 📖 What is Jellyfin? **Jellyfin** is a free, open-source media server that puts you in full control of your media library. It is the community-driven, privacy-respecting alternative to proprietary platforms like Plex and Emby — with **no subscriptions, no tracking, and no vendor lock-in**. Jellyfin lets you collect, manage, and stream your movies, TV shows, music, live TV, photos, and books from your own server to any device, anywhere in the world. --- ## ✨ Key Features & Capabilities ### 🎥 Media Management - **Movies & TV Shows** — Organizes your video library with rich metadata, posters, fan art, trailers, and ratings pulled from online databases (TMDb, TheTVDB, etc.) - **Music** — Full music library management with MusicBrainz integration, album art, lyrics, and playlists - **Photos** — Browse and share your photo collection; supports slideshow playback - **Books & Audiobooks** — Manage eBooks and audiobooks (via plugins) - **Live TV & DVR** — Watch and record live television using an HDHomeRun tuner or compatible TV backend (Tvheadend, NextPVR) ### 📡 Streaming & Playback - **Direct Play** — Streams media in its original format with zero quality loss if the client supports it - **Transcoding** — On-the-fly conversion of media to formats compatible with any client device - **Hardware Acceleration** — Supports Intel Quick Sync, AMD AMF, NVIDIA NVENC, VA-API, and VideoToolbox for fast, low-CPU transcoding - **Adaptive Bitrate** — Automatically adjusts quality based on your network connection - **Resume Playback** — Tracks your watch progress across all devices - **SyncPlay** — Watch content simultaneously with other users in perfect sync ### 👥 User Management - **Multiple Users** — Create separate profiles with individual libraries, permissions, and parental controls - **Parental Controls** — Restrict access by content rating, hide libraries, and set PIN-protected profiles - **Guest Access** — Share your server with friends and family without giving full access - **Activity Logs** — Full audit trail of who watched what and when ### 📺 Client Support Jellyfin has official and community clients for virtually every platform: - **Web Browser** — Built-in web UI accessible from any browser - **Android & Android TV** - **iOS & Apple TV** - **Roku** - **Fire TV / Kodi** - **Samsung Tizen & LG webOS Smart TVs** - **Desktop** — Windows, macOS, Linux - **Xbox** (via browser or Kodi) ### 🔌 DLNA & Casting - DLNA server support for smart TVs and media players - Chromecast support via the web client - AirPlay via community plugins ### 🔒 Privacy & Security - **100% self-hosted** — your data never leaves your server - **No telemetry** — zero tracking or analytics by default - **Optional SSL/HTTPS** — secure your server with Let's Encrypt or custom certificates - **API-first architecture** — full REST API for automation and integrations ### 🧩 Plugin Ecosystem Extend Jellyfin with community plugins: - Open Subtitles & Subscene for automatic subtitle downloads - Fanart.tv for enhanced artwork - Ani-Sync for AniList/MyAnimeList integration - Playback reporting & statistics dashboards --- ## 🖥️ Prerequisites Before you begin, ensure you have the following installed on your **Linux** host: | Requirement | Minimum Version | Check Command | |---|---|---| | Docker Engine | 24.x+ | `docker --version` | | Docker Compose | v2.x+ (plugin) | `docker compose version` | | Available RAM | 2 GB+ | `free -h` | | Available Disk | Depends on library size | `df -h` | > ⚠️ **Linux Only:** Running Jellyfin in Docker on Windows or macOS is **not officially supported** and hardware-accelerated transcoding will not work on those platforms. Install natively on Windows/macOS instead. --- ## 📁 Recommended Directory Structure Before deploying, set up the following folder layout on your host machine: ``` jellyfin-deploy/ ├── docker-compose.yml ← The compose file from this repo ├── jellyfin/ │ ├── config/ ← Jellyfin configuration & database (auto-created) │ └── cache/ ← Transcoding cache (auto-created) └── media/ ├── movies/ ← Your movie files ├── tvshows/ ← Your TV show files └── music/ ← Your music files ``` --- ## 🚀 Installation Instructions ### Step 1 — Install Docker If Docker is not already installed, follow the official guide for your distribution: ```bash # Ubuntu / Debian (quick install) curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER # Allow your user to run Docker without sudo newgrp docker # Apply group change without logging out ``` Verify the installation: ```bash docker --version docker compose version ``` --- ### Step 2 — Clone or Download This Repository ```bash git clone https://github.com/YOUR_USERNAME/jellyfin-docker.git cd jellyfin-docker ``` Or simply create a working directory and place the provided files inside it: ```bash mkdir jellyfin-deploy && cd jellyfin-deploy # Copy docker-compose.yml and README.md here ``` --- ### Step 3 — Create Required Directories ```bash mkdir -p jellyfin/config mkdir -p jellyfin/cache mkdir -p media/movies mkdir -p media/tvshows mkdir -p media/music ``` > Your actual media files should be placed in (or symlinked from) the `media/` subdirectories, or you can update the bind mount paths in `docker-compose.yml` to point directly to where your media already lives. --- ### Step 4 — Configure `docker-compose.yml` Open `docker-compose.yml` in a text editor and customize the following: #### 4a. Set your Timezone ```yaml environment: - TZ=America/New_York # ← Change to your timezone (e.g. Europe/London) ``` Find your timezone string at: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones #### 4b. Set the Published Server URL *(optional but recommended)* ```yaml environment: - JELLYFIN_PublishedServerUrl=http://YOUR_SERVER_IP_OR_DOMAIN:8096 ``` Replace `YOUR_SERVER_IP_OR_DOMAIN` with your server's LAN IP (e.g., `192.168.1.100`) or public domain name. #### 4c. Set Media Paths By default, the compose file uses relative paths (`./media/movies`, etc.). To point at existing media folders elsewhere on your system, change the `source:` paths: ```yaml volumes: - type: bind source: /mnt/nas/movies # ← Your actual path target: /media/movies read_only: true ``` #### 4d. Set User/Group (Recommended) Find your current user's UID and GID: ```bash id # Example output: uid=1000(youruser) gid=1000(yourgroup) ``` Uncomment and update the `user:` line in `docker-compose.yml`: ```yaml user: "1000:1000" ``` This prevents Jellyfin from running as root and ensures correct file permissions. --- ### Step 5 — Start Jellyfin ```bash docker compose up -d ``` The `-d` flag runs the container in the background (detached mode). Check that it started successfully: ```bash docker compose ps docker compose logs -f jellyfin ``` --- ### Step 6 — Complete the Setup Wizard Open your browser and navigate to: ``` http://YOUR_SERVER_IP:8096 ``` You will be greeted by the **Jellyfin Setup Wizard**. Follow these steps: 1. **Create your admin account** — Set a username and password 2. **Add media libraries** — Point Jellyfin to `/media/movies`, `/media/tvshows`, `/media/music` (these are the container-side paths) 3. **Choose metadata language** — Select your preferred language for scraped info 4. **Configure remote access** — Enable if you want to access Jellyfin outside your home network 5. **Finish** — Jellyfin will begin scanning your media library immediately --- ## 🛑 Managing the Container | Action | Command | |---|---| | Start | `docker compose up -d` | | Stop | `docker compose down` | | Restart | `docker compose restart jellyfin` | | View logs | `docker compose logs -f jellyfin` | | Update image | `docker compose pull && docker compose up -d` | | Remove container & volumes | `docker compose down -v` | --- ## ⚡ Hardware Acceleration (Optional) Hardware transcoding dramatically reduces CPU usage during video playback. ### Intel / AMD (VA-API via `/dev/dri`) Uncomment the `devices` section in `docker-compose.yml`: ```yaml devices: - /dev/dri:/dev/dri ``` Then in the Jellyfin Admin Dashboard: 1. Go to **Dashboard → Playback → Transcoding** 2. Set **Hardware acceleration** to **Video Acceleration API (VAAPI)** 3. Set the VA-API device to `/dev/dri/renderD128` 4. Save and test ### NVIDIA GPU Requires the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). Add to `docker-compose.yml`: ```yaml deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] ``` Then in Jellyfin, set Hardware acceleration to **NVENC**. --- ## 🌐 Exposing Jellyfin to the Internet (Optional) ### Option A — Port Forwarding Forward TCP port `8096` on your router to your server's LAN IP. ### Option B — Reverse Proxy with HTTPS (Recommended) Use **Nginx Proxy Manager**, **Traefik**, or **Caddy** in front of Jellyfin to enable HTTPS. Example Nginx config snippet: ```nginx server { listen 443 ssl; server_name jellyfin.yourdomain.com; 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; } } ``` --- ## 🔧 DLNA Configuration (Optional) For DLNA support (smart TVs discovering Jellyfin automatically), you need host networking: ```yaml network_mode: host ``` > ⚠️ When using host networking, remove the `ports:` section entirely — host network mode exposes all ports directly. --- ## 🗂️ Backup & Restore The only directory you need to back up is `./jellyfin/config/`. This contains: - The Jellyfin database (`jellyfin.db`) - All server settings and user data - API keys and plugin configurations ```bash # Backup tar -czf jellyfin-backup-$(date +%Y%m%d).tar.gz ./jellyfin/config # Restore tar -xzf jellyfin-backup-YYYYMMDD.tar.gz ``` --- ## 🐛 Troubleshooting | Problem | Solution | |---|---| | Port 8096 not accessible | Check firewall: `sudo ufw allow 8096/tcp` | | Permission denied on media | Set correct `user: UID:GID` in compose file | | Media not appearing | Check that bind mount paths are correct; restart and re-scan | | High CPU during playback | Enable hardware acceleration; ensure Direct Play is used when possible | | Container won't start | Run `docker compose logs jellyfin` to inspect errors | --- ## 📚 Useful Links - 🏠 [Jellyfin Official Website](https://jellyfin.org) - 📖 [Official Documentation](https://jellyfin.org/docs/) - 🐳 [Docker Hub Image](https://hub.docker.com/r/jellyfin/jellyfin) - 💬 [Jellyfin Forum](https://forum.jellyfin.org) - 🔌 [Plugin Catalogue](https://jellyfin.org/docs/general/server/plugins/) - ⚡ [Hardware Acceleration Guide](https://jellyfin.org/docs/general/post-install/transcoding/hardware-acceleration) - 🛡️ [Backup & Restore Guide](https://jellyfin.org/docs/general/administration/backup-and-restore) --- ## 📜 License Jellyfin is released under the [GNU General Public License v2.0](https://github.com/jellyfin/jellyfin/blob/master/LICENSE). This deployment configuration is provided as-is for personal use. --- *Made with ❤️ for the self-hosting community*