ReelSpace

ReelSpace

Docker app from Reel Apps' Repository

Overview

ReelSpace turns your media library into clear, actionable storage insights. See which movies, shows, libraries, resolutions, codecs, and duplicates consume the most space—then make smarter decisions before your server fills up. Read-only by design.

ReelSpace

ReelSpace turns your media library into clear, actionable storage insights. See which movies, shows, libraries, resolutions, codecs, and duplicates consume the most space—then make smarter decisions before your server fills up.

ReelSpace does not delete, move, rename, or transcode files in the initial release.

The project is not affiliated with, endorsed by, or sponsored by Plex, Unraid, or Lime Technology. Plex is a trademark of Plex, Inc.; Unraid is a trademark of Lime Technology, Inc.

Application icon

Features

  • Streaming, cancellable full and quick scans with live root, path, and file progress
  • Read-only scan-root folder browser for directories mounted under /data
  • Safe controls for clearing scan history or removing indexed roots without deleting media
  • Cached directory aggregates, historical snapshots, growth, changes, and forecasts
  • Explorer with hierarchical browsing, filtering, sorting, pagination, and exports
  • ffprobe metadata for resolution, codec, HDR, container, audio, and bitrate
  • Staged duplicate detection with optional full SHA-256 verification
  • Device/inode hardlink grouping excluded from reclaimable-space calculations
  • Logical, allocated, physical-unique, and sparse-file-aware size reporting
  • Optional Plex HTTP API enrichment and path mappings
  • Webhook, Discord, Slack, ntfy, and Gotify test delivery; adapter extension points
  • Responsive light/dark/system UI, OpenAPI docs, diagnostics, and health endpoints
  • Non-privileged Docker packaging and a safe Unraid Community Applications template

Screenshots

Screenshots will be added from the first clean Unraid 7.2.x release-candidate build:

  • docs/screenshots/overview.png — dashboard and growth
  • docs/screenshots/explorer.png — hierarchical storage explorer
  • docs/screenshots/duplicates.png — duplicates and hardlinks

These are deliberately marked placeholders; no image is presented as a tested Unraid installation screenshot yet.

Architecture

The React/TypeScript interface and FastAPI service ship in one container. SQLAlchemy stores the current index, cached aggregates, compact snapshots, and per-scan changes in SQLite under /config. The scanner streams filesystem entries, never follows symlinks, and purges stale index entries only after a successful scan. Plex, notifications, and future automation integrations are adapters around the independent filesystem core. See the implementation plan. The latest automated and Docker smoke results are recorded in the validation report.

Installation

The current release is v0.1.3, published as ghcr.io/bgriffin63/reelspace:latest for linux/amd64 and linux/arm64.

Unraid (recommended)

ReelSpace is a Docker application, not an Unraid plugin. Do not paste its URL into Plugins → Install Plugin; that screen accepts .plg files, while ReelSpace ships as a container.

Until ReelSpace is listed in Community Applications, install its Docker template:

  1. Open Unraid → Terminal and run:

    mkdir -p /boot/config/plugins/dockerMan/templates-user
    curl -fsSL \
      https://raw.githubusercontent.com/BGriffin63/ReelSpace/main/templates/reelspace.xml \
      -o /boot/config/plugins/dockerMan/templates-user/my-ReelSpace.xml
    
  2. Refresh the Docker page, select Add Container, and choose ReelSpace from the Template list.

  3. Review the required values:

    Setting Host value Container value Access
    Application data /mnt/user/appdata/reelspace /config Read/write
    Media /mnt/user/Media /data/media Read-only
    Web UI 8080 8080 TCP
    PUID / PGID 99 / 100 PUID / PGID Unraid defaults
  4. Change /mnt/user/Media if your share uses a different spelling or location. Unraid paths are case-sensitive.

  5. Click Create, wait for the image download to finish, then open http://YOUR-UNRAID-IP:8080.

  6. In Settings → Scan roots, select Browse, choose /data/media or one of its subfolders, enter a display name and category, and select Add scan root.

  7. Open Scans and start a quick or full scan.

ReelSpace's folder browser only displays directories mounted under /data. To expose another share, edit the container and add another read-only path mapping:

/mnt/user/downloads  -> /data/downloads:ro
/mnt/user/domains    -> /data/vms:ro
/mnt/user/Media/TV   -> /data/tv:ro

You can optionally map /mnt/user to /data/shares:ro to browse all user shares, although mapping only the shares ReelSpace needs is safer. Never map ReelSpace's own /config directory beneath /data, and enter container paths such as /data/media inside ReelSpace—not Unraid host paths such as /mnt/user/Media.

To update on Unraid, open Docker, select Check for Updates, and update ReelSpace. Unraid recreates the container automatically; the /config mapping preserves the database and settings, and startup applies database migrations.

Docker Compose

Create a compose.yaml containing:

services:
  reelspace:
    image: ghcr.io/bgriffin63/reelspace:latest
    container_name: reelspace
    ports:
      - "8080:8080"
    environment:
      TZ: America/Chicago
      PUID: 1000
      PGID: 1000
      UMASK: "022"
    volumes:
      - ./reelspace-config:/config
      - /path/to/media:/data/media:ro
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true

Replace /path/to/media, then install or update:

docker compose pull
docker compose up -d

Open http://localhost:8080, add /data/media under Settings → Scan roots, and start a scan. State persists in ./reelspace-config.

Docker CLI

docker run -d \
  --name reelspace \
  --restart unless-stopped \
  --security-opt no-new-privileges:true \
  -p 8080:8080 \
  -e TZ=America/Chicago \
  -e PUID=1000 \
  -e PGID=1000 \
  -e UMASK=022 \
  -v reelspace-config:/config \
  -v /path/to/media:/data/media:ro \
  ghcr.io/bgriffin63/reelspace:latest

The API documentation is available at http://localhost:8080/docs.

Scanning and storage semantics

A full scan re-stats and reanalyzes every included file. A quick scan reuses cached hashes and media probes when size and modification time are unchanged, while still traversing the root to detect removals. Defaults are intentionally conservative: two filesystem workers, one ffprobe worker, small pauses between batches, and no symlink following.

Logical size is the sum of path-visible apparent sizes. Allocated size uses filesystem blocks where available. Physical unique size counts a device/inode identity once. A sparse VM image can report a large logical size but much lower allocated size.

Hardlinks are multiple directory entries for the same (device, inode). Sonarr and Radarr frequently use them so downloads and imported media share blocks. They are shown as hardlink groups and are never treated as independently reclaimable duplicate copies. True duplicates have distinct physical identities and matching content hashes.

Scheduled scans

Settings includes a lightweight daily scheduler for all enabled roots. The recommended default is a quick scan during an off-peak hour, such as 03:00. The scheduler sleeps between checks and consumes negligible CPU while idle. If a root is already scanning at its scheduled time, ReelSpace retries it later rather than overlapping the scan. Scheduled quick scans still traverse the root to detect additions and removals, but unchanged files reuse cached hashes and media metadata.

Media and Plex

Media probing runs only for recognized extensions, is bounded by timeout and file-size settings, and is cached by size and nanosecond modification time. HDR classification is conservative; missing evidence produces Unknown. “REMUX-like” means high bitrate and is an estimate, not a Plex edition classification.

To connect Plex, get a token using Plex's documented account process, enter the server URL and token under Settings → Plex connection, and run the connection test. The token is encrypted with an installation-local key under /config, returned to the UI only as “configured,” and never logged. Path mappings translate a Plex-visible prefix (for example /movies) to the scanner container prefix (/data/media/movies). The core scanner works fully without Plex.

Notifications

Use Notifications to test generic webhooks, Discord, Slack, ntfy, or Gotify. Provider adapters are isolated so SMTP, Pushover, quiet hours, event rules, cooldowns, and native Unraid notification delivery can evolve without coupling the scanner to a provider. Secrets must be supplied only through application configuration, never in public issue reports.

Backup, restore, and upgrade

Stop the container and copy the complete /config directory, including reelspace.db and .secret-key. Restore both together; the key is required to decrypt stored secrets. For an integrity check:

docker exec reelspace python -c \
  "import sqlite3; print(sqlite3.connect('/config/reelspace.db').execute('pragma integrity_check').fetchone()[0])"

To back up SQLite safely while running:

docker exec reelspace python -c \
  "import sqlite3; s=sqlite3.connect('/config/reelspace.db'); d=sqlite3.connect('/config/reelspace-backup.db'); s.backup(d)"

Before upgrading, back up /config, pull the new image, and recreate the container. Docker Compose users can run docker compose pull && docker compose up -d; Unraid users can select Docker → Check for Updates, then update ReelSpace. Alembic migrations run automatically at startup, and release notes identify any exceptional step.

Troubleshooting

  • Path inaccessible: confirm it is mapped into the container and the host path exists. Do not enter /mnt/user/... in the UI unless that exact path was mounted.
  • Permission denied: align PUID/PGID with a user/group allowed to read the share. Unraid defaults are 99:100. Leave analyzed mounts read-only.
  • No media metadata: verify ffprobe can read the file and inspect the scan warning. Corrupt files and timeouts do not abort a scan.
  • Unexpected double count: remove overlapping roots or explicitly acknowledge the overlap only when intentional.
  • Network mount disappeared: restore it and scan again. Failed scans do not purge the last known-good index.
  • Slow scan: disable metadata/duplicate analysis for non-media roots, reduce probing, use quick scans, and schedule full scans away from playback hours.

For one million files, use SSD-backed appdata, retain WAL mode, keep root scopes purposeful, avoid overlaps, paginate the explorer, and rely on cached aggregates rather than repeated full scans. The synthetic index utility is:

python -m app.benchmark --files 1000000

Privacy and security

There is no telemetry, cloud account, destructive filesystem operation, privileged mode, Docker socket, or required host networking. All intelligence remains in /config. Expose the UI only to a trusted LAN or place it behind an authenticated TLS reverse proxy. See SECURITY.md for the threat model.

Development

Backend:

python -m venv .venv
. .venv/bin/activate
pip install -e "./backend[dev]"
REELSPACE_CONFIG_DIR=./local-config uvicorn app.main:app --reload --port 8080
pytest
ruff check backend tests
mypy backend/app

Frontend:

cd frontend
pnpm install
pnpm dev
pnpm test
pnpm build

Container:

docker build --build-arg VERSION=0.1.3 -t reelspace:local .
docker run --rm -p 8080:8080 -v reelspace-config:/config \
  -v /path/to/media:/data/media:ro reelspace:local

Known limitations

  • Installation and container lifecycle are validated on Unraid 7.2.0. Large-library scans and FUSE inode accounting still need release-candidate validation against representative media shares.
  • Plex connection and library discovery are implemented; the deeper library sync and watched/unmatched reports are extension points for the next milestone.
  • Complete event-rule persistence, SMTP/Pushover delivery, and optional Unraid host metrics are not yet complete.
  • No cleanup workflow exists by design.

Future adapters are planned for Sonarr, Radarr, Lidarr, Readarr, Bazarr, Overseerr, Jellyseerr, SABnzbd, NZBGet, qBittorrent, Transmission, Tautulli, Jellyfin, Emby, the Unraid API, native notifications, and an explicitly reviewed cleanup workflow.

Community Applications

A Community Applications submission is planned but is not yet listed. Until it is approved, use the manual Unraid Docker-template process above. Maintainers should follow the Unraid submission checklist.

Install ReelSpace on Unraid in a few clicks.

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

Requirements

Unraid OS 7.2 or newer. Map analyzed directories read-only.

Related apps

Explore more like this

Explore all

Details

Repository
ghcr.io/bgriffin63/reelspace:latest
Last Updated2026-07-28
First Seen2026-07-28

Runtime arguments

Web UI
http://[IP]:[PORT:8080]
Network
bridge
Shell
sh
Privileged
false
Extra Params
--security-opt=no-new-privileges

Template configuration

Web UIPorttcp

Web interface and API port.

Target
8080
Default
8080
Value
8080
Application dataPathrw

Persistent database, settings, encryption key, and diagnostics.

Target
/config
Default
/mnt/user/appdata/reelspace
Value
/mnt/user/appdata/reelspace
MediaPathro

Primary media directory. Keep this mapping read-only.

Target
/data/media
Default
/mnt/user/Media
Value
/mnt/user/Media
Additional shares (optional)Pathro

Optional Unraid share or /mnt/user mapping for the read-only folder browser. Prefer mapping only the shares you want ReelSpace to see.

Target
/data/shares
Downloads (optional)Pathro

Optional complete or incomplete download directory, read-only.

Target
/data/downloads
VM storage (optional)Pathro

Optional domains or VM image directory, read-only.

Target
/data/vms
Appdata analysis (optional)Pathro

Optional appdata directory for analysis only. Never map the application's own /config here.

Target
/data/appdata
PUIDVariable

Container process user ID. Unraid default is 99 (nobody).

Default
99
Value
99
PGIDVariable

Container process group ID. Unraid default is 100 (users).

Default
100
Value
100
UMASKVariable

Permissions mask for files created under /config.

Default
022
Value
022
TimezoneVariable

IANA timezone used for schedules and displayed timestamps.

Target
TZ
Default
America/Chicago
Value
America/Chicago
Log levelVariable

Structured application log verbosity: DEBUG, INFO, WARNING, or ERROR.

Target
REELSPACE_LOG_LEVEL
Default
INFO
Value
INFO
Built-in authenticationVariable

Enable first-run local administrator setup, Argon2 passwords, expiring sessions, login throttling, and CSRF protection.

Target
REELSPACE_AUTH_ENABLED
Default
false
Value
false