Skip to content

Repository files navigation

Polarr — self-hosted music discovery, requests, and streaming

Polarr is a homeserver music hub: point it at Lidarr (same pattern as Seerr → Sonarr/Radarr), request missing music, optionally fall back to a Downtify-inspired yt-dlp acquirer, and stream from the web UI.

Packaging targets the Umbrel App Store model: browser first-run, Docker runtime, persisted volumes, no SSH setup.

Stack

Layer Choice
Web + API Next.js (App Router)
UI shadcn-style components + Tailwind
Config / library DB SQLite (better-sqlite3, WAL) — tracks, requests lifecycle, downloads, events
Music manager Lidarr API
Fallback acquire yt-dlp + ffmpeg (container includes both)
Umbrel host port 3647

Local dev

npm install
npm run dev

Open http://localhost:3000. Complete the setup wizard (admin account + optional Lidarr URL/API key).

Fallback (Downtify-style) downloads land under POLARR_DOWNLOADS_DIR and are streamable by default once the file is on disk — no extra import step.

Environment variables:

Variable Default Purpose
POLARR_DATA_DIR ./data SQLite + app state
POLARR_MUSIC_DIR ./music Library root to scan
POLARR_DOWNLOADS_DIR ./music/downloads Fallback download output

Optional: install yt-dlp and ffmpeg for fallback acquisition outside Docker.

Docker (local)

docker compose up --build
# or with BuildKit local cache (faster rebuilds):
npm run docker:build:fast

App: http://localhost:3647
Health: http://localhost:3647/api/v1/status

Production images publish from polarr-app as ghcr.io/kevinguest/polarr-app.

Image build notes (kept fast on purpose):

  • Multi-stage + npm layer cache; source COPY only src/ + config
  • Prefer better-sqlite3 prebuilds (npm_config_build_from_source=false)
  • Standalone Next output (small runtime image)
  • Pinned yt-dlp release (cacheable layer)
  • GH Actions (.github/workflows/docker.yml): GHA cache, PR = amd64 only, main/tags = amd64+arm64

Umbrel package

The Umbrel store package lives in polarr-app (not this repo):

  • polarr-app/umbrel-app.yml — manifest (port: 3647, dependency on lidarr, STORAGE_DOWNLOADS)
  • polarr-app/docker-compose.yml — app_proxy → web on internal 3000, music mount under shared Downloads

Before a store PR:

  1. Publish images from polarr-app (ghcr.io/kevinguest/polarr-app)
  2. Pin the image digest in that repo’s Umbrel compose file
  3. Follow skills from umbrel-apps: develop → package → test
  4. Galleries are left empty; Umbrel team supplies assets

Suggested Umbrel Lidarr URL during setup: http://lidarr_server_1:8686

API paths are whitelisted through app_proxy (/api/*) for session and bearer auth without Umbrel cookies.

API surface

  • GET /api/v1/status — health (no secrets)
  • POST /api/auth/login — session token
  • GET /api/library / POST scan
  • GET /api/search?q=
  • POST /api/requests — Lidarr + optional fallback
  • GET /api/stream/:id — range-aware audio
  • GET|POST /api/settings

License note

Fallback downloading uses tools that can touch third-party content. Users are responsible for complying with copyright and provider terms in their jurisdiction. Polarr is intended for legitimate self-hosted library management and streaming of music you are allowed to use.

About

Self-hosted music discovery, Lidarr requests, and streaming

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages