diff --git a/serverAppConfigs-docs/Dankserver/Jellyfin.md b/serverAppConfigs-docs/Dankserver/Jellyfin.md index 741a9f0..6c9e2a2 100644 --- a/serverAppConfigs-docs/Dankserver/Jellyfin.md +++ b/serverAppConfigs-docs/Dankserver/Jellyfin.md @@ -1,7 +1,7 @@ --- type: reference title: Jellyfin -description: "Jellyfin on Dankserver: quadlet unit, overlay metadata view layout, ports, access, hardware-transcode status." +description: "Jellyfin on Dankserver: quadlet unit, overlay metadata view, provider keys, ports, access, transcode status." tags: [jellyfin, dankserver, media-server] timestamp: 2026-10-30T00:00:00Z --- @@ -117,6 +117,61 @@ where the LDAP plugin runs. Verified 2026-09-25: `alex` authenticates over `AuthenticateByName` (HTTP 200; full plugin flow logged — service bind, search, `ldapUid`, user bind, token). +## Metadata providers and their keys (2026-10-30) + +TMDb, OMDb, StudioImages and MusicBrainz are **core plugins** in Jellyfin 12 — +no DLL, just a configuration file the running container owns under the data +root. TVDB is not core (its metadata provider was removed in 10.9), so it is an +official-catalog plugin. + +| Provider | Shape on disk | Key lives in | +|---|---|---| +| TMDb | `config/plugins/configurations/Jellyfin.Plugin.Tmdb.xml` → `` | `/home/dank/Containers/jellyfin/provider-keys` → `TMDB_API_KEY=` (mode 600) | +| TVDB | `config/plugins/thetvdb_24.0.0.0/` + `…Jellyfin.Plugin.Tvdb.xml` → `` | the same file → `TVDB_API_KEY=` | +| OMDb | `…Jellyfin.Plugin.Omdb.xml` | **not configured** — its key is issued by email, 1 000 req/day, and its ToS forbids storing the returned data; ratings stay Jellyfin's own lookup | + +**None of it is tracked in git.** Those XML files belong to the container and +hold credentials, and `tests/jellyfin_providers.bats` fails the suite if one is +ever committed. The keys themselves sit in the per-service host env file that is +the fleet's convention for container credentials (grafana, caddy, pihole, +copyparty, romm, seerr): `provider-keys`, mode 600, beside the data root. +`scripts/jellyfin-providers.sh` is the only thing that writes the XML: + +``` +scripts/jellyfin-providers.sh plan # what would change; prints no key +scripts/jellyfin-providers.sh install # plugin + keys, previous copy to trash +scripts/jellyfin-providers.sh verify # plugin + key LENGTHS, never key bytes +``` + +- **A key never enters git, argv, or the tool's output.** The installer reads + that 600-perm file itself (a value in argv is world-readable through + `/proc//cmdline`) and refuses it when it is group- or world-readable — + an exposed key is an error, not a warning. A key that shows up in a transcript + or `ps` output has leaked: rotate it with the provider, rewrite + `provider-keys`, re-run `install`. +- **The TVDB artifact is pinned three ways**: sha256 + `6302fba3857bdde8d186dd099fac09ca43247041f531a528a2c788add70a5319`, the + official plugin guid `a677c0da-fac5-4cde-941a-7134223f14c8`, and version + `24.0.0.0` (`targetAbi 12.0.0.0`, which fits the deployed 12.4.0). A sha + match alone only proves the bytes are the bytes fetched — the guid check is + what says it is the official plugin. Rollback: move `thetvdb_24.0.0.0/` into + the trash and revert the pin; a second `thetvdb_*` directory is a refusal, + never a quiet second copy. +- **The homelab TVDB key is a licensed key** (its JWT claims say + `community_supported: false`), so it needs **no PIN** — the optional + `TVDB_PIN=` line exists only for a subscriber-shaped key. +- **TVDB is installed and keyed but is not a metadata agent**: TMDb still + identifies everything. Enabling TVDB as a provider would re-fetch show + metadata across the library, so it is a deliberate, separate change. +- **The deployer places the keys before it restarts jellyfin** + (`ensure_provider_keys` in `scripts/deploy-remote.sh`) and warns instead of + failing when `provider-keys` is absent, so a host without it still deploys. +- **Keys and plugins are read at start-up**: after a manual `install` the + change is inert until `./scripts/deploy.sh dankserver --service jellyfin`. +- TMDb's terms are the reason this stays narrow: attribution required, no + caching beyond 6 months, no derivative works. Fine for a personal homelab, + and the reason no bulk enrichment pass runs against it. + ## Configuration workflow 1. Create libraries pointing at `/data` folders (movies, shows, audio). diff --git a/serverAppConfigs-docs/index.md b/serverAppConfigs-docs/index.md index a5e7551..bf32af6 100644 --- a/serverAppConfigs-docs/index.md +++ b/serverAppConfigs-docs/index.md @@ -49,7 +49,7 @@ is a locator: one row, one clause, no numbers. | [[Copyparty]] | Copyparty is a lightweight file server and media streamer that runs as a single Python binary. | | [[Dankserver Stack]] | Service inventory and routing overview for the media and library host. | | [[Entropy Volume]] | The Dankserver entropy volume is a RAID-backed LUKS filesystem mounted at | -| [[Jellyfin]] | Jellyfin on Dankserver: quadlet unit, overlay metadata view layout, ports, access, hardware-transcode status. | +| [[Jellyfin]] | Jellyfin on Dankserver: quadlet unit, overlay metadata view, provider keys, ports, access, transcode status. | | [[mariadb]] | The MariaDB backend for RomM: quadlet unit, network alias, env-file secret handling, and the backup path. | | [[Media Metadata View]] | The SSD-backed overlay the two media servers read and write: shape, guards, commands, laws, rollback. | | [[Media Relayout]] | Census, plan and apply the movie library into Jellyfin format, and move TV out of it: the gates, refusals, rollback. |