All apps · 0 apps
PlexLibrarian
Docker app from UnraidUser-0614219466's Repository
Overview
Readme
View on GitHubPlex Librarian
Find unwatched media, manage users, save bandwidth and space.
Install · Features · Integrations · Configuration · Get help
Plex Librarian is a tool for managing and maintaining Plex servers. It's intended as a simpler alternative to heavier tools with similar functionality, while offering some unique cleanup tools of its own. The goal is to reclaim terabytes of storage in as few clicks as possible, using sensible defaults.
What it does
| Capability | What you get | |
|---|---|---|
| 🧹 | Stale media discovery | Find unwatched or long-unwatched movies, shows, TV seasons, and music; filter and sort by age, size, play count, and more. |
| 💾 | Duplicate detection | Surface duplicate movie and episode versions and see how much space each copy consumes. |
| 🔎 | Episode Gaps | Audit TV seasons for missing numbers between the first and last episode already present in Plex, with irregular metadata called out separately. |
| 👥 | User insights | Review viewing activity, inactive accounts, and signals that may indicate account sharing. |
| 🔗 | Sonarr & Radarr coordination | Remove a title through the app that manages it, preventing an immediate re-download. Multiple instances are supported. |
| 🌱 | Hardlink & torrent cleanup | Delete verified qBittorrent files and the library hardlink created by an Arr import in one guided workflow. Plex Librarian can also clean up orphaned download-side hardlinks after the torrent is gone. |
Installation
Unraid
Open Plex Librarian in Community Apps, or search for Plex Librarian from the Apps tab. Keep the defaults, select Apply, then open the web UI from the Docker page and choose Sign in with Plex. Plex Librarian discovers your server and starts its first sync.
Normal operation does not require access to your media shares. Plex, Sonarr, or Radarr performs managed deletion using its own mounts and permissions. Only the optional orphan-download cleanup needs the additional read-only library and read/write download mounts described below.
Docker Compose
Create a compose.yml file:
services:
plex-librarian:
image: edon231/plex-librarian:latest
container_name: plex-librarian
ports:
- "8288:8080"
volumes:
- plex-librarian-data:/data
# Optional: required only for verified orphan-hardlink cleanup.
# - /path/to/library:/media:ro
# - /path/to/downloads:/downloads:rw
restart: unless-stopped
volumes:
plex-librarian-data:
Start the container, open http://<docker-host>:8288, and choose Sign in with
Plex:
docker compose up -d
Images are published for AMD64 and ARM64 to
Docker Hub and
GitHub Container Registry.
Use edon231/plex-librarian:latest for the newest stable release, or pin a full
version such as edon231/plex-librarian:0.1.0 for predictable upgrades. The
equivalent GHCR image is ghcr.io/brycepearce/plex-librarian. The edge tag
tracks the latest successful build from main and may contain unreleased
changes.
Sonarr, Radarr, Seerr, and qBittorrent
Connect Sonarr and Radarr
Plex Librarian can coordinate whole-title deletion with Radarr for movies and Sonarr for TV. Arr removes the title and its files, then Plex Librarian asks Plex to refresh the affected library.
Before anything is queued, the confirmation dialog verifies the mapped Arr
title and shows the folder it manages. Radarr's deleteFiles operation owns
removal of the complete title folder, including its safeguards for shared or
nested movie paths. If a library is not mapped, coordinated deletion is
refused; Delete from Plex only must be selected explicitly.
Open Settings → Media connections, add an instance with its URL and API key (found in Sonarr/Radarr under Settings → General → Security), then map each library under Library mappings.
Use a URL reachable from inside the Plex Librarian container, such as
http://192.168.1.20:8989 or http://sonarr:8989 on a shared Docker network.
Do not use localhost, which points back at Plex Librarian itself.
Remove a stale TV season
Open a TV library's Stale analysis page and switch Shows to Seasons. Season age is conservative: the newest episode addition determines the added date, and the most recent play of any episode determines the last-watched date. This keeps one recently added or watched episode from making the whole season look older than it is.
Whole-season removal accepts one season at a time. The confirmation preview re-reads its exact Plex episode membership. When Sonarr coordination is selected, Plex Librarian keeps the series, unmonitors that season's episodes, and deletes only EpisodeFiles proven to belong entirely to the selected season. A file shared with another season, ambiguous multi-instance ownership, or changed path mapping blocks the operation. Plex only is an explicit fallback and may allow Sonarr to download a monitored season again.
Optional qBittorrent cleanup uses the same fail-closed ownership checks as duplicate-season cleanup. It is offered only when every selected payload path and the complete download job manifest can be attributed to this season.
Optional qBittorrent cleanup
Add qBittorrent under Settings → Media connections to inspect live torrents associated with Sonarr/Radarr import history or verified direct path mappings. The deletion preview shows the bounded payload tree plus the job's tracker host, ratio, upload total, and cumulative seeding time. When explicitly selected, Plex Librarian removes the verified job and asks qBittorrent to delete its downloaded payload before Arr deletes the remaining library hardlink.
Plex Librarian does not locate or independently delete a saved .torrent file.
If an association cannot be verified, that item remains Arr-only. In a bulk
selection, qBittorrent cleanup applies only to rows with a verified job, and the
preview identifies the Plex, Sonarr, Radarr, and qBittorrent actions for every
item.
Orphan hardlink cleanup
Retained Radarr import history can point to an old download path after its torrent has disappeared. Plex Librarian shows these paths as unmanaged leftovers by default. To inspect the common hardlink case, edit the Radarr connection, expand Orphan download cleanup, and configure:
- The library root reported by Radarr and its read-only Plex Librarian mount.
- The download root reported by Radarr and its read/write Plex Librarian mount.
For example, Radarr paths under /data/media and /data/torrents could map to
Plex Librarian mounts /media and /downloads. Radarr roots may also be Windows
drive or UNC paths such as D:\Media; the Plex Librarian mount is always the
absolute Linux path visible inside its container.
Plex Librarian removes an orphaned source file only when the source and current Radarr-managed destination are regular files on the same filesystem with the same inode. It rechecks that identity immediately before unlinking, rejects symbolic links and paths outside the configured download root, and prunes only empty directories. Radarr-tracked media, subtitle, and metadata sidecars inside the same historical payload are eligible under that exact rule. Untracked sidecars, samples, metadata, and mixed directory contents are retained and explained in the preview.
Inspection stops after a shared 5,000-entry budget per preview or 12 directory levels and reports the unverified remainder; directories are never recursively deleted. Multi-file torrents are removed with their payload only when every manifest file is attributable to the selected Arr title. Mixed or partially attributed packs remain untouched.
The two mounts must refer to the same underlying filesystems Radarr sees. Their
container paths can differ because the web UI stores the translation, but the
local library and download roots must be separate, non-overlapping paths.
Configure Radarr's Import Extra Files setting for sidecars such as sub,
idx, and srt so Radarr can track them with the managed movie folder.
Use the qBittorrent Web UI URL as seen from the Plex Librarian container. Enter its username and password, or leave both blank only when qBittorrent's authentication bypass explicitly trusts the Plex Librarian host or subnet. Desktop qBittorrent users must first enable Web User Interface (Remote control). Private tracker passkeys are never returned to the browser; only the tracker hostname is displayed.
Configuration
Most settings live in the web UI. Under Settings → Automatic sync, you can enable daily refreshes, choose the local-time hour and IANA time zone, and decide whether the app catches up after being offline for more than 24 hours. The page previews the next scheduled window, and named zones follow daylight saving changes automatically. If a daylight-saving jump removes the chosen local hour, that day's scheduled run is skipped.
These environment variables are available for Docker and advanced Unraid installations:
| Variable | Required | Description |
|---|---|---|
DB_PATH |
No | SQLite database path. Default: /data/librarian.db |
PORT |
No | Container HTTP port. Default: 8080 |
PLEX_URL |
No | Direct Plex server URL; use with PLEX_TOKEN to skip the setup wizard |
PLEX_TOKEN |
No | Plex authentication token; use with PLEX_URL |
QBITTORRENT_URL |
No | qBittorrent Web UI URL; overrides connections saved in the web UI |
QBITTORRENT_USERNAME |
No | qBittorrent Web UI username; omit only when authentication bypass trusts this container |
QBITTORRENT_PASSWORD |
No | qBittorrent Web UI password; omit only when authentication bypass trusts this container |
LIBRARY_SYNC_CONCURRENCY |
No | Maximum libraries synced in parallel. Default: 3 |
FETCH_CONCURRENCY |
No | Maximum concurrent Plex page requests per library. Default: 8 |
SYNC_STALL_TIMEOUT_MINUTES |
No | Abort a sync after this many minutes without progress. Default: 15 |
LOG_RETENTION_DAYS |
No | Days to retain sync history and activity; use 0 to retain indefinitely. Default: 180 |
The concurrency defaults are intentionally conservative because Plex Librarian often shares a host with Plex. Raise them only when the host has capacity to spare.
For a bind mount instead of the Docker-managed volume shown above, map any
persistent host directory to /data. This makes the database easy to include
in a file-based backup routine.
Sonarr, Radarr, and Seerr are configured in the web UI so multiple instances can
be managed independently. qBittorrent can also be configured there; the
QBITTORRENT_* variables are power-user overrides and take precedence over
database-backed connections.
Manual Plex configuration
Set both PLEX_URL and PLEX_TOKEN to bypass the Plex authorization wizard.
Environment variables take precedence over credentials saved through the web
UI.
Use a direct local Plex URL when possible, such as
http://192.168.1.100:32400. To locate a token in Plex Web, open an item's
three-dot menu, select Get Info → View XML, and copy the X-Plex-Token
parameter from the resulting URL.
Optional Plex webhooks
Plex Pass users can configure a webhook for faster viewing-activity updates between full syncs. In Plex Web, open Settings → Webhooks → Add Webhook and enter:
http://<plex-librarian-host>:8288/api/webhook/plex
The webhook records playback lifecycle events used for watch-state and user activity insights. It follows the same trusted-network security model as the rest of the application.
Backups and security
All application data lives under /data, including the SQLite database, Plex
credentials, Sonarr/Radarr API keys, mappings, and activity history. Back up
this directory and treat the backup as sensitive.
Plex Librarian is designed for a trusted self-hosted network. If remote access is required, place it behind a reverse proxy that provides authentication and TLS.
Support and contributing
Found a bug or have an idea? Open an issue. Pull requests are welcome; please run the workspace validation command before submitting a change.
deno task fmt # apply the repository formatting rules
deno task verify # formatting, lint, type-checking, tests, and production build
The project uses Deno 2.9.5, matching the Docker image and CI. To catch
problems automatically before commits and pushes, install the repository's Git
hooks once after cloning:
deno task hooks:install
Development transparency
AI-assisted development tools are used in this project. AI-assisted changes are reviewed, tested, and maintained under the same standards as other contributions. Project maintainers remain responsible for the resulting code, documentation, and releases.
Plex Librarian is open-source software available under the MIT License.
Install PlexLibrarian on Unraid in a few clicks.
Find PlexLibrarian 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.
Categories
Related apps
Explore more like this
Explore allDetails
ghcr.io/brycepearce/plex-librarian:latestRuntime arguments
- Web UI
http://[IP]:[PORT:8080]/- Network
bridge- Shell
sh- Privileged
- false
- Extra Params
--init
Template configuration
Port for the Plex Librarian web UI.
- Target
- 8080
- Default
- 8288
- Value
- 8288
Persistent app data directory for the database and saved settings. The default is ready to use.
- Target
- /data
- Default
- /mnt/user/appdata/plex-librarian
- Value
- /mnt/user/appdata/plex-librarian
Optional. Read-only library mount used to verify Radarr orphan-download hardlinks. After adding it, configure the matching Radarr and local roots under Settings > Media connections.
- Target
- /media
Optional. Download mount beneath which Plex Librarian may unlink files proven to be hardlinks of current Arr-managed media. Never map a broader root than necessary.
- Target
- /downloads
Optional. URL of your Plex Media Server (e.g. http://192.168.1.100:32400). Set this together with Plex Token to bypass the OAuth setup wizard.
- Target
- PLEX_URL
Optional. Your Plex authentication token. Set this together with Plex URL to bypass the OAuth setup wizard.
- Target
- PLEX_TOKEN
Full path inside the container where the SQLite database file lives. Only change this if you have a specific reason to.
- Target
- DB_PATH
- Default
- /data/librarian.db
- Value
- /data/librarian.db
Optional power-user override. qBittorrent Web UI URL reachable from this container. Configure qBittorrent in the web UI instead for multiple instances.
- Target
- QBITTORRENT_URL
qBittorrent Web UI username. Leave blank only when authentication bypass trusts this container.
- Target
- QBITTORRENT_USERNAME
qBittorrent Web UI password. Leave blank only when authentication bypass trusts this container.
- Target
- QBITTORRENT_PASSWORD
Max number of libraries synced in parallel. Kept low by default to avoid competing with Plex for resources on the same host — only raise this on dedicated hardware.
- Target
- LIBRARY_SYNC_CONCURRENCY
- Default
- 3
- Value
- 3
Max concurrent Plex page requests per library. Kept low by default to avoid competing with Plex for resources on the same host — only raise this on dedicated hardware.
- Target
- FETCH_CONCURRENCY
- Default
- 8
- Value
- 8
Abort a sync if it reports no progress for this many minutes — e.g. the Plex server going offline mid-sync. Only raise this if you have a very slow or high-latency Plex connection triggering false positives.
- Target
- SYNC_STALL_TIMEOUT_MINUTES
- Default
- 15
- Value
- 15
Days to keep sync history and activity feed entries before they're automatically deleted. Raise this to retain history longer, or set to 0 to keep them forever.
- Target
- LOG_RETENTION_DAYS
- Default
- 180
- Value
- 180