Prismarr

Prismarr

Docker app from Prismarr's Repository

Overview

One dashboard for your self-hosted media stack. Prismarr brings qBittorrent, Radarr, Sonarr, Prowlarr, Seerr and TMDb together in a single modern interface: unified Ctrl+K search, a merged movie/episode calendar, a dashboard that surfaces what matters today, and one settings page where every API key lives (stored in SQLite, never in environment variables). Ships as a single container with SQLite inside, no external database and no Redis. First boot opens a 7-step setup wizard: create the admin, plug your services in, done. IMPORTANT: the data volume must map to /var/www/html/var/data (Prismarr does NOT use the Servarr /config convention). All credentials are configured from the UI and kept in the database.

Prismarr

One dashboard for your self-hosted media stack.

Latest release CI Docker pulls Image size Stars Last commit Discord Buy Me a Coffee

AGPL-3.0 PHP 8.4 Symfony 8 FrankenPHP 1.3 SQLite

Features · Quick start · Configuration · Upgrade · What's next · Support · License · AI


Prismarr showcase

Static screenshots (click to expand)

Dashboard Discover

Calendar Movies (Radarr)

Series detail (Sonarr) Downloads (qBittorrent)

Settings (custom theme)


About

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.


Project status

Prismarr is maintained by a single developer (for now) in spare time. The codebase is production-ready - I run it on my own homelab daily - but support, bug fixes and new features land when I have the bandwidth. There is no SLA, no commercial backing and no team behind this.

That said, I actively welcome and encourage feedback. Feature requests, bug reports, code reviews, UI critiques, design ideas, translations - if you take the time to write something, I'll take the time to read it carefully and reply. Open an issue, drop a PR, or just tell me what's missing or what could be better. Outside contributors are exactly how a solo project becomes a real one, and I'd love that to happen.

The CHANGELOG is kept up to date, and the public Kanban shows what's in progress, what's planned for the next release and what's queued for later.


Features

  • 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+K search 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.
  • Downloads: full qBittorrent dashboard (server-side pagination, sorting, filters, drag-and-drop upload) 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, history) plus a "Current Plex activity" dashboard widget. The API key stays server-side and responses are sanitised.
  • 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.

Quick start

Requirements

  • Docker and Docker Compose
  • At least one of: qBittorrent, Radarr, Sonarr, Prowlarr, Seerr
  • Optional: Gluetun if qBittorrent runs behind a VPN
  • Optional: a TMDb API key (free) to enable the Discovery page

Install

Step 1. Get a docker-compose.yml file. Pick one of the two options below.

Option A — Copy-paste

Create a file named docker-compose.yml with the following content:

services:
  prismarr:
    image: shoshuo/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:

Option B — Download

wget -O docker-compose.yml https://raw.githubusercontent.com/Shoshuo/Prismarr/main/docker-compose.example.yml

(or curl -O https://raw.githubusercontent.com/Shoshuo/Prismarr/main/docker-compose.example.yml && mv docker-compose.example.yml docker-compose.yml)

Option C: Bind-mount (Servarr-style layout)

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/data

Drop the top-level volumes: block from Option A, and create the host folder before first start: mkdir -p ./prismarr-config.

[!warning] If you write your own compose instead of using a template above, 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 Prismarr's session and database I/O can saturate the share and, in the worst case, lock up the whole server. Always point it at a dedicated subfolder (never the appdata root) so the container's startup chown stays scoped to Prismarr's own data.


Step 2. Start the container:

docker compose up -d

Step 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 (optional)

APP_SECRET and MERCURE_JWT_SECRET are auto-generated on first boot and persisted in the prismarr_data volume. No .env editing required.

Default port

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:8080

Configuration

Everything 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 API keys, qBittorrent password, 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.

Environment variables (optional)

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 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 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

Persistent data

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 ..

Reverse proxy

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.


Upgrade

docker compose pull
docker compose up -d

SQLite migrations run automatically on container start. The prismarr_data volume is preserved.

To pin a specific version instead of latest:

services:
  prismarr:
    image: shoshuo/prismarr:1.0.0

Testing pre-release builds

shoshuo/prismarr:beta is the unreleased work-in-progress build of main.

/!\ No stability guarantee /!\

:beta can be broken, regress features, or lose data. It is not held to the quality bar of :latest, and there is no promise it works as well, or at all. Do not run it on an instance you care about.

You only ever get :beta if you explicitly set image: shoshuo/prismarr:beta in your compose file. The :beta tag is built separately and never touches :latest, so users on :latest (including with Watchtower or other auto-pull setups) stay on stable. If you do opt into :beta, auto-pull will keep fetching fresh pre-release builds, which is usually what a tester wants.

If you still want to help test it:

  • Back up your prismarr_data volume before switching, and again before each :beta pull. A pre-release database migration may not be safely reversible, so going back to :latest can require restoring that backup.
  • Report problems on the issue tracker with a [beta] prefix in the title, including the version shown on Settings → Updates and docker logs prismarr.

What's next

Everything lives on the public Kanban: what's in progress, what's planned for the next release, and what's parked for later.


Support and community

Prismarr is built by one person in spare time. Two ways to be part of it:

  • Join the Discord to ask for help, report issues, share setups, or follow what's coming next.
  • Buy me a coffee if Prismarr is useful to you and you'd like to support the time that goes into it. Entirely optional, and every bit is appreciated.

For anything that needs tracking (bugs, feature requests), GitHub issues and pull requests stay the right place. See Contributing.


Tech stack

  • Backend: PHP 8.4 / Symfony 8 / Doctrine ORM
  • Server: FrankenPHP (Caddy + PHP embed, 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 image is ~282 MB and runs on amd64 and arm64.


FAQ

Why PHP / Symfony? Because the developer (me) is comfortable with it and Symfony 8 lets a solo dev ship a polished, testable, batteries-included web app fast. The runtime is FrankenPHP in worker mode, so the per-request overhead is small. Performance is a non-issue at homelab scale.

ARM / Raspberry Pi support? Yes. The image is built for linux/amd64 and linux/arm64. It runs on a Raspberry Pi 4/5, an Apple Silicon Mac, or any arm64 NAS.

Does Prismarr need internet access? Only for TMDb (cover art, metadata, discovery) and the Servarr 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 contribute a translation in another language? Yes - duplicate symfony/translations/messages+intl-icu.en.yaml to your locale (e.g. messages+intl-icu.de.yaml), translate, and open a PR. The setup wizard will pick up the new locale automatically.


Contributing

Contributions are welcome - please open an issue first to discuss the scope before submitting a PR.

Before any commit: make check (PHP lint + Twig lint + full PHPUnit suite).


License

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.


Acknowledgements

Inspired by the remarkable work of:

And, on a more personal note: thank you to my friends and family for the patience, the encouragement, and for asking "so when does it ship?" often enough to keep me going. This release is for you.


Star history

Star history


Note on AI usage

Prismarr is a solo project. I make the calls on what to ship, what to drop, how things plug together. The bugs are on me too. Claude Code (Anthropic) helped me move faster on the chunks listed below; the rest is mine.

To stay transparent, here are the concrete areas where it was actively helpful:

Primary uses

  • i18n translation and key wiring - English isn't my native language; Claude handled the bulk of the EN/FR YAML files (4 188 keys on each side, kept in exact parity) and the trans() call sites in PHP and Twig.
  • Log and JavaScript debugging - faster triage of stack traces, Turbo/Alpine quirks, and front-end edge cases I couldn't reproduce locally.
  • API endpoint cataloguing - mapping the ~600 endpoints across Radarr v3, Sonarr v3, Prowlarr v1, Seerr, qBittorrent v2 and TMDb v3 from their OpenAPI specs.
  • Code audits - flagging missed translations, forgotten edge cases and bugs in my own code.
  • SVG icons and illustrations - generating and tweaking inline SVGs (logo variants, empty-state illustrations, status icons) when no off-the-shelf asset matched.

Secondary uses

  • PHPUnit test debugging - turning failing assertions into readable diffs.
  • Mobile responsive design - tightening the calendar week/day views, sidebar collapse and dashboard widget grids on phones.
  • Security review and hardening - second-opinion checks on SSRF guards, CSP, CSRF tokens, XSS, SQL/XML injection patterns, profiler exposure.
  • Documentation translation and polish - README, CHANGELOG, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT in both English and French.
  • Local commit messages and the private PROGRESSION.md log - keeping the per-session journal readable. That file lives only on my machine and is never pushed to GitHub.
  • Single-container Docker design - the FrankenPHP + s6-overlay layout that supervises the web server and the messenger worker.

Nothing landed without me reading it, running it, and watching make check go green (PHP lint + Twig lint + full PHPUnit). Claude is a tool I leaned on, not a co-author.

Install Prismarr on Unraid in a few clicks.

Find Prismarr 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 Prismarr Review the template variables and paths Click Install

Download Statistics

18,069
Total Downloads

Related apps

Details

Repository
shoshuo/prismarr:latest
Last Updated2026-06-09
First Seen2026-06-09

Runtime arguments

Web UI
http://[IP]:[PORT:7070]/
Network
bridge
Shell
sh
Privileged
false
Extra Params
--stop-timeout=30

Template configuration

WebUI PortPorttcp

HTTP port Prismarr listens on.

Target
7070
Default
7070
Value
7070
DataPathrw

Persistent data: SQLite DB, auto-generated secrets, sessions, cache, avatars. Container target MUST stay /var/www/html/var/data.

Target
/var/www/html/var/data
Default
/mnt/user/appdata/prismarr
Value
/mnt/user/appdata/prismarr
TZVariable

IANA timezone for the clock and date helpers, e.g. Europe/Paris. Falls back to UTC if unset.

Default
UTC
Value
UTC
PHP_MEMORY_LIMITVariable

PHP memory ceiling per request. Bump (e.g. 2048M, or -1 for unlimited) for very large Radarr/Sonarr libraries.

Default
1024M
Value
1024M
PHP_MAX_EXECUTION_TIMEVariable

PHP wall-time ceiling per request, in seconds. Bump alongside PHP_MEMORY_LIMIT if the films/series page times out.

Default
120
Value
120
TRUSTED_PROXIESVariable

Set to your reverse-proxy network (Traefik, nginx, Caddy, Cloudflare Tunnel) so Symfony reads the right X-Forwarded-* headers. Leave empty otherwise.