One dashboard for your self-hosted media stack.
This is ndandan's fork of Shoshuo/Prismarr — it tracks upstream closely and adds extra integrations and dashboard features on top.
About this fork · Features · Quick start · Configuration · Upgrade · Contributing · License
Prismarr brings qBittorrent, Radarr, Sonarr, Prowlarr, Seerr and TMDb together in a single modern Symfony interface. No more juggling six tabs to manage your library.
It's not a replacement for Radarr or Sonarr - those run side by side and keep doing what they do best. Prismarr is the unified control surface: one search bar that hits the local library and TMDb, one calendar that merges movie releases and episode airs, one dashboard that surfaces what matters today (a recent download, a pending request, a trending pick), and one settings page where every API key lives - never on disk in plain text and never in environment variables.
The whole thing ships as a single Docker container with SQLite inside.
First boot opens a 7-step wizard: create the admin, plug your services in,
done. No external database, no Redis, no per-service .env files. Pull
the image, mount one volume, you're up.
Prismarr is created and maintained by Shoshuo. This repository is a personal fork of it — see below for what's different.
This fork stays close to upstream (it merges upstream regularly and keeps its code mergeable back), and everything general-purpose gets offered back as an upstream PR. What lives here:
Contributed back and merged upstream — these started here and are now part of the original project:
- Library-page performance rework (short-TTL library cache + batched
curl_multi*arr calls) — #56 - CI/workflow modernisation with fork-friendly guards — #59
- Plex activity via Tautulli (dashboard widget + full Plex Activity page) and latency-aware health chips — #60
- In-place quick-look modal on the dashboard — #61
- Plex Activity statistics, graphs and per-user filter — #62
Proposed upstream, pending — already shipped in this fork:
- Dashboard theming: 17 glance-style HSL presets with an admin Theme picker — #66
- Dashboard layout customization: reorder + hide/show sections — #68
- One unified rich detail modal everywhere (top-bar search, dashboard, Explorer, Plex activity) — #69
- Search fix: keep the global search icon from overlapping text in compact density — #70
- Performance slice: cross-request service-health caching, browser cache headers on static assets, prod cache pre-warmed at image build — #74
- Plex items open the app-global quick-look modal — #75
- Deluge tab: full torrent management via deluge-web JSON-RPC — #76
Fork-only — outside upstream's scope, only available here:
- FrankenPHP/Symfony worker mode (opt-in): an env-gated flag
(
PRISMARR_WORKER) that boots the kernel once and keeps it resident instead of rebuilding it per request. Off by default. On a real homelab it cut a health-poll response from ~46 ms to ~3 ms (~15×) and a large Films-page render from ~3.0 s to ~0.3 s (~10×); TMDb-bound pages like Discover are unchanged, as expected. See the Configuration table. - Unraid server widget: an admin-only dashboard section for the Unraid 7 GraphQL API — array and disk health, parity status with live check progress and ETA, CPU/RAM/uptime, per-container Docker status chips, and UPS state.
- Houndarr widget: a read-only dashboard stat tile for Houndarr backlog searching — tracked / eligible / cooldown / unreleased counts and 7-day searches, plus a health chip.
- UniFi Network widget: an admin-only dashboard section for the UniFi OS Network API — live WAN up/download bandwidth, client counts (wired/wireless/guest), a 24-hour usage graph, and per-device infrastructure status (gateway/switches/APs) with gateway CPU/RAM.
The full details live in docs/FORK-CHANGES.md and the CHANGELOG. The fork is run daily on a real homelab (Unraid), and every change lands through the same quality gate as upstream: PHP lint, Twig lint and the full PHPUnit suite must be green in CI before an image is published.
Everything upstream Prismarr does, plus the fork additions (marked fork):
- Movies & Series: Radarr and Sonarr libraries with five view modes, multiple instances side by side (1080p / 4K / Anime, each first-class in the UI), global
Ctrl+Ksearch and a quick-add modal with a per-instance target picker. - Unified calendar: movie and episode releases merged across instances, deduped by
tmdbId/tvdbId, with month / week / day views and iCal export. - Dashboard: hero spotlight, upcoming releases, pending Seerr requests, live service health, watchlist, trending and latest additions. Paints instantly, each widget hydrates on its own.
- Dashboard customization (fork): an admin can reorder and hide/show every dashboard section, and pick one of 17 theme presets.
- Quick-look everywhere (fork): clicking any media tile — dashboard, top-bar search result, Explorer, Plex activity — opens one rich in-place detail modal (poster, synopsis, ratings, release/air dates, watchlist, Add/Manage deep-links) instead of navigating away.
- Downloads: full qBittorrent dashboard (server-side pagination, sorting, filters, drag-and-drop upload), a full Deluge tab (live table, labels, seeding columns, detail panel, add/limits — via deluge-web JSON-RPC), plus dedicated SABnzbd and NZBGet pages. Optional Gluetun integration.
- Discovery: TMDb landing page with recommendations and trending, watchlist, an explorer with filters, and deep-links into your library.
- Plex activity (Tautulli): optional read-only page (now playing, watch stats, graphs with a per-user filter, history) plus a "Current Plex activity" dashboard widget. The API key stays server-side and responses are sanitised.
- Unraid server monitoring (fork): optional admin-only dashboard section — array/parity health with live check progress, disks, CPU/RAM, Docker containers and UPS, via the Unraid 7 GraphQL API.
- Houndarr (fork): optional dashboard stat tile with backlog-search totals and a health chip.
- UniFi network monitoring (fork): optional admin-only dashboard section — live WAN up/download, client counts (wired/wireless/guest), a 24-hour usage graph and gateway/switch/AP status, via the UniFi OS Network API.
- Preferences: theme, UI density, timezone, date format, English / French UI, settings export / import (credentials always stripped).
- Security: Symfony auth with login rate-limiter, non-root container, dynamic CSP, SSRF protection on user-provided URLs, CSRF on every mutation.
- Docker and Docker Compose
- At least one of: qBittorrent, Deluge, Radarr, Sonarr, Prowlarr, Seerr
- Optional: Gluetun if qBittorrent runs behind a VPN
- Optional: a Deluge instance (deluge-web URL + password) for the Deluge tab
- Optional: a TMDb API key (free) to enable the Discovery page
- Optional: a Tautulli instance (URL + API key) for the Plex activity page and widget
- Optional: an Unraid 7 server (GraphQL API key) for the server monitoring widget
- Optional: a Houndarr instance (URL + API key) for the backlog-search widget
| Image | What you get |
|---|---|
ghcr.io/ndandan/prismarr:latest |
This fork — upstream Prismarr plus everything listed above |
shoshuo/prismarr:latest |
The original upstream project (Docker Hub) |
The instructions below use the fork image. Both use the same volume layout,
so switching between them is just changing the image: line (back up first —
the fork may carry schema migrations upstream doesn't have yet).
Step 1. Create a file named docker-compose.yml:
services:
prismarr:
image: ghcr.io/ndandan/prismarr:latest
container_name: prismarr
restart: unless-stopped
stop_grace_period: 30s
ports:
- "7070:7070"
volumes:
- prismarr_data:/var/www/html/var/data
volumes:
prismarr_data:If you prefer host folders next to your other Servarr containers (Radarr, Sonarr, etc.) for easy browsing, replace the named volume with a bind-mount. The container target must stay at /var/www/html/var/data:
volumes:
- ./prismarr-config:/var/www/html/var/dataDrop the top-level volumes: block, and create the host folder before first start: mkdir -p ./prismarr-config.
Warning
If you write your own compose, the container target for the data volume must be /var/www/html/var/data. Prismarr does not use the Servarr /config or /app/config convention. A bind-mount on the wrong path silently creates an anonymous volume that resets on every redeploy, with no error in the logs.
Warning
Unraid: map the data volume to a dedicated subfolder on your cache pool (/mnt/cache/appdata/prismarr), not to /mnt/user/.... The /mnt/user share goes through FUSE (shfs), where session and database I/O can saturate the share. Prismarr releases the session lock early on read-only requests, which removes the worst of it, but a dedicated cache-pool subfolder (never the appdata root, so the startup chown stays scoped) remains the right mapping.
Step 2. Start the container:
docker compose up -dStep 3. Open http://localhost:7070 in your browser. The setup wizard
will guide you through:
- admin account creation
- TMDb API key (optional)
- Radarr / Sonarr / Prowlarr / Seerr URLs and keys
- qBittorrent + Gluetun, Deluge (optional)
Tautulli, Unraid and Houndarr are configured later from Settings → Services (each with its own enable toggle and Test-connection button).
APP_SECRET and MERCURE_JWT_SECRET are auto-generated on first boot and
persisted in the prismarr_data volume. No .env editing required.
Prismarr listens on 7070. To use a different port, change the left side of
the mapping in docker-compose.yml:
ports:
- "8080:7070" # access on http://localhost:8080Everything is configured from the UI:
- First boot: the 7-step setup wizard at
/setup - Later: the Settings page at
/admin/settings(admin only)
External service credentials (TMDb / Radarr / Sonarr / Prowlarr / Seerr /
Tautulli / Unraid / Houndarr API keys, qBittorrent and Deluge passwords, service URLs),
display preferences and language are stored in the SQLite database
(setting table). They never appear in environment variables or in any
committable file.
Two framework-level secrets - APP_SECRET and MERCURE_JWT_SECRET - are
auto-generated on first boot and persisted inside the volume at
var/data/.env.local. They never leave the volume; you don't have to set,
rotate or back them up manually.
| Variable | Default | Purpose |
|---|---|---|
APP_ENV |
prod |
Switch to dev for local development only |
PRISMARR_PORT |
7070 |
Internal listening port |
TRUSTED_PROXIES |
127.0.0.1,REMOTE_ADDR |
Adjust if running behind Traefik / nginx / Caddy / Cloudflare Tunnel |
TZ |
UTC |
Container time zone (e.g. Europe/Paris, Pacific/Honolulu). Drives both the OS clock and the PHP date helpers — see upstream issue #12 |
PHP_MEMORY_LIMIT |
1024M |
PHP memory ceiling per request. Bump (e.g. 2048M, -1 for unlimited) if you have a very large Radarr / Sonarr library — see upstream issue #13 |
PHP_MAX_EXECUTION_TIME |
120 |
PHP wall-time ceiling per request, in seconds. Bump alongside PHP_MEMORY_LIMIT if the films / series page times out |
PRISMARR_WORKER |
(unset) | Enables FrankenPHP/Symfony worker mode — the kernel is booted once and kept resident, skipping the per-request bootstrap for faster responses. Set to 1 (or true) for the default worker count, or to a number (e.g. 4) to run that many workers. Off by default / 0 / false = classic per-request mode; no image rebuild needed to toggle |
PRISMARR_WORKER_NUM |
(2× CPU) | Optional explicit worker-thread count; overrides the count when PRISMARR_WORKER is enabled. Leave unset to use FrankenPHP's default (2× the available CPUs) |
Everything lives in the prismarr_data Docker volume:
prismarr.db(SQLite database).env.local(auto-generated secrets)sessions/(login sessions)cache/(TMDb / cover thumbnails)avatars/(uploaded user avatars)
A standard backup is docker run --rm -v prismarr_data:/data -v $(pwd):/backup alpine tar czf /backup/prismarr-data.tgz -C /data ..
Prismarr handles HSTS and Permissions-Policy headers itself. When sitting
behind a reverse proxy that terminates TLS (Traefik, nginx, Caddy,
Cloudflare Tunnel), set TRUSTED_PROXIES to your proxy network so that
Symfony reads the right X-Forwarded-* headers.
docker compose pull
docker compose up -dSQLite migrations run automatically on container start. The prismarr_data
volume is preserved.
The fork publishes two tags to GHCR, built by GitHub Actions:
ghcr.io/ndandan/prismarr:latest— rebuilt frommain. This is the stable fork build; nothing reachesmainwithout green CI (lint + full PHPUnit suite) and a live test.ghcr.io/ndandan/prismarr:beta— pre-release builds of in-progress feature branches, used to test on a real deployment before merging.
Warning
:beta can be broken, regress features, or lose data. Do not run it on
an instance you care about, and back up the prismarr_data volume before
switching — a pre-release migration may not be reversible.
The fork does not cut versioned releases; for pinned semver tags, use the
upstream image (shoshuo/prismarr:1.x.x) — minus the fork-only features.
- Backend: PHP 8.4 / Symfony 8 / Doctrine ORM
- Server: FrankenPHP (Caddy + PHP embed; optional resident worker mode) supervised by s6-overlay
- Frontend: Tabler UI + Alpine.js + Turbo (Hotwire) via Symfony AssetMapper
- Database: SQLite (zero-config, automatic Doctrine migrations)
- Cache + sessions: filesystem (no Redis required)
- Queue: Symfony Messenger (Doctrine transport)
- Real-time: Mercure SSE built into Caddy
A single Docker container ships everything. The fork's GHCR image is built
for linux/amd64 (its target deployment is Unraid); the upstream Docker Hub
image also ships arm64 if you need ARM.
Why a fork? To add integrations the upstream project considers out of scope (Unraid server monitoring, Houndarr) and to iterate on features before proposing them upstream. Everything general-purpose is offered back as a PR — five have been merged so far, and several more are open.
Will this fork drift away from upstream? No — staying mergeable is an explicit goal. Upstream changes are merged in regularly, upstream-origin code is left untouched even when fork changes obsolete it, and fork features are built to sit on top rather than rewrite.
Does Prismarr need internet access? Only for TMDb (cover art, metadata, discovery) and the services you point it at. The app itself works fully on a LAN; if you don't configure TMDb, the Discovery page is the only feature that goes dark.
Can I run it behind a reverse proxy?
Yes. Set TRUSTED_PROXIES to your proxy network (see Configuration).
HSTS and Permissions-Policy headers are emitted by the embedded Caddy.
Where are my API keys stored? Is it safe?
In the SQLite database (table setting). The database lives in the
prismarr_data Docker volume, never in environment variables, never
in any file under version control. The export feature strips every
key matching api_key, password or secret so accidentally
sharing your config is safe.
How do I back up my install?
Snapshot the prismarr_data Docker volume (one-liner in the
Configuration section). It contains the SQLite DB, the auto-generated
secrets, sessions, cache and avatars - everything needed to restore.
Can I switch between the fork image and the upstream image? Yes, they share the same volume layout — but back up first. The fork can carry database migrations upstream doesn't have yet, and a downgrade across a migration may require restoring the backup.
- Improvements to core Prismarr are best opened against upstream so every user benefits — that's where this fork sends its own general-purpose work.
- Issues and PRs about fork-only features (Unraid widget, Houndarr widget, anything in FORK-CHANGES.md) are welcome here.
The upstream contributor docs apply to this fork too: CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md (no public issues for vulnerabilities).
Before any commit: make check (PHP lint + Twig lint + full PHPUnit suite).
AGPL-3.0 - you may use, modify and redistribute Prismarr freely, including in self-hosted production. Derivatives must remain open source under the same license. This fork inherits and keeps the upstream license.
- Shoshuo — Prismarr's author and maintainer. The overwhelming majority of this codebase is their work; the original project lives at Shoshuo/Prismarr, with a Discord and a Buy Me a Coffee page if you'd like to support it.
- Overseerr / Seerr and the Servarr family (Radarr, Sonarr, Prowlarr, Bazarr…) for the inspiration.
- Tabler for the UI kit.
- Tautulli, Houndarr and the Unraid API for the services the fork integrates.
The upstream project documents its AI usage in the original README; that note covers the bulk of this codebase and stands as written.
The fork's additions (Tautulli, quick-look, themes, layout customization, Unraid and Houndarr widgets, the performance work) were built with heavy use of Claude Code (Anthropic), with the fork maintainer directing the design, reviewing the changes, and verifying each feature live on a real deployment before it ships. Nothing lands without green CI: PHP lint, Twig lint and the full PHPUnit suite.












