Skip to content

Repository files navigation

DiscVault

DiscVault is a self-hosted physical media collection manager for 4K UHD, Blu-ray, and DVD.

DiscVault 26 is the next-generation app experience. It is available as a beta today and will become the production channel when promoted to stable.

It includes:

  • DiscVault 26 library with poster, list, and detail views
  • Rich movie, container, box-set, poster, backdrop, video, and metadata pages
  • PostgreSQL-backed v26 foundation with a guided migration path
  • Plugin runtime for metadata, import sources, receivers, digital sources, API, and MCP
  • Plex/Jellyfin digital media matching and MovieVault metadata integration
  • Barcode scanning and manual entry
  • Metadata lookup through configurable plugins
  • Collection filtering, search, and format-aware browsing
  • Backup and restore tools
  • User management, groups, owner/admin tooling, and RBAC
  • MemberGroups — user-created collaboration groups with invite system
  • Watchlist & watch history
  • Passkey authentication and recovery
  • Invite-only registration — admin issues one-time passwords, open sign-up can be disabled
  • Multilingual UI
  • URL routing and deep links — share direct links to movies or views
  • MCP endpoint integration for AI workflows
  • PWA — works offline after adding to homescreen
  • Push notifications — group members are notified when a new disc is added to a shared group
  • User-scoped MCP access — personal API keys connect your AI assistant to your own collection only

Live Website

Docker Images

ghcr.io/helmerznl/discvault:latest   # production / stable
ghcr.io/helmerznl/discvault:beta     # DiscVault 26 beta

Docker image references are lowercase. GitHub may show the repository name as helmerzNL/DiscVault, but Docker pulls should use ghcr.io/helmerznl/discvault.

Troubleshooting

Unraid

Screenshots

DiscVault 26 desktop preview

Library posters Library list
Rich detail page Backdrops
Watchlist detail Watched history
RBAC admin Plugin admin
Operations Preferences

Migration to DiscVault 26

DiscVault 26 includes a guided migration flow for existing installations. The wizard checks your current data, confirms what can be imported, runs the migration, and then opens the new DiscVault 26 app.

Start migration Authenticate with current passkey
Review migration wizard Confirm migration scope
Ready to start Migration in progress
Migration finished Start DiscVault 26

Current stable desktop

Sign in Collection Import
Sign in Collection Import
Backup & Restore User Management Logfiles
Backup & Restore User Management Logfiles
Advanced & MCP
Advanced & MCP

Mobile

Sign in Search Add movie Profile
Metadata Authentication User management Backup & Restore
Logfiles Advanced Collection

Install DiscVault 26 Beta

Use the beta channel to try DiscVault 26 while it is still being finalized. Create a backup before moving an existing library between stable and beta. Generate JWT_SECRET once, store it securely, and reuse the same value for every container recreation:

export JWT_SECRET="$(openssl rand -base64 48)"
docker run -d \
  --name discvault \
  -p 6080:80 \
  -p 6090:6090 \
  -e TZ=Europe/Amsterdam \
  -e RP_ID=localhost \
  -e RP_ORIGIN=http://localhost:6080 \
  -e JWT_SECRET="$JWT_SECRET" \
  -v /mnt/user/appdata/discvault:/data \
  ghcr.io/helmerznl/discvault:beta

Open: http://localhost:6080

For a reverse-proxy production-like beta host, set passkey values to the public hostname:

RP_ID=discvault.example.com
RP_ORIGIN=https://discvault.example.com
JWT_SECRET=<stable value generated with: openssl rand -base64 48>

JWT_SECRET is required for every deployment and must remain unchanged across container restarts. DiscVault stops during startup when it is missing rather than deriving a predictable value from the database configuration.

Optional password + TOTP authentication

Passkeys remain the preferred sign-in method. To expose Legacy password authentication, set LEGACY_AUTH_ENABLED=true. Existing installations must then enable password login in Users & roles and confirm the warning with a fresh passkey assertion.

On a completely fresh installation (no users or credentials), the setup wizard may instead create the first Owner with a 15+ character password and mandatory TOTP. This no-passkey bootstrap is atomic and single-use. TOTP secrets and recovery codes are never included in backups; restored MFA-enabled password users are prompted to enroll TOTP again.

Install DiscVault 26 Production / Stable

Use the production channel for stable deployments. When DiscVault 26 is promoted from beta to production, this is the channel to run. Set JWT_SECRET to the same securely stored value used by the existing instance.

docker run -d \
  --name discvault \
  -p 6080:80 \
  -p 6090:6090 \
  -e TZ=Europe/Amsterdam \
  -e RP_ID=localhost \
  -e RP_ORIGIN=http://localhost:6080 \
  -e JWT_SECRET="$JWT_SECRET" \
  -v /mnt/user/appdata/discvault:/data \
  ghcr.io/helmerznl/discvault:latest

Open: http://localhost:6080

Before updating production:

  • Create a backup from the admin tools or copy the persistent data directory while the container is stopped.
  • Keep the same /data volume mapping so posters, backdrops, uploads, users, passkeys, and settings remain available.
  • Review release notes before moving between beta and production channels.

Search engines and AI crawlers

A DiscVault instance is a private collection manager, and it keeps itself out of search results and out of AI training corpora without any configuration:

  • /robots.txt disallows every crawler on every path, and names the search engines, AI crawlers, SEO bots and link-preview fetchers individually.
  • Every response carries X-Robots-Tag: noindex, nofollow, noarchive, nosnippet, noimageindex, and every rendered page repeats it as a <meta name="robots"> tag — this is the part that clears an instance already in an index, since a Disallow alone stops a crawler from ever seeing the noindex.
  • Known crawler user agents are refused with 403. /robots.txt and /api/next/health always answer, so container health checks and uptime monitors are unaffected.

Set DISCVAULT_BLOCK_CRAWLERS=false only if you deliberately want an instance to be findable. Nothing has to be misconfigured for the opposite to happen: a reachable host with a public DNS record gets crawled on its own, which is how two self-hosted instances ended up in Google.

All three layers are served by DiscVault itself, so a reverse proxy in front of it must pass them through: a proxy that answers /robots.txt from its own configuration, or strips response headers, replaces DiscVault's answer with its own. Cloudflare's own "Block AI bots" setting is complementary, not a substitute — it never sees a request that does not go through Cloudflare.

None of this is a security control — a user agent is self-reported, so a scraper that wants in can simply claim to be a browser. An instance that must not be reachable still belongs behind authentication, a VPN, or off the public internet.

Install the standalone MovieVault v2 plugin

DiscVault 26.4.44 and newer provide the local anonymous synchronization bridge used by the separately released movievault_v2 plugin. Download the plugin ZIP and checksum from helmerzNL/DiscVault-Plugins, verify the SHA-256 checksum, and extract its movievault_v2/ root folder into DISCVAULT_PLUGIN_INSTALL_DIR (normally /data/plugins in the persistent volume).

Restart DiscVault or refresh its plugin registry. The plugin is enabled by default and is DiscVault's highest-priority metadata source (order 5, above every other bundled source including tmdb at 10). DiscVault queues the first synchronization automatically, and normal barcode, title, release, and box-set queries then use the derived PostgreSQL index.

Two settings are enforced by DiscVault and not editable in the plugin-settings UI:

  • Endpoint. DiscVault always uses the enforced origin https://movies2.vaultstack.eu. Self-hosted operators who need a different instance can override it out-of-band with the MOVIEVAULT_V2_ORIGIN environment variable (an invalid or empty value falls back to the default).
  • Anonymous bucket fallback. Always on. It is what resolves a disc the locally synced index does not carry yet, so a barcode lookup without it silently misses every title MovieVault has not distributed into this instance's index. Override out-of-band with MOVIEVAULT_V2_BUCKET_FALLBACK=0 only if you have a reason to. The fallback applies to barcode and box-set lookups; title queries cannot use it, because buckets are keyed by the hash of the EAN.

movievault_26 has been removed from DiscVault and uninstalled from existing installations. It was DiscVault's only metadata_receiver, so the v1 receiver route that contributed back to MovieVault is gone with it, along with its stored connection (instance keypair, API tokens, handshake state) and the MOVIEVAULT_SEARCH_URL / MOVIEVAULT_INGEST_URL / MOVIEVAULT_DISCVAULT_HANDSHAKE_SECRET / MOVIEVAULT_SHARING_MODE settings that configured it. What continues to work is the separate movievault_v2 release-contribution and field-correction path, gated by movievault_v2_contribution_enabled in App Admin — that one is untouched.

DiscVault 26.4.57 adds negotiated distribution-3 support. The matching deterministic movievault_v2 feature package (currently 1.5.0) ships as a bundled default plugin and is also available under dist/plugins/ for staged installation. Older plugins continue to use distribution-2; v3 is selected only when both the plugin manifest and core declare support.

DiscVault no longer bundles or distributes a local bluray_com metadata provider. Blu-ray.com release-detail fallback is owned by MovieVault v2 and is reached only through the standalone movievault_v2 plugin and DiscVault's anonymous core bridge. Existing installations must disable and uninstall the old bluray_com metadata provider before enabling this route. The separate import_bluray_com collection-import plugin remains available and unchanged.

DiscVault 26.4.61 adds core consumer support for distribution-4 (a strict distribution-3 superset that adds a required-nullable primary poster on release and box-set upserts, with bounded anonymous background caching and authenticated local poster URLs). Distribution-4 is negotiated only when both the installed plugin manifest and DiscVault core declare support, so it stays inactive by default until the matching movievault_v2 plugin release advertises distribution-4 in its distributionContractRange; that plugin change ships separately from helmerzNL/DiscVault-Plugins and is not part of this repository. Existing distribution-2/distribution-3 installations are unaffected.

DiscVault 26.5.10 adds a bounded, anonymous release-technical-1 bridge for the existing barcode scanner and manual barcode entry. Matching movievault_v2 plugin releases keep this technical fallback disabled by default. When an operator enables it, DiscVault still checks the synchronized local index and optional hash bucket first. Only a genuine miss sends the normalized barcode and bounded release hints to MovieVault; no account, instance, collection, contribution credential, cookie, or client address is sent. Pending results are polled only by their opaque resolution ID. External results remain visibly unreviewed and require confirmation.

The same DiscVault server-side bridge is used by PWA, Android, and iOS clients. Client scanners only submit a barcode to DiscVault and never contact MovieVault or a metadata provider directly.

Repository Structure

  • app/ - Main application code (backend, frontend, mcp-server, deployment files)
  • .github/workflows/ - CI/CD workflows

The marketing website (https://discvault.eu) lives in its own repository: helmerzNL/DiscVault.EU.

License

MIT

About

DiscVault 4K Collection App

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages