Manage your Plex library storage. Shelflife connects to Seerr (or Overseerr/Jellyseerr for legacy setups) and Tautulli to let users vote on whether content they requested should be kept or deleted. Admins get a dashboard showing what can be safely pruned.
- Users sign in with their Plex account (same login as Seerr/Overseerr)
- Shelflife syncs media requests from Seerr (or Overseerr) and watch history from Tautulli
- Each user sees their own requests and marks them as Keep or Can Delete
- Admins see an aggregate view of what users have flagged for deletion
By default Shelflife is read-only -- it syncs data but never modifies your external services. Optionally, admins can connect Sonarr and Radarr to execute deletions directly from the admin review dashboard.
- Seerr, Overseerr (legacy), or Jellyseerr (legacy) -- for media request data
- Tautulli -- for watch history
- A Plex account
Note: Both Overseerr and Jellyseerr have been archived and succeeded by Seerr (v3.0.0+). Shelflife supports all three -- configure
SEERR_URL/SEERR_API_KEYfor Seerr,OVERSEERR_URL/OVERSEERR_API_KEYfor legacy Overseerr, orJELLYSEERR_URL/JELLYSEERR_API_KEYfor legacy Jellyseerr. Seerr takes priority when multiple are configured.
Shelflife shows file sizes alongside media items in the admin review panel to help prioritize deletions by storage impact. For movies, file sizes are pulled automatically from Tautulli. For TV shows, Tautulli does not calculate total file sizes by default, so Shelflife falls back to querying the Plex server directly using the admin user's Plex token.
To enable Tautulli-native file size calculation for TV shows (recommended for faster syncs):
- Open Tautulli > Settings > General
- Click Show Advanced at the top
- Enable Calculate Total File Sizes
- Save and restart Tautulli
- Open each TV library's Media Info tab in Tautulli at least once to trigger the initial calculation
After this, Tautulli will return TV show file sizes in its API, and Shelflife will use those values. If the setting is not enabled, Shelflife will fall back to querying the Plex server API for TV episode sizes and aggregating them per show. This fallback works automatically but adds extra API calls during sync.
| Variable | Required | Description |
|---|---|---|
SEERR_URL |
* | URL of your Seerr instance (e.g. http://192.168.1.100:5055) |
SEERR_API_KEY |
* | Found in Seerr under Settings > General |
NEXT_PUBLIC_SEERR_URL |
No | Public URL of your Seerr instance (for deep links in the UI) |
OVERSEERR_URL |
* | URL of your Overseerr instance (legacy fallback) |
OVERSEERR_API_KEY |
* | Found in Overseerr under Settings > General |
NEXT_PUBLIC_OVERSEERR_URL |
No | Public URL of your Overseerr instance (legacy fallback for UI links) |
JELLYSEERR_URL |
* | URL of your Jellyseerr instance (legacy fallback) |
JELLYSEERR_API_KEY |
* | Found in Jellyseerr under Settings > General |
NEXT_PUBLIC_JELLYSEERR_URL |
No | Public URL of your Jellyseerr instance (legacy fallback for UI links) |
TAUTULLI_URL |
Yes | URL of your Tautulli instance (e.g. http://192.168.1.100:8181) |
TAUTULLI_API_KEY |
Yes | Found in Tautulli under Settings > Web Interface |
SESSION_SECRET |
Yes | Random string for signing sessions (minimum 32 characters) |
SONARR_URL |
No | URL of your Sonarr instance -- enables TV show deletion from admin |
SONARR_API_KEY |
No | Found in Sonarr under Settings > General |
RADARR_URL |
No | URL of your Radarr instance -- enables movie deletion from admin |
RADARR_API_KEY |
No | Found in Radarr under Settings > General |
PLEX_CLIENT_ID |
No | Identifier for Plex auth (defaults to shelflife) |
ADMIN_PLEX_ID |
No | Force a specific Plex user as admin. If unset, the first user to sign in becomes admin |
DATABASE_PATH |
No | Path to SQLite database (defaults to /app/data/shelflife.db in Docker) |
COOKIE_SECURE |
No | Set to true if behind HTTPS reverse proxy. Defaults to false for plain HTTP |
DEBUG |
No | Set to true for verbose debug logging (useful for troubleshooting) |
* One of SEERR_URL/SEERR_API_KEY, OVERSEERR_URL/OVERSEERR_API_KEY, or JELLYSEERR_URL/JELLYSEERR_API_KEY must be set. When multiple are configured, Seerr takes priority.
If you are developing or making UI changes and want hot-reloading without building a Docker container every time:
- Install Bun
- Run the local dev script:
This script will automatically copy
bun run dev:local
.env.exampleto.env(if you don't already have one), ensure the SQLite database migrations are up to date, and start the Next.js dev server at the port specified in your.env(defaulting tohttp://localhost:3000). You can edit the UI files and see them update instantly.
services:
shelflife:
image: ghcr.io/fauxvo/shelflife:latest
container_name: shelflife
restart: unless-stopped
ports:
- "3000:3000"
environment:
# Seerr (recommended) — or use OVERSEERR_URL/OVERSEERR_API_KEY for legacy
- SEERR_URL=http://your-ip:5055
- SEERR_API_KEY=your-key
- TAUTULLI_URL=http://your-ip:8181
- TAUTULLI_API_KEY=your-key
- SESSION_SECRET=your-random-32-char-secret
# Optional: enable admin deletion from Sonarr/Radarr
# - SONARR_URL=http://your-ip:8989
# - SONARR_API_KEY=your-key
# - RADARR_URL=http://your-ip:7878
# - RADARR_API_KEY=your-key
volumes:
- shelflife-data:/app/data
volumes:
shelflife-data:docker compose up -dThe app will be available at http://localhost:3000.
Important -- Networking: Shelflife needs to reach your Seerr/Overseerr and Tautulli instances. On Unraid with the default bridge network,
localhostand127.0.0.1refer to the container itself, not your server. Use your Unraid server's IP address (e.g.http://192.168.1.100:5055) when settingSEERR_URL(orOVERSEERR_URL) andTAUTULLI_URL.
Before starting, grab these from your existing services:
- Seerr API Key: Open Seerr > Settings > General > scroll to API Key and copy it (or use your existing Overseerr API key if still on Overseerr)
- Tautulli API Key: Open Tautulli > Settings > Web Interface > scroll to API Key and copy it
Shelflife needs a random secret string (minimum 32 characters) for signing login sessions. Run this in the Unraid terminal to generate one:
openssl rand -hex 32Copy the output -- you'll paste it into the SESSION_SECRET field below.
Requires the Compose Manager plugin.
-
In Compose Manager, click Add New Stack
-
Give it a name (e.g.
shelflife) -
Paste this into the compose editor:
services: shelflife: image: ghcr.io/fauxvo/shelflife:latest container_name: shelflife restart: unless-stopped ports: - "3000:3000" environment: # Seerr (recommended) — or use OVERSEERR_URL/OVERSEERR_API_KEY for legacy - SEERR_URL=http://YOUR_UNRAID_IP:5055 - SEERR_API_KEY=your-seerr-api-key - TAUTULLI_URL=http://YOUR_UNRAID_IP:8181 - TAUTULLI_API_KEY=your-tautulli-api-key - SESSION_SECRET=your-generated-secret-from-above # Optional: enable admin deletion from Sonarr/Radarr # - SONARR_URL=http://YOUR_UNRAID_IP:8989 # - SONARR_API_KEY=your-sonarr-api-key # - RADARR_URL=http://YOUR_UNRAID_IP:7878 # - RADARR_API_KEY=your-radarr-api-key # - DEBUG=true # Uncomment for verbose logging volumes: - /mnt/user/appdata/shelflife:/app/data
-
Replace
YOUR_UNRAID_IPwith your Unraid server's IP address -
Replace the API keys and session secret with your actual values
-
Click Compose Up
To update: Click Compose Down, then Pull, then Compose Up. Or use Watchtower for automatic updates.
-
In the Unraid web UI, go to the Docker tab
-
Click Add Container
-
Toggle Advanced View in the top-right if not already enabled
-
Fill in the basic fields:
Field Value Name shelflifeRepository ghcr.io/fauxvo/shelflife:latestNetwork Type bridge -
Click Add another Path, Port, Variable, Label or Device for each of the following:
Port mapping:
Config Type Name Container Port Host Port Port Web UI30003000Volume mapping:
Config Type Name Container Path Host Path Path Data/app/data/mnt/user/appdata/shelflifeEnvironment variables (add one at a time):
Config Type Name Key Value Variable Seerr URL SEERR_URLhttp://YOUR_UNRAID_IP:5055(or useOVERSEERR_URLlegacy)Variable Seerr API Key SEERR_API_KEYYour Seerr API key (or use OVERSEERR_API_KEYlegacy)Variable Tautulli URL TAUTULLI_URLhttp://YOUR_UNRAID_IP:8181Variable Tautulli API Key TAUTULLI_API_KEYYour Tautulli API key Variable Session Secret SESSION_SECRETYour generated secret Variable Sonarr URL SONARR_URLhttp://YOUR_UNRAID_IP:8989(optional)Variable Sonarr API Key SONARR_API_KEYYour Sonarr API key (optional) Variable Radarr URL RADARR_URLhttp://YOUR_UNRAID_IP:7878(optional)Variable Radarr API Key RADARR_API_KEYYour Radarr API key (optional) Variable Debug Logging DEBUGtrue(optional) -
Click Apply
To update: Click the container icon in the Docker tab and select Update, or use Watchtower for automatic updates.
This imports a pre-configured template so you only need to fill in your values:
- Open the Unraid terminal (or SSH in)
- Run:
mkdir -p /boot/config/plugins/dockerMan/templates-user wget -O /boot/config/plugins/dockerMan/templates-user/shelflife.xml \ https://raw.githubusercontent.com/fauxvo/shelflife/main/unraid/shelflife.xml
- Go to the Docker tab and click Add Container
- From the Template dropdown, select shelflife
- Fill in your Seerr URL (or Overseerr URL), API Key, Tautulli URL, Tautulli API Key, and Session Secret
- Click Apply
The template has all ports, paths, and optional settings pre-configured. You just fill in your credentials.
"Connection refused" when syncing: Your SEERR_URL (or OVERSEERR_URL) or TAUTULLI_URL is probably using localhost or 127.0.0.1. Change it to your Unraid server's actual IP address (e.g. http://192.168.1.100:5055).
Container starts but can't reach the web UI: Make sure port 3000 isn't already in use by another container. You can change the host port (the left side) to something else, e.g. 3001:3000.
Database errors after update: The SQLite database is stored in /mnt/user/appdata/shelflife/. As long as that volume mapping is correct, your data persists across container updates.
Something not working? Enable debug logging: Add the environment variable DEBUG=true to your container. This outputs detailed logs for auth, sync, and API calls. Check the container logs in the Unraid Docker tab (click the container icon > Log) to see what's happening.
- Open Shelflife in your browser at
http://YOUR_UNRAID_IP:3000 - Click Sign in with Plex
- Authorize the app in the Plex popup
- The first user to sign in automatically becomes the admin
- Go to the Admin page and click Sync to pull in your Seerr/Overseerr requests and Tautulli watch history
- Share the URL with your Plex users so they can log in and vote on their own requests