Skip to content

Phase 5 — Media Library

Goal: Set up a self-hosted streaming platform on the mini PC that lets you and your family watch movies and TV shows on demand, with an automated pipeline for finding and downloading requested content.

Time estimate: 3–4 hours
What you need: Mini PC running Windows, home network access, Cloudflare tunnel token (saved in Phase 4), Backblaze B2 keys (saved in Phase 7 prep)
Prerequisites: Phase 1 complete (UNAS2 with Media_Library share), Phase 4 complete (Tailscale on mini PC), Cloudflare tunnel created


Stack Overview

App Role Status
Jellyfin Streaming server — what family watches ✅ Active (v10.11.x)
Seerr Request portal — what family uses to request ✅ Active (replaces Overseerr)
Radarr Automated movie monitoring and grabbing ✅ Active
Sonarr Automated TV show monitoring and grabbing ✅ Active
Prowlarr Torrent indexer manager ✅ Active
qBittorrent Download client ✅ Active

Why Seerr and not Overseerr or Jellyseerr? Overseerr was originally Plex-only. Jellyseerr was a fork that added Jellyfin support. The two teams merged into a single project called Seerr — the unified successor to both. Both Overseerr and Jellyseerr are now officially deprecated. Seerr runs on the same port (5055) and has identical integration with Radarr, Sonarr, and Jellyfin.


Architecture

Family requests via Seerr (request.ahanabipin.in)
              ↓
       Radarr / Sonarr
       (monitors & grabs)
              ↓
           Prowlarr
       (finds on indexers)
              ↓
         qBittorrent
         (downloads)
              ↓
   Z:\Movies or Z:\TV on UNAS2
              ↓
           Jellyfin
     (streams to everyone)
              ↓
   watch.ahanabipin.in
   (family watches)

All six services run as Docker containers on the mini PC. Media files live on the UNAS2 (Media_Library share) mapped as Z:\ — the mini PC is the brain, UNAS2 is the storage.


Step 1 — Configure Windows for 24/7 Server Use

Before installing anything, configure Windows so it never sleeps or restarts unexpectedly.

Disable sleep: 1. Settings → System → Power & Sleep 2. Set all options to Never

Disable automatic restarts for updates: 1. Settings → Windows Update → Advanced Options 2. Toggle off Restart this device as soon as possible 3. Set Active hours to cover most of your day (e.g. 7am–11pm)

Enable auto-login (so mini PC recovers after any reboot): 1. Press Win+R → type netplwiz → Enter 2. Uncheck Users must enter a username and password 3. Enter your Windows password when prompted → OK


## Step 2 — Map UNAS2 Media_Library as Network Drive Z:\

  1. Open File Explorer
  2. Right-click This PCMap network drive
  3. Configure:
  4. Drive letter: Z:
  5. Folder: \\192.168.1.2\Media_Library
  6. Tick Reconnect at sign-in
  7. Tick Connect using different credentials
  8. Enter your File Service Credentials when prompted
  9. Confirm Z:\ appears in File Explorer

Create required subfolders on Z:\:

Z:\
├── Movies\
├── TV\
└── Downloads\
    ├── Complete\
    └── Incomplete\

Step 3 — Install Docker Desktop

  1. Go to docker.com/products/docker-desktop
  2. Download Docker Desktop for Windows
  3. Run the installer — accept all defaults
  4. Ensure Use WSL 2 instead of Hyper-V is selected
  5. Restart when prompted
  6. After restart, wait for Docker Desktop to show Engine running (green dot in system tray)
  7. Go to Docker Desktop → Settings → General → tick Start Docker Desktop when you log in

Verify:

docker --version

You should see Docker version 2x.x.x


Step 4 — Create the Docker Compose File

Create this folder structure on the mini PC:

C:\docker\mediastack\
├── docker-compose.yml
└── config\
    ├── jellyfin\
    ├── seerr\
    ├── radarr\
    ├── sonarr\
    ├── prowlarr\
    └── qbittorrent\

Create folders via Command Prompt:

mkdir C:\docker\mediastack\config\jellyfin
mkdir C:\docker\mediastack\config\seerr
mkdir C:\docker\mediastack\config\radarr
mkdir C:\docker\mediastack\config\sonarr
mkdir C:\docker\mediastack\config\prowlarr
mkdir C:\docker\mediastack\config\qbittorrent

Create C:\docker\mediastack\docker-compose.yml:

version: "3.8"

services:

  jellyfin:
    image: jellyfin/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    ports:
      - "8096:8096"
    volumes:
      - C:\docker\mediastack\config\jellyfin:/config
      - Z:\Movies:/media/movies
      - Z:\TV:/media/tv
    environment:
      - TZ=Asia/Kolkata

  seerr:
    image: ghcr.io/seerr-team/seerr:latest
    container_name: seerr
    restart: unless-stopped
    ports:
      - "5055:5055"
    volumes:
      - C:\docker\mediastack\config\seerr:/app/config
    environment:
      - TZ=Asia/Kolkata

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: radarr
    restart: unless-stopped
    ports:
      - "7878:7878"
    volumes:
      - C:\docker\mediastack\config\radarr:/config
      - Z:\Movies:/movies
      - Z:\Downloads\Complete:/downloads
    environment:
      - TZ=Asia/Kolkata
      - PUID=1000
      - PGID=1000

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: sonarr
    restart: unless-stopped
    ports:
      - "8989:8989"
    volumes:
      - C:\docker\mediastack\config\sonarr:/config
      - Z:\TV:/tv
      - Z:\Downloads\Complete:/downloads
    environment:
      - TZ=Asia/Kolkata
      - PUID=1000
      - PGID=1000

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    restart: unless-stopped
    ports:
      - "9696:9696"
    volumes:
      - C:\docker\mediastack\config\prowlarr:/config
    environment:
      - TZ=Asia/Kolkata
      - PUID=1000
      - PGID=1000

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    restart: unless-stopped
    ports:
      - "8080:8080"
      - "6881:6881"
      - "6881:6881/udp"
    volumes:
      - C:\docker\mediastack\config\qbittorrent:/config
      - Z:\Downloads\Complete:/downloads/complete
      - Z:\Downloads\Incomplete:/downloads/incomplete
    environment:
      - TZ=Asia/Kolkata
      - PUID=1000
      - PGID=1000
      - WEBUI_PORT=8080

Start all containers:

cd C:\docker\mediastack
docker compose up -d

First run pulls all images — takes 5–10 minutes. Verify all running:

docker compose ps

All six should show status Up.


Step 5 — Configure qBittorrent

  1. Open http://localhost:8080
  2. Default login: username admin, password adminadmin
  3. Go to Tools → Options → Downloads
  4. Default save path: /downloads/complete
  5. Incomplete torrents: /downloads/incomplete
  6. Go to Tools → Options → Web UI
  7. Change default password immediately
  8. Go to Tools → Options → BitTorrent
  9. Set upload speed limit to ~70% of your upload bandwidth to avoid saturating your home internet during downloads

Step 6 — Configure Prowlarr

  1. Open http://localhost:9696
  2. Complete setup wizard — set username and password
  3. Go to Indexers → Add Indexer
  4. Add public indexers — commonly used: 1337x, YTS (for movies), RARBG mirrors, EZTV (for TV)
  5. Add any Malayalam/regional content indexers if needed
  6. Go to Settings → Apps → Add Application
  7. Add Radarr: URL http://radarr:7878 API key: found in Radarr → Settings → General → API Key
  8. Add Sonarr: URL http://sonarr:8989 API key: found in Sonarr → Settings → General → API Key
  9. Test both connections — confirm green tick

Step 7 — Configure Radarr

  1. Open http://localhost:7878
  2. Complete setup — set username and password
  3. Go to Settings → Media Management
  4. Root folder: /movies (maps to Z:\Movies)
  5. Go to Settings → Download Clients → Add → qBittorrent
  6. Host: qbittorrent
  7. Port: 8080
  8. Username and password: your qBittorrent credentials
  9. Category: radarr
  10. Test → confirm success → Save
  11. Go to Settings → Profiles
  12. Configure quality profile — HD-1080p recommended as default

Step 8 — Configure Sonarr

  1. Open http://localhost:8989
  2. Complete setup — set username and password
  3. Go to Settings → Media Management
  4. Root folder: /tv (maps to Z:\TV)
  5. Go to Settings → Download Clients → Add → qBittorrent
  6. Same settings as Radarr above
  7. Category: sonarr
  8. Test → confirm success → Save
  9. Configure quality profiles as desired

Step 9 — Configure Jellyfin

  1. Open http://localhost:8096
  2. Complete initial setup wizard:
  3. Language: English
  4. Create admin user: your name + strong password
  5. Add media libraries:
    • Movies → browse to /media/movies
    • TV Shows → browse to /media/tv
  6. Let Jellyfin scan and build its library
  7. Go to Dashboard → Playback → Transcoding
  8. Enable hardware acceleration — select Intel QuickSync or NVENC depending on your mini PC's GPU
  9. Create user accounts for family:
  10. Dashboard → Users → Add User
  11. One account per family household
  12. Simple password — easy to type on a TV remote

Jellyfin 10.11.x note: This is a major release with significant database changes. If you ever upgrade from an earlier version, read the release notes carefully before upgrading and take a full backup first. Fresh installs are unaffected.


Step 10 — Configure Seerr

Seerr is the request portal your family uses to request new movies and shows. It replaces both Overseerr (Plex-only) and Jellyseerr (Jellyfin fork) as the unified successor to both.

  1. Open http://localhost:5055
  2. Click Sign In with Jellyfin
  3. Jellyfin URL: http://jellyfin:8096
  4. Sign in with your Jellyfin admin credentials
  5. Import your Jellyfin users — Seerr syncs all accounts
  6. Go to Settings → Services → Radarr → Add
  7. URL: http://radarr:7878
  8. API key: from Radarr → Settings → General
  9. Set default quality profile and root folder (/movies)
  10. Test → Save
  11. Go to Settings → Services → Sonarr → Add
  12. URL: http://sonarr:8989
  13. API key: from Sonarr → Settings → General
  14. Set default quality profile and root folder (/tv)
  15. Test → Save
  16. Configure request limits per user if desired (Settings → Users → select user → Request limit)

Step 11 — Install and Activate Cloudflare Tunnel

This makes Jellyfin and Seerr accessible to family via watch.ahanabipin.in and request.ahanabipin.in without any port forwarding on your ISP router.

  1. Download cloudflared-windows-amd64.msi from: developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads
  2. Run the installer
  3. Open Command Prompt as Administrator
  4. Paste and run the tunnel install command saved in your password manager during Phase 4: cmd cloudflared.exe service install eyJhIjoiNWFiN...
  5. Go to Cloudflare → Networking → Tunnels → confirm ahanabipin-home shows as Healthy

Verify: - https://watch.ahanabipin.in → Jellyfin loads ✅ - https://request.ahanabipin.in → Seerr loads ✅


Step 12 — Complete Tailscale Subnet Routing

(If not done already as part of Phase 4)

  1. Open Command Prompt as Administrator on the mini PC
  2. Run: cmd tailscale up --advertise-routes=192.168.1.0/24
  3. Go to login.tailscale.com
  4. Find the mini PC → ...Edit route settings
  5. Approve the 192.168.1.0/24 subnet route
  6. On both phones → Tailscale app → Settings → enable Accept routes

Test from your phone on mobile data (WiFi off) — try connecting to smb://192.168.1.2 in a file manager. You should be able to browse the NAS remotely.


Step 13 — Configure Startup Behaviour

Service How it auto-starts
Docker containers restart: unless-stopped in docker-compose.yml
Docker Desktop Enabled in Docker Desktop Settings → General
Cloudflare Tunnel Installed as Windows service — starts automatically
Tailscale Enable in Tailscale system tray → Settings → Run on startup
Network drive Z:\ Reconnect at sign-in option set during mapping

Network drive timing issue: Windows sometimes starts Docker before Z:\ reconnects after a reboot. If containers fail to start after a reboot, open Command Prompt and run: cmd cd C:\docker\mediastack docker compose restart


Service URLs Reference

Local (mini PC only):

Service URL
Jellyfin http://localhost:8096
Seerr http://localhost:5055
Radarr http://localhost:7878
Sonarr http://localhost:8989
Prowlarr http://localhost:9696
qBittorrent http://localhost:8080

External (accessible from anywhere):

Service URL Who
Jellyfin https://watch.ahanabipin.in Family streaming
Seerr https://request.ahanabipin.in Family requests

Verification Checklist

  • [ ] Windows power settings configured — no sleep, no auto-restart
  • [ ] Auto-login enabled on Windows
  • [ ] UNAS2 mapped as Z:\ with Movies\, TV\, Downloads\ subfolders
  • [ ] Docker Desktop installed and running
  • [ ] All 6 containers running (docker compose ps shows all Up)
  • [ ] qBittorrent configured with correct paths and new password
  • [ ] Prowlarr configured with indexers and connected to Radarr + Sonarr
  • [ ] Radarr configured — root folder /movies, download client set
  • [ ] Sonarr configured — root folder /tv, download client set
  • [ ] Jellyfin set up with movie and TV libraries, family accounts created
  • [ ] Seerr connected to Jellyfin, Radarr, and Sonarr
  • [ ] Cloudflare Tunnel active — showing Healthy in dashboard
  • [ ] watch.ahanabipin.in loading Jellyfin ✅
  • [ ] request.ahanabipin.in loading Seerr ✅
  • [ ] Tailscale subnet routing configured and tested
  • [ ] Remote NAS access confirmed on mobile data
  • [ ] All services confirmed to restart after a Windows reboot

Troubleshooting

Docker containers not starting:

docker compose logs [container_name]

Most common cause: Z:\ not mapped before Docker starts. Map the drive, then run docker compose restart.

Jellyfin not finding media: Confirm files are in Z:\Movies or Z:\TV. Trigger a manual scan: Dashboard → Libraries → Scan all libraries.

qBittorrent Web UI not accessible: Confirm container is running. Check no other app uses port 8080.

Cloudflare Tunnel showing Inactive: Open Windows Services (services.msc) → find Cloudflare Tunnel → confirm Running. If Stopped, right-click → Start.

Seerr not connecting to Radarr/Sonarr: Use container names as hostnames (radarr, sonarr) not localhost — containers reference each other by name within the Docker network, not by localhost.

Seerr image not found on first pull: Confirm the image name is exactly ghcr.io/seerr-team/seerr:latest — GitHub Container Registry requires the full path. If unavailable, check github.com/seerr-team/seerr for the current image name as it may have updated.

Family members can't log in to Jellyfin: Reset via Dashboard → Users → select user → Reset Password. Passwords are case sensitive.

Video buffering for remote viewers: 1080p needs ~8–10 Mbps upload per viewer. In Jellyfin → Dashboard → Playback, set a remote streaming bitrate limit (e.g. 10 Mbps).

Z:\ drive not reconnecting after reboot: Run docker compose restart after login. Consider adding a startup script that waits 30 seconds then runs this command automatically.


Future Addition — Recommendarr (Optional)

Once the stack is running smoothly, consider adding Recommendarr — an AI-powered recommendation engine that analyses your Jellyfin library and suggests what to watch next. It integrates directly with Jellyfin and can be added as a seventh Docker container. Not essential but a nice quality-of-life addition for active users.


Phase 5 complete. Proceed to Phase 6 — Family Onboarding.