Service — Authentik (SSO)

What it is

Authentik is a self-hosted identity provider (IdP). It provides single sign-on (SSO) via OAuth2 / OIDC so users register once and log in to every junc service with one account. The Authentik UUID is the canonical per-user identity across the whole junc — including Quorra.

Location

  • Admin UI: https://auth.juncyard.com/if/admin/
  • User portal: https://auth.juncyard.com
  • Port: 9090:9000 (host:container)
  • Compose: ~/projects/junc1/compose/auth/docker-compose.yml
  • Data: ~/data/auth/

Integrated services

ServiceURLStatus
Matrix (Synapse)chat.juncyard.comActive
Giteagit.juncyard.comActive
Open-WebUIquorra.juncyard.comActive
Nextcloudcloud.juncyard.comActive
Actual Budgetbudget.juncyard.comActive
Jellyfinwatch.juncyard.comActive (via SSO plugin)
Immichphotos.juncyard.comActive

Adding a new service

  1. In Authentik admin: Applications → Providers → Create → OAuth2/OpenID Provider
    • Use an RSA signing key (required for Synapse and Actual Budget; safe default for all).
    • Set issuer_mode to per_provider for services that validate the issuer claim (e.g. the Jellyfin SSO plugin).
    • Set the redirect URI to https://<service-url>/<service-specific-callback-path>.
  2. Create an Application linked to the provider (the slug becomes part of the discovery URL).
  3. Discovery URL format: https://auth.juncyard.com/application/o/<slug>/.well-known/openid-configuration
  4. Configure the service with the client ID, secret, and discovery URL.

User invitations

To invite a new household member:

  1. Admin → Directory → Invitations → Create — set an expiry, optionally tie it to a group.
  2. Send them the generated link (format: https://auth.juncyard.com/if/flow/default-source-enrollment/?itoken=...).
  3. They complete signup (username + password) and are logged in automatically as an Internal user.

How the enrollment flow is wired (default-source-enrollment):

OrderStagePurpose
0invitation-stageValidates the invite token; blocks the flow without one
0default-source-enrollment-promptCollects username, password, repeat password
1default-source-enrollment-writeCreates the user (type: Internal)
2default-source-enrollment-loginLogs the user in immediately

Notes

  • Authentik requires Redis — the authentik-redis container must run alongside authentik-server and authentik-worker.
  • Synapse’s public_baseurl must be https://matrix.juncyard.com for the OIDC callback URL to resolve correctly.
  • Actual Budget requires the RS256 signing algorithm specifically; its callback URI is https://budget.juncyard.com/openid/callback; it auto-creates users on first SSO login (ACTUAL_USER_CREATION_MODE=login).
  • Gitea: the provider must use sub_mode=user_id (returns an integer PK); the external_login_user.external_id column must match that integer string.
  • Jellyfin: uses the 9p4/jellyfin-plugin-sso plugin; the provider must use issuer_mode=per_provider; register both HTTP and HTTPS redirect URIs (/sso/OID/r/authentik).
  • Nextcloud: the User OIDC app must be installed (occ app:install user_oidc) before configuring the provider; configure it via occ user_oidc:provider.
  • Immich stores its OAuth config in the system_metadata Postgres table (key = 'system-config'), not in env vars.