Skip to content

jellyfin-librarian

jellyfin-librarian is an internal webhook handler that automatically syncs Jellyfin user state from Authentik on every login.

Jellyfin has no concept of a default user profile — every new user starts with access to all libraries and no playback restrictions. Without automation, each new user would require manual configuration in the Jellyfin admin UI. jellyfin-librarian solves this by hooking into the login event and enforcing the correct policy automatically.

It also syncs the user's email from Authentik into Jellyseerr (if the user doesn't already have one set), and enables all email notification types so users get notified about their media requests.


How It Works

graph LR
    User -->|1. logs in| Jellyfin
    Jellyfin -->|2. AuthenticationSuccess webhook| Librarian[jellyfin-librarian]
    Librarian -->|3. GET /core/users/| Authentik
    Authentik -->|4. jellyfin_libraries + email| Librarian
    Librarian -->|5. POST /Users/id/Policy| Jellyfin
    Librarian -->|6. GET /user?q=username| Jellyseerr
    Librarian -->|7. POST /user/id/settings| Jellyseerr
Hold "Alt" / "Option" to enable pan & zoom

On every successful login:

  1. Jellyfin fires an AuthenticationSuccess webhook to jellyfin-librarian
  2. Librarian looks up the user in Authentik and reads jellyfin_libraries attribute and email
  3. Maps the attribute value to Jellyfin folder IDs via LIBRARY_MAPPING
  4. Compares against the user's current Jellyfin policy — if different, POSTs the updated policy
  5. Looks up the user in Jellyseerr — if they have no email set, syncs the Authentik email and enables all email notification types

Idempotent

If the policy already matches, no update is made. The handler fires on every login safely.


Deployment

  • Namespace


    bots

  • Source


    gitea.hdhomelab.com/cicd/jellyfin-librarian

  • Config


    flux/apps/noah/bots/jellyfin-librarian/

  • Port


    8080 (cluster-internal only)


Library Attribute Values

The jellyfin_libraries attribute on the Authentik user record controls which libraries are enabled:

jellyfin_libraries Libraries
cn Chinese libraries only
en English libraries only
all All libraries
(not set) Defaults to en

The attribute is set automatically during user registration via the Authentik enrollment flow. For existing users, set it manually:

Admin → Directory → Users → user → Edit → Attributes:

{"jellyfin_libraries": "cn"}

Set in the invitation Attributes field when creating the invite:

{"groups": ["jellyfin_user"], "attributes.jellyfin_libraries": "cn"}


Policy Applied on Login

In addition to library folder access, jellyfin-librarian enforces these policy settings for all managed users:

Setting Value Reason
EnableAllFolders false Restrict to EnabledFolders only
EnabledFolders Per jellyfin_libraries attribute Library access control
EnableVideoPlaybackTranscoding false Direct play only
EnableAudioPlaybackTranscoding false Direct play only
EnablePlaybackRemuxing false Direct play only

Full policy update

Jellyfin requires the complete policy object on POST /Users/{id}/Policy. jellyfin-librarian reads the existing policy and merges in only the fields it manages, leaving all other settings untouched.


Jellyseerr Email Sync

After syncing library permissions, jellyfin-librarian checks if the user exists in Jellyseerr and whether they have a real email set (Jellyseerr defaults the email field to the username for Jellyfin users).

If no real email is set:

  1. Pulls the email from the user's Authentik account
  2. Sets it in Jellyseerr via the user settings API
  3. Enables all user-facing email notification types: Request Approved, Request Declined, Request Available

Best-effort

Jellyseerr sync failures are logged but do not block the library policy sync. If Jellyseerr is down, the user's library permissions still get updated.


Configuration

Environment Variables

Env Var Source Value
JELLYFIN_URL ConfigMap http://jellyfin.media.svc:8096
JELLYFIN_API_KEY Vault secret Jellyfin API key
AUTHENTIK_URL ConfigMap http://authentik-server.infra.svc
AUTHENTIK_TOKEN Vault secret Authentik API token (read-only)
LIBRARY_MAPPING ConfigMap JSON map of attribute value → folder IDs
JELLYSEERR_URL ConfigMap Jellyseerr base URL
JELLYSEERR_API_KEY Vault secret Jellyseerr API key

LIBRARY_MAPPING is defined in the ConfigMap in deployment.yaml. Folder IDs are static — look them up once via GET /Library/VirtualFolders and update the ConfigMap.

Vault Secrets

Create at path jellyfin-librarian in Vault:

Key Description
jellyfin-api-key Jellyfin API key — Dashboard → API Keys
authentik-token Authentik API token — Admin → Directory → Tokens, intent: API Token
jellyseerr-api-key Jellyseerr API key — Settings → General

Jellyfin Webhook Plugin

The Webhook plugin must be installed from the Jellyfin plugin catalog and configured to point at jellyfin-librarian.

Setting Value
Destination URL http://jellyfin-librarian.bots.svc:8080/webhook
Event type Authentication Success
Content-Type header application/json
Request body template
{
  "NotificationType": "{{NotificationType}}",
  "NotificationUsername": "{{NotificationUsername}}",
  "UserId": "{{UserId}}"
}

Body template required

The plugin sends an empty body by default. The request body template and Content-Type: application/json header must both be set or the handler will fail to parse the payload.