media-box

media-box

Docker app from devblaze's Repository

Overview

All-in-one series and movie PVR: a self-hosted Sonarr + Radarr + request-management replacement. Monitors your libraries, searches Torznab indexers, grabs via qBittorrent or TorBox, imports and renames automatically, and lets your users request media Jellyseerr-style. Migrate your existing Sonarr/Radarr libraries from Settings > Migrate. USE WITH CAUTION ON EXISTING MEDIA LIBRARIES: media-box manages files — it can move, rename, upgrade and delete media it imports. If you point it at a library that Sonarr/Radarr or your media server already manage, start safe: set Settings > Media Management > File operations to Read-only (no file changes) or Ask (every change waits for your approval on the File Changes page), and only switch to Allow once you trust what it does. PATHS: this template maps three separate shares — Downloads, Movies and TV. If Downloads is on a DIFFERENT filesystem than Movies/TV, imports COPY the file (slower, needs free space). To get instant, space-free hardlink imports, point all three at subfolders of ONE share.

media-box

media-box

A self-hosted, all-in-one PVR + media server in a single container — a replacement for Sonarr, Radarr, Bazarr, Jellyseerr, and Jellyfin. The only thing you need to bring is an indexer.


🚧 UNDER DEVELOPMENT — USE AT YOUR OWN RISK 🚧

This is an early work in progress and is NOT optimized or hardened for public / production use.
Expect rough edges, breaking changes, and bugs. If you stumbled on this and want to try it: keep backups, don't point it at data you can't afford to lose, and run it entirely at your own risk.


media-box home — Netflix-style discover with Continue Watching

What it does

  • Two libraries, one app — movies and series, metadata via TMDB.
  • Full PVR loop — monitor → RSS sync → search Torznab indexers → grab via qBittorrent or TorBox (debrid) → import (hardlink / copy / move) with template renaming → history & upgrades.
  • Release preferences — per quality profile, prefer specific groups (e.g. YIFY/YTS for movies, an anime group for anime) with automatic fallback; plus required / ignored terms (substring or /regex/).
  • Netflix-style Discover for everyday users — hero billboards, hover rows, Movies / Series / Anime categories, search with type filters, an "available only" toggle. Available titles play in-browser; the rest can be requested.
  • In-app player — direct-play with HTTP-range seeking, plus an HLS transcoder (Intel QSV/VAAPI, AMD VAAPI, NVIDIA NVENC) for anything the browser can't decode. ffprobe-populated media info.
  • Library Import — scan existing movie/series folders, auto-match to TMDB, and resolve the uncertain ones from a manual review panel.
  • Requests + roles — admins manage everything; normal users browse & request.
  • One-click migration from existing Sonarr / Radarr (library, monitored flags, quality profiles, Torznab indexers, qBittorrent clients).

Built on Next.js 16 (a single process: UI + /api/v1 + an in-process job scheduler) with SQLite/Drizzle.

Screenshots

Movie library

Movie library

Add from TMDB

Add anything from TMDB

Series management

Series management — seasons, monitoring, search

Movie management

Movie management with cast & file state

More in docs/screenshots/ — Library Import, admin settings (transcoding, RAM cache, AI assistant).


Install on Unraid (Docker template)

Easiest: media-box is available in Unraid Community Applications — open the Apps tab and search for media-box. (The CA-registered copy of the template lives in devblaze/torbox-client/templates/, the maintainer template repo — keep it in sync with unraid/media-box.xml.)

⚠️ Use with caution on existing media libraries. media-box manages files — it can move, rename, upgrade and delete media it imports. Pointing it at a library that Sonarr/Radarr or your media server already manage? Start with Settings → Media Management → File operations set to Read-only or Ask, and switch to Allow once you trust what it does.

The manual route below still works: media-box ships an Unraid Docker template at unraid/media-box.xml. The container image is published to the GitHub Container Registry (ghcr.io/devblaze/media-box).

1. Publish the image (once, and on each update)

Let CI do it (recommended). The included GitHub Actions workflow (.github/workflows/docker-publish.yml) builds linux/amd64 and pushes to ghcr.io/devblaze/media-box on every commit to main — no secrets to configure, it uses the built-in GITHUB_TOKEN.

One-time: after the first successful run, the ghcr package is private. Open the package settingsChange visibilityPublic so Unraid can pull it without a docker login.

Or build and push it yourself (docker login ghcr.io with a PAT that has write:packages):

docker buildx build --platform linux/amd64 \
  -t ghcr.io/devblaze/media-box:latest --push .

2. Install the template in Unraid

Unraid reads user templates from /boot/config/plugins/dockerMan/templates-user/. Drop unraid/media-box.xml in there and it shows up in the Add Container → Template dropdown.

SSH into your Unraid server (or open the web terminal) and fetch the template straight from the repo:

wget -O "/boot/config/plugins/dockerMan/templates-user/my-media-box.xml" \
  https://raw.githubusercontent.com/devblaze/media-box/main/unraid/media-box.xml

Then in the Unraid GUI: Docker tab → Add Container → set Template to media-box and fill in the paths below.

No SSH? Download unraid/media-box.xml, then upload it to /boot/config/plugins/dockerMan/templates-user/my-media-box.xml with any SMB/SFTP client (the flash share maps to /boot).

3. Configure the container

The template exposes these; adjust the host paths to your shares:

Setting Container path Notes
WebUI Port 7878 change the host side if it clashes
Config /config app config + SQLite DB — persist this (/mnt/user/appdata/media-box)
Downloads /downloads your download client's output share
Movies /movies movie library share
TV /tv series library share
PUID / PGID / UMASK / TZ env Unraid defaults 99 / 100 / 022
Intel/AMD GPU (optional) /dev/dri for hardware transcoding — then set Settings → Transcoding

Hardlinks vs copy: if Downloads is on a different filesystem than Movies/TV, imports copy (slower, needs free space). Point all three at subfolders of one share for instant, space-free hardlink imports (the trash-guides layout). For NVIDIA, install the Unraid Nvidia-Driver plugin and add Extra Parameters --runtime=nvidia plus NVIDIA_VISIBLE_DEVICES=all instead of the /dev/dri device.

4. First run

Open http://<unraid-ip>:7878, create the admin account, then:

  1. Settings → General — paste a free TMDB API key.
  2. Settings → Media Management — set your downloads / movies / series paths (or they seed from the DOWNLOADS_DIR / MOVIES_DIR / SERIES_DIR env vars) and add root folders.
  3. Settings → Indexers — add Torznab endpoints (Prowlarr/Jackett).
  4. Settings → Download Clients — add qBittorrent and/or TorBox.
  5. Settings → Library Import — import media you already have on disk.
  6. Optionally Settings → Migrate — import from an existing Sonarr/Radarr.

Normal (non-admin) users you create land on the Netflix-style Discover page and can play what's available or request the rest.


Updating

media-box applies its database migrations automatically on boot, so updating is just pulling a newer image:

  1. Rebuild & push a new image (step 1 above) — or let the GitHub Actions CI publish it on push to main.
  2. In Unraid: Docker tab → media-box → Force update (or Check for UpdatesUpdate). Unraid pulls the new :latest and recreates the container; /config (your DB) is preserved.

docker compose users: docker compose pull && docker compose up -d.


Non-Unraid (docker compose)

A docker-compose.yml mirrors the Unraid mapping (separate downloads/movies/tv shares, optional /dev/dri). Edit the volume paths, then docker compose up -d.


API

Everything the UI does goes through GET/POST/PUT/DELETE /api/v1/*. External tools authenticate with the X-Api-Key header (shown under Settings → General). GET /api/v1/health is unauthenticated for the container healthcheck.

Development

yarn install
yarn dev       # config + SQLite DB land in ./.config-dev
yarn test      # parser / naming / scoring test suite
yarn typecheck

Note: this repo tracks a modified Next.js 16 — read node_modules/next/dist/docs/ before changing framework-facing code (see AGENTS.md).

Install media-box on Unraid in a few clicks.

Find media-box in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for media-box Review the template variables and paths Click Install

Related apps

Details

Repository
ghcr.io/devblaze/media-box:latest
Last Updated2026-08-03
First Seen2026-08-03

Runtime arguments

Web UI
http://[IP]:[PORT:7878]
Network
bridge
Shell
sh
Privileged
false

Template configuration

WebUI PortPorttcp

Web interface port

Target
7878
Default
7878
Value
7878
ConfigPathrw

App configuration and SQLite database (persist this)

Target
/config
Default
/mnt/user/appdata/media-box
Value
/mnt/user/appdata/media-box
DownloadsPathrw

Download client output (torrents/usenet). Put on the SAME share as Movies/TV for hardlinks.

Target
/downloads
Default
/mnt/user/downloads
Value
/mnt/user/downloads
MoviesPathrw

Movie library

Target
/movies
Default
/mnt/user/movies
Value
/mnt/user/movies
TVPathrw

Series (TV) library

Target
/tv
Default
/mnt/user/tv
Value
/mnt/user/tv
PUIDVariable

User ID for file ownership

Default
99
Value
99
PGIDVariable

Group ID for file ownership

Default
100
Value
100
UMASKVariable

File creation mask

Default
022
Value
022
TZVariable

Timezone (e.g. Europe/Athens)

Default
Europe/Athens
Value
Europe/Athens
Intel/AMD GPUDevice

Pass the iGPU for hardware transcoding (Intel QuickSync / AMD VAAPI). Then set Settings &gt; Transcoding &gt; Hardware acceleration to VAAPI or QSV. Leave unset for CPU transcoding. For NVIDIA, install the Unraid Nvidia-Driver plugin and add Extra Parameters: --runtime=nvidia plus NVIDIA_VISIBLE_DEVICES.

Target
/dev/dri
Default
/dev/dri
Value
/dev/dri