Self-hosted media operations dashboard for seedboxes, download clients, and the Arr ecosystem.
2.3K
Flowarr is a self-hosted media operations dashboard for people running seedboxes, download clients, and the Arr ecosystem.
It sits above tools like qBittorrent, Radarr, Sonarr, Plex, and Jellyfin to show storage usage, download state, media lifecycle state, and cleanup recommendations in one place.
Flowarr is built with heavy AI assistance — see How Flowarr Is Built for exactly what that means before you decide whether to run it.
More views in Screenshots.
/health, and serves the built frontend directly — no separate frontend container needed (Swagger is available in local development only).Click any shot to view it full size. The dashboard is at the top of this page — local and seedbox usage, active SFTP transfers with live progress and cancel, recent imports, and torrent-client state side by side.
Storage — local and seedbox roots split by whether each folder backs a download rule or is only monitored for free space.
Cleanup — media-server-derived duplicate and stale candidates, with the kept copy chosen explicitly, confidence shown, and dry-run on by default.
Settings — per-integration configuration for the torrent client, SFTP, Radarr/Sonarr, Plex, and Jellyfin, with a "Test connection" button and secrets stored encrypted.
Flowarr is developed with extensive use of Claude (Anthropic's AI coding tooling). Stating that plainly here so nobody has to guess:
What this means for you: judge Flowarr the way you'd judge any self-hosted hobby project — on whether it works in your setup, not on who typed it. Run it against data you have backed up, keep dry-run on until you've verified your roots and paths, and open an issue if something is wrong. Bug reports are welcome and get fixed.
If AI-assisted development is a dealbreaker for you, that's a completely reasonable position — better you know now than three commits into a fork.
Flowarr ships as a single prebuilt image published to GitHub Container Registry — no build step, no separate database container:
docker run -d \
--name flowarr \
-p 8080:8080 \
-e PUID=1000 -e PGID=1000 \
-v /mnt/media:/media \
-v flowarr-data:/var/lib/flowarr/data \
-v flowarr-keys:/var/lib/flowarr/keys \
ghcr.io/theclosetcoder/flowarr:latest
Open http://localhost:8080 and complete first-run admin setup. flowarr-data holds the SQLite database and flowarr-keys holds the credential-encryption key ring — keep both volumes across upgrades. Add further -v /mnt/diskN/Folder:/media/Folder mounts for additional media disks.
Flowarr runs as the unprivileged user PUID:PGID (default 1000:1000), not root. Set them to the owner of your media folders (id -u and id -g on the host), the same as you would for Radarr or Sonarr: Flowarr needs write access under /media for downloads and cleanup, and read access to any SFTP private key you mount. The container takes ownership of its own flowarr-data and flowarr-keys volumes at startup, so volumes created by older root-based images keep working after an upgrade. If you start the container with --user instead, it skips that step and runs as that user directly, so the volumes must already be writable by it.
To pin a version instead of following latest, use a tag from the Packages page (e.g. ghcr.io/theclosetcoder/flowarr:v1.2.0).
Prefer Compose if you want .env-driven integration settings (qBittorrent, Radarr, Sonarr, SFTP) instead of one-off -e flags. From the repository root:
cd docker
cp .env.example .env
nano .env
docker compose -f docker/docker-compose.yml up --build
Set FLOWARR_MEDIA_ROOT in docker/.env to your host media folder, for example:
FLOWARR_MEDIA_ROOT=/mnt/media
Inside Flowarr, use the container paths under /media, for example /media/Movies or /media/TV Shows.
Open http://localhost:8080 for the dashboard, health at http://localhost:8080/health.
Docker Compose reads these optional variables:
FLOWARR_PUID=1000
FLOWARR_PGID=1000
FLOWARR_QBITTORRENT_BASE_URL=
FLOWARR_QBITTORRENT_USERNAME=
FLOWARR_QBITTORRENT_PASSWORD=
FLOWARR_RADARR_BASE_URL=
FLOWARR_RADARR_API_KEY=
FLOWARR_SONARR_BASE_URL=
FLOWARR_SONARR_API_KEY=
FLOWARR_MEDIA_ROOT=./data/media
FLOWARR_SEEDBOX_MOUNT_PATH=./data/seedbox
FLOWARR_SEEDBOX_PATH_OR_ENDPOINT=/seedbox
FLOWARR_AUTO_DOWNLOAD_ENABLED=false
FLOWARR_AUTO_DOWNLOAD_OVERWRITE_EXISTING=false
FLOWARR_SFTP_HOST=
FLOWARR_SFTP_PORT=22
FLOWARR_SFTP_USERNAME=
FLOWARR_SFTP_PASSWORD=
FLOWARR_SFTP_PRIVATE_KEY_PATH=
FLOWARR_SFTP_PRIVATE_KEY_HOST_PATH=./data/keys
The API also supports .NET environment variable binding:
ConnectionStrings__Flowarr=Data Source=/var/lib/flowarr/data/flowarr.db
Flowarr__Cleanup__DryRun=true
Flowarr__Cleanup__AllowDelete=false
Flowarr__Storage__LocalPath=/media
Flowarr__Storage__SeedboxPathOrEndpoint=/seedbox
Flowarr__AutoDownload__Enabled=false
Flowarr__AutoDownload__LocalImportPath=/media/import
Flowarr can pull completed or seeding downloads from a remote seedbox over SFTP into one or more local media paths.
You can configure Deluge or qBittorrent, SFTP seedbox, Radarr, Sonarr, Plex, and auto-download settings from the Connections page in the app. Deluge Web only needs its web password; qBittorrent can use username and password. Passwords, API keys, and key passphrases are encrypted before being stored in the SQLite database using ASP.NET Core Data Protection. A saved secret is only ever sent to the server it was saved for: when you change a connection's base URL, or the SFTP host or port, type its password or API key again. The Docker Compose file persists the encryption key ring in the flowarr-keys volume and the database file in the flowarr-data volume so saved credentials and data remain readable after container rebuilds.
You can also seed defaults with .env:
FLOWARR_AUTO_DOWNLOAD_ENABLED=true
FLOWARR_MEDIA_ROOT=/mnt/media
FLOWARR_SFTP_HOST=your-ultra-sftp-host
FLOWARR_SFTP_PORT=22
FLOWARR_SFTP_USERNAME=your-ultra-username
FLOWARR_SFTP_PASSWORD=your-ultra-password
In the app, configure at least one seedbox root under SFTP settings — quota, storage, and download features all depend on it:
Download roots are the paths reported by Deluge/qBittorrent, such as /downloads/movies.Media roots are completed library paths managed by Radarr/Sonarr, such as /media/Movies.For private key auth, mount a host key folder and point Flowarr at the in-container key path:
FLOWARR_SFTP_PRIVATE_KEY_HOST_PATH=/path/on/host/keys
FLOWARR_SFTP_PRIVATE_KEY_PATH=/keys/id_rsa
FLOWARR_SFTP_PASSWORD=
Auto-download behavior:
/downloads/movies can go to /media/Movies, while /downloads/tv can go to /media/TV Shows.FLOWARR_AUTO_DOWNLOAD_OVERWRITE_EXISTING=true — and if a local file's size doesn't match the remote (e.g. a partial file left by an interrupted transfer), it re-downloads it regardless of that setting, since a mismatched size is never a legitimately "already downloaded" file.By default, the Storage page reports free space from the SFTP server's statvfs response, which on a shared host is the whole server's free space, not your personal allocation. If your provider gives you a fixed quota, set it under Connections → SFTP → "Account quota (GB)" — Flowarr will then report quota - total account usage (computed via one periodic scan of the seedbox root, cached for ~15 minutes) as the free-space figure across all your seedbox entries instead.
For multiple disks, add extra bind mounts to the api service, then add matching local media paths in the app:
volumes:
- /mnt/disk1/Movies:/media/Movies
- /mnt/disk2/TV Shows:/media/TV Shows
- /mnt/archive:/media/Archive
hasPassword and hasPrivateKeyPassphrase flags instead.flowarr-keys Docker volume. Removing it can make existing encrypted credentials unreadable.Cleanup targets local disk space, not the seedbox (the seedbox is assumed to be temporary storage, not something Cleanup needs to manage). It requires a media server connection — Plex (Connections → Plex, with a base URL and token), Jellyfin (Connections → Jellyfin, with a base URL and API key), or both. The server's own library data gives Flowarr the exact local file path, watch count, last-viewed date, and (via multiple Media entries / MediaSources under one item) a built-in signal for duplicate physical copies of the same title, without needing Radarr/Sonarr at all.
When both servers are configured and index the same folders, each file is only counted once: a title counts as watched if it was watched on either server, and the most recent view wins. Jellyfin watch state is combined across all Jellyfin users the same way.
Clicking "Generate recommendations" runs as a background job and shows live progress in the UI — Plex requires one API call per TV series to fetch episode data, and Jellyfin one pass per user, so a large library can take a while.
A local file is suggested for cleanup when:
Media entries on one Plex item, or multiple MediaSources on one Jellyfin item). The largest copy is kept; the rest are flagged (Certain confidence).Certain confidence).Uncertain confidence — needs manual review, since this is a weaker signal than the version-group case above).Safety rules:
Flowarr__Cleanup__AllowDelete=true, exact path confirmation (typed into the UI, must match the candidate's path exactly), and the path must fall under a configured seedbox root or local media path.Note: candidate paths come from the media server's own view of the filesystem, so the server and Flowarr need to see the same file paths (e.g. both mounting /media the same way) for candidates to resolve to real, deletable files — Flowarr silently skips anything it can't verify exists rather than presenting an unusable candidate.
Flowarr uses a custom "converge" icon (three sources merging into a download tray) instead of a generic favicon, defined once as a scalable source and reused everywhere:
frontend/public/icon.svg — the master vector icon, used as the browser-tab favicon in browsers that support SVG favicons.frontend/public/icons/favicon-16.png and favicon-32.png — PNG favicon fallbacks for browsers that don't.frontend/public/icons/apple-touch-icon.png (180×180) — used by iOS Safari's "Add to Home Screen".frontend/public/icons/icon-192.png and icon-512.png, referenced from frontend/public/manifest.webmanifest — used by Android/Chrome's "Add to Home Screen" / install prompt.frontend/src/components/FlowarrMark.tsx — the same glyph as an inline SVG component, used for the in-app sidebar and login-screen logo so it matches the installed icon.All of this is wired up via <link>/<meta> tags in frontend/index.html (favicon, apple-touch-icon, manifest, theme-color) — nothing further to configure. To change the icon, edit frontend/public/icon.svg and FlowarrMark.tsx to match, then regenerate the PNGs in frontend/public/icons/ at the same sizes (16, 32, 48, 180, 192, 512px) with any SVG-to-PNG tool, keeping the existing filenames.
On first launch, Flowarr asks you to create a local admin account. The password must be at least 12 characters and is stored as a salted PBKDF2 hash. API routes require the admin session cookie except /health and first-run auth endpoints. Complete this first-run setup on your local network before exposing the instance to the internet.
Flowarr itself serves plain HTTP with no TLS. Don't forward its port directly to the internet — put a TLS-terminating reverse proxy in front of it instead (nginx, Caddy, Traefik, or a Cloudflare Tunnel). Flowarr trusts X-Forwarded-For/X-Forwarded-Proto headers from any source, so make sure inbound internet traffic can only reach it through that proxy (e.g. a Cloudflare Tunnel with no router port-forward, or a firewall rule that only allows the reverse proxy's host/network to reach the published port).
Flowarr uses an embedded SQLite database (flowarr.db, persisted via the flowarr-data Docker volume) and applies EF Core migrations at API startup — no separate database container or manual setup required.
Never edit a migration after it has shipped. EF Core tracks which migration IDs have already run per database in __EFMigrationsHistory; editing an already-applied migration's Up() has no effect on environments that already ran it, since Migrate() only checks the ID, not the file contents. Add a new migration instead, generated with dotnet dotnet-ef migrations add <Name> --project backend/Flowarr.Infrastructure --startup-project backend/Flowarr.Api -o Migrations.
backend/
Flowarr.Api/
Flowarr.Core/
Flowarr.Infrastructure/
frontend/
docker/
docker-compose.yml
Flowarr is licensed under the Apache License, Version 2.0.
Content type
Image
Digest
sha256:0821c343a…
Size
112.8 MB
Last updated
6 days ago
docker pull closetcoder/flowarr