Files
oikos/containers/101-jellyfin.md
dtoro fd35b48c8d Phase 1-4: full doc reorg
Phase 1 — fix stale state after strong migration (Phase 1+2, 2026-07-05)
  - README: corrected IPs (jellyfin 206→246, arriman 132→245, etc.),
    added missing containers (128 trmnl, 129 house, 133 seanime, 134 romm,
    124 authentik), updated last-refreshed date, added strong host context
  - containers/101-jellyfin.md: IP 206→246, host hubris→strong, mount
    /mnt/library→/mnt/media_local, GPU 760M→680M+RX7600, privilege→priv
  - containers/118-elementsynapse.md: IP 239→242, added Host: strong
  - containers/122-arriman.md: IP 132→245, mount→/mnt/media_local, added Host
  - containers/129-house.md: IP 212→244, added Host: strong
  - containers/130-grimmory.md: IP 213→247, mount→/mnt/media_local, added Host
  - containers/121-caddy.md: fixed site list (books→grimmory, removed auth→VPS,
    added house, roms, teddy, trmnl)
  - hosts/strong.md: updated At-a-glance to reflect 7 LXCs hosted
  - containers/123-claudio-bot.md, 127-mule-photos-new.md: archived to
    containers/archive/ (were destroyed LXCs with living pages)
  - inventory.yaml: verified correct — no changes needed

Phase 2 — structural cleanup
  - infrastructure/index.md: one-page overview of all cross-cutting systems
  - runbooks/: moved runbook-budget-from-csv.md and runbook-dpkg-interrupted.md
    from operations/ with YAML frontmatter added
  - plans/done/: moved 4 completed plans out of active view; updated index
  - vms/index.md: added VM index page

Phase 3 — navigation & discoverability
  - GLOSSARY.md: term definitions (Authentik, Caddy, LXC, VAAPI, etc.)
  - README: added table of contents, links to glossary + infrastructure index
  - investigations/: archived 2 resolved cases (crash-loop, authentik-migration)
    to investigations/archive/; updated index with active vs archived sections

Phase 4 — ongoing discipline
  - CONTRIBUTING.md: documented same-session update rule with explicit checklist
  - README: replaced full LXC table with summary + link to containers/index.md
    (single source of truth; de-duplication)
2026-07-06 00:46:27 +02:00

8.0 KiB

101 — jellyfin

Media server: serves the movies / TV / anime / music libraries from /mnt/media_local to LAN clients. Hardware transcoding via AMD Radeon 680M + RX 7600 VAAPI. Authentik SSO via OIDC.

At a glance

  • Host: strong (migrated from hubris 2026-07-05)
  • IP: 192.168.8.246
  • Privilege: privileged (recreated on strong as priv)
  • Resources: 4 cores / 8 GiB RAM / 1 GiB swap / 16 GiB rootfs
  • GPU: /dev/dri/renderD128 + /dev/dri/card0 (AMD Radeon 680M iGPU + RX 7600 dGPU) passed via dev0 / dev1 in LXC config
  • Mounts: /mnt/media_local/mnt/library
  • Public hostname: media.hubris.networkcaddy:8096
  • Version: Jellyfin 10.11.11 (apt package, Ubuntu 24.04 noble repo)
  • FFmpeg: jellyfin-ffmpeg7 7.1.4

Service / port map

Service Listen Notes
jellyfin :8096 HTTP (caddy terminates TLS)

Hardware acceleration (VAAPI)

GPU is passed through to the LXC via dev0: /dev/dri/renderD128,gid=993 and dev1: /dev/dri/card0,gid=44 in /etc/pve/lxc/101.conf (strong). The jellyfin user is in the render (GID 993) and video groups inside the container.

GPU Model Role
Radeon 680M iGPU (AMD Ryzen 7 PRO 6850U) Primary VAAPI encoder/decoder
RX 7600 dGPU (add-in) Secondary transcode, HEVC/AV1 encoding

Encoding settings (/etc/jellyfin/encoding.xml):

  • HardwareAccelerationType: vaapi
  • VaapiDevice: /dev/dri/renderD128
  • EnableHardwareEncoding: true
  • AllowHevcEncoding: true
  • AllowAv1Encoding: true
  • EnableTonemapping: true
  • HardwareDecodingCodecs: h264, hevc, vc1, vp9, av1
  • EnableThrottling: true
  • EnableSegmentDeletion: true

Trickplay (/etc/jellyfin/system.xml):

  • EnableHwAcceleration: true
  • EnableHwEncoding: true

Authentik SSO (OIDC)

Jellyfin uses the SSO-Auth plugin v4.0.0.4 for Authentik OIDC login. No Caddy forward-auth gate — the SSO plugin handles auth directly via OIDC redirect flow.

Architecture

User → media.hubris.network → Caddy (TLS, no forward-auth) → Jellyfin :8096
                                                                ↓
                                                    Login page with "Sign in with Authentik" button
                                                                ↓ (click)
                                                    /sso/OID/start/Authentik
                                                                ↓ (302 redirect)
                                                    auth.hubris.network OIDC
                                                                ↓ (login)
                                                    /sso/OID/redirect/Authentik?code=...&state=...
                                                                ↓
                                                    Jellyfin SSO plugin validates token → logged in

Components

  1. SSO-Auth plugin — installed at /var/lib/jellyfin/plugins/SSO-Auth_4.0.0.4/

    • Config: /var/lib/jellyfin/plugins/configurations/SSO-Auth.xml
    • Provider name: Authentik
    • OIDC endpoint: https://auth.hubris.network/application/o/jellyfin/
    • SchemeOverride: https (required — without it, plugin generates http:// redirect URIs that Authentik rejects)
    • EnableAuthorization: false (prevents plugin from overwriting admin permissions on each SSO login — see jellyfin-sso-plugin)
    • OidScopes: ["email"] (openid+profile added by default by the plugin; must be non-null or OidChallenge() throws ArgumentNullException)
  2. Authentik OIDC providerProvider for Jellyfin (PK 6)

    • Client ID: vt61t5Y2ZVtN6l3QjitkBvwUJjFKvSyl4TDBXcJx
    • Redirect URI: https://media.hubris.network/sso/OID/redirect/Authentik
    • Application slug: jellyfin
  3. SSO button injection/usr/share/jellyfin/web/sso-inject.js

    • Injected via <script defer src="sso-inject.js?v=3"> in index.html
    • Polls for .readOnlyContent div on the login page, adds "Sign in with Authentik" button linking to /sso/OID/start/Authentik
    • Cache-busted with ?v=N parameter (bump on changes)
    • Lost on apt upgrade — re-inject the script tag and copy the JS file after apt-get upgrade jellyfin*
  4. Caddy config — no forward-auth gate for media.hubris.network:

    media.hubris.network {
        tls { dns ionos {env.IONOS_AUTH_API_TOKEN} }
        reverse_proxy 192.168.8.206:8096
    }
    

Known issues / pitfalls

  • OidScopes must be non-null — if the field is missing from the plugin config XML, OidChallenge() throws System.ArgumentNullException. Always include OidScopes in the provider config (even if empty array).
  • SchemeOverride: "https" is required — without it, the plugin generates http:// redirect URIs (from the internal HTTP listener). Authentik rejects them with "Redirect URI Error".
  • SSO button JS is not served by the plugin — the __plugin/SSO-Auth.js endpoint returns 404 on Jellyfin 10.11.x when the plugin is installed manually (not via Jellyfin's plugin manager). The sso-inject.js workaround in index.html is the fallback.
  • No Caddy forward-auth gate — the SSO plugin's OIDC redirect flow is incompatible with Caddy's import authentik forward-auth. If both are enabled, the forward-auth intercepts the OIDC callback and breaks the flow. Use one or the other, not both. SSO plugin (OIDC redirect) is preferred.
  • API key for setup — a temp API key can be inserted directly into the ApiKeys SQLite table for automated configuration:
    INSERT INTO ApiKeys VALUES (1, '2026-07-04', '2026-07-04', 'setup', 'jf-setup-key-...');
    

Permissions

Member of the media GID 10000 standard. Service user jellyfin is in the media group inside the container; /mnt/media_local on strong's ludo-lvm is owned root:media with mode 2775.

Changelog

2026-07-06 — wiki: IP, host, GPU, mount path updated for strong migration

Updated At-a-glance: IP 206→246, host hubris→strong, mount /mnt/library→/mnt/media_local, GPU Radeon 760M→680M+RX7600, privilege unpriv→priv. Permissions section updated. Changelog entry in 122-arriman.md updated similarly.

2026-07-04 — VAAPI hardware acceleration + Authentik SSO + resource bump

  • Upgraded Jellyfin 10.11.8 → 10.11.11 (purge + reinstall to fix DB migration bug)
  • Enabled VAAPI hardware acceleration (Radeon 760M): h264/hevc/vc1/vp9/av1 decode + encode
  • Bumped resources: 2→4 cores, 4→8 GiB RAM, 512→1024 MiB swap
  • Enabled trickplay HW acceleration + throttling + segment deletion
  • Installed SSO-Auth plugin v4.0.0.4 with Authentik OIDC provider
  • Configured SchemeOverride: https, OidScopes: ["email"], EnableAuthorization: false
  • Injected SSO button via sso-inject.js in web index.html
  • Removed Caddy forward-auth gate (incompatible with SSO plugin OIDC flow)
  • Database was wiped during cache relocation attempt — no LVM snapshot existed. All watch states, user accounts, and library configs lost. Libraries re-added via setup wizard.

2026-04-28 — wiki entry created

Initial documentation. No config changes.

2026-04-20 — joined the media GID 10000 standard

Idmap block applied; in-container media group at GID 10000 mapped to host GID 10000. See media permissions. Config backup: /root/101.conf.bak.*.