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)
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 viadev0/dev1in LXC config - Mounts:
/mnt/media_local↔/mnt/library - Public hostname:
media.hubris.network→ caddy →: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:vaapiVaapiDevice:/dev/dri/renderD128EnableHardwareEncoding:trueAllowHevcEncoding:trueAllowAv1Encoding:trueEnableTonemapping:trueHardwareDecodingCodecs: h264, hevc, vc1, vp9, av1EnableThrottling:trueEnableSegmentDeletion:true
Trickplay (/etc/jellyfin/system.xml):
EnableHwAcceleration:trueEnableHwEncoding: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
-
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 generateshttp://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 orOidChallenge()throwsArgumentNullException)
- Config:
-
Authentik OIDC provider —
Provider for Jellyfin(PK 6)- Client ID:
vt61t5Y2ZVtN6l3QjitkBvwUJjFKvSyl4TDBXcJx - Redirect URI:
https://media.hubris.network/sso/OID/redirect/Authentik - Application slug:
jellyfin
- Client ID:
-
SSO button injection —
/usr/share/jellyfin/web/sso-inject.js- Injected via
<script defer src="sso-inject.js?v=3">inindex.html - Polls for
.readOnlyContentdiv on the login page, adds "Sign in with Authentik" button linking to/sso/OID/start/Authentik - Cache-busted with
?v=Nparameter (bump on changes) - Lost on apt upgrade — re-inject the script tag and copy the JS file
after
apt-get upgrade jellyfin*
- Injected via
-
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
OidScopesmust be non-null — if the field is missing from the plugin config XML,OidChallenge()throwsSystem.ArgumentNullException. Always includeOidScopesin the provider config (even if empty array).SchemeOverride: "https"is required — without it, the plugin generateshttp://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.jsendpoint returns 404 on Jellyfin 10.11.x when the plugin is installed manually (not via Jellyfin's plugin manager). Thesso-inject.jsworkaround inindex.htmlis the fallback. - No Caddy forward-auth gate — the SSO plugin's OIDC redirect flow is
incompatible with Caddy's
import authentikforward-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
ApiKeysSQLite 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.
Related
- Caddy reverse proxy
- Media permissions
- arriman — *arr stack writes the libraries jellyfin reads
- DNS split-horizon
- Authentik admin — OIDC provider creation, SSO plugin config
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.jsin webindex.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.*.