Files
Frank 327e78b950 docs(vault): destroy the dead weight — 53 pages and the change diary
The vault was 155 pages / 31,210 lines, most of it measurement ledgers for
payloads that no longer run. A throughput figure for a runtime nobody operates is
not a record: AI moves faster than the vault, so the number is wrong before
anyone reads it, and a wrong number in a runbook gets believed. Per the new
purpose test in `AGENTS.md` → *Documentation Policy*, it is destroyed.

Gone (`.AGENTTRASH/20261019-destruction/`, KILL-LIST.txt is the manifest):
- the `frank-medium` endpoint and its five era pages, `frank-npu`, FastFlowLM,
  the ikllama/kingjones/dealign/frank-redo eras, the ling/swift15/freetoken/ubatch
  campaign pages, qwen3.8 spec-matrix and strix-optimizations, the two
  "Running Qwen3.6 …" pages;
- the whole `Pipeline Parallelism/` folder (no live script passes a pipeline flag)
  and the multi-device/x4-pair/hybrid/offload experiment pages;
- every vLLM page — no vLLM endpoint exists on this fleet;
- `LLM/deployment.md` (`Architecture/Deployment Flow.md` is the test-referenced
  owner) and the external surveys (SGLang, Lemonade, llama.cpp forks/diff,
  self-hosted app census, the TTS survey) that were obsolete by construction;
- `log.md`, 2,380 lines. Git holds the chronology; a causal law belongs to the
  page that owns the thing it governs, never to a diary.

Survivors: 101 pages, 17,542 lines, 0 OKF violations, 0 unresolved links. Eras
tables keep the window, payload, runtime, reason and rollback pointer; the rate
columns are blanked. The live shapes stay verbatim — those numbers are what the
deployer and `models.yml` consume.
2026-10-19 10:56:37 -07:00

5.9 KiB

type, title, description, tags, timestamp
type title description tags timestamp
reference Jellyfin Jellyfin on Dankserver: quadlet unit, entropy-volume data layout, ports, client access, hardware-transcode status.
jellyfin
dankserver
media-server
2026-09-03T00:00:00Z

Jellyfin

Jellyfin is the free media server on Dankserver — a podman quadlet service (jellyfin.service, generated from dankserver/jellyfin/quadlet/jellyfin.container) serving music, movies, and shows over LAN. It replaced the earlier research brief; it runs alongside Plex, which remains the primary server for some clients.

Host: Dankserver (192.168.0.235) — Access: http://192.168.0.235:8096 public vhost jelly.franksdank.cloud behind the Anubis guard chain → Authentik outpost (post-auth route proxies localhost:8096).

Facts (verified from the live unit, 2026-09-03)

Item Value
Unit ~/.config/containers/systemd/jellyfin.container → jellyfin.service (user manager), Restart=always, RestartSec=5
Image ghcr.io/jellyfin/jellyfin:latest
Network dankserver_appnet; publishes 8096/tcp, 8920/tcp, 7359/udp, 1900/udp
Data roots /home/dank/Containers/jellyfin/config:/config, /home/dank/Containers/jellyfin/cache:/cache
Media Volume=/mnt/entropy:/data:ro — the whole Entropy Volume mounted read-only; nothing automated writes to it
GPU none — no AddDevice; CPU decode only (jellyfin-ffmpeg path)
Env quirks DOTNET_SYSTEM_IO_DISABLEFILELOCKING=true, LD_PRELOAD=libjemalloc.so.2, MALLOC_TRIM_THRESHOLD_=131072 kept verbatim from the compose-era container (zero-drift cutover)
Health curl -f http://localhost:8096/health every 30 s

Data layout

/home/dank/Containers/jellyfin/config   -> /config   (JELLYFIN_DATA_DIR)
/home/dank/Containers/jellyfin/cache    -> /cache    (JELLYFIN_CACHE_DIR, XDG_CACHE_HOME)
/mnt/entropy                            -> /data     (read-only media volume)

Library folders point at /data paths; because the mount uses the same absolute path as on the host, library paths survive container recreation.

Ports & access

Port Proto Purpose
8096 TCP Web UI + API (JELLYFIN_PublishedServerUrl=http://192.168.0.235:8096)
8920 TCP DLNA/UPnP root device control
7359 UDP service discovery (client auto-discovery)
1900 UDP SSDP discovery

Client access paths and the public-exposure policy (auth wall required before any public vhost; Plex-style claim tokens do not exist here — Jellyfin uses its own users/API keys) follow the fleet Authentik/Anubis chain pattern.

Authentik LDAP authentication (2026-09-25)

Jellyfin has no native external-auth, so it authenticates users through the LDAP-Auth plugin (jellyfin-plugin-ldapauth) against an Authentik LDAP provider. A user logs in with their authentik username + password; the plugin binds as a service account, searches the directory, and rebinds as the user to verify the password.

authentik side (on Dankclaw):

  • LDAP provider Jellyfin LDAP (Base DN dc=franksdank,dc=cloud, bind/search mode direct) + application Jellyfin.
  • LDAP outpost Jellyfin LDAP Outpost → container authentik-outpost-ldap (quadlet dankclaw/authentik/quadlet/authentik-outpost-ldap.container) publishing 389/636 on the Dankclaw host for cross-host binds.
  • Service account svc-jellyfin-ldap (DN cn=svc-jellyfin-ldap,ou=users,dc=franksdank,dc=cloud).
  • Access groups jellyfin_users (search filter (memberOf=cn=jellyfin_users,ou=groups,dc=franksdank,dc=cloud)) and jellyfin_admins (admin filter (cn=jellyfin_admins)). Add a user to jellyfin_users to grant them Jellyfin access; jellyfin_admins grants the Jellyfin admin role.

Jellyfin side (plugin config, set via admin → Plugins → LDAP-Auth):

  • Server 192.168.0.143:389 (plain LDAP over the trusted LAN), Base DN dc=franksdank,dc=cloud, bind user = the service-account DN, search attributes uid,cn,mail,displayName, uid attr uid, username attr cn CreateUsersFromLdap=true, all folders enabled.

Gotcha — the bind credential is a PASSWORD, not a token. The LDAP bind is verified by authentik's default authentication flow (standard-password backend). The service account must have a password set (admin → user → Recovery → Set password); an API/app token is not accepted as the bind password and the bind fails with flow error password: Invalid. The service-account password is stored only in the Jellyfin plugin config (the LdapBindPassword field) — it is never committed to this repo.

Verification (2026-09-25): ldapsearch bind + the jellyfin_users search both succeed from Dankclaw; a real user (alex, in jellyfin_users) logged into the web UI with their authentik password and the plugin created the matching Jellyfin user. Gotcha — the login endpoint changed in Jellyfin 12.1. The legacy POST /Users/Auth/Password route (and its LegacyEmbyRouteRewriteMiddleware) was removed; probing it now returns a silent 401 with no plugin log, which reads like an auth failure but is just a dead route. The web UI and modern clients use POST /Users/AuthenticateByName (with the Authorization: MediaBrowser Client=…, DeviceId=…, Device=…, Version=… header), which is 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).

Configuration workflow

  1. Create libraries pointing at /data folders (movies, shows, audio).
  2. Set metadata/language preferences (LANG=en_US.UTF-8 pinned in the unit).
  3. Configure clients to use http://192.168.0.235:8096 or the guarded vhost.

See Also