Skip to main content
4nton Hugo Site
About Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Selfhosted SSO med Authentik

Selfhosted SSO med Authentik

Dokumentation for at centralisere login til mine selfhostede services (Forgejo, Jellyfin, n8n, Kanboard, Shaarli, WebDAV) bag én identity provider, i stedet for separat auth pr. app.

Hvorfor

  • Ét login-flow og én 2FA-politik i stedet for app-for-app opsætning.
  • Tilføjer 2FA til services der i dag ikke har det (fx WebDAV, som kun er beskyttet af et langt password).
  • Centraliseret brugerstyring og adgangslog.

Footprint

Komponent Rolle
server Web-UI, API, OIDC/SAML-endpoints
worker Baggrundsjobs (flows, outpost-sync)
PostgreSQL Database
Redis Cache/session store

Officielt minimum er 2 CPU-tråde + 2 GB RAM. I et lille setup som dette kører det typisk fint med ~1 CPU / 1.5-2 GB RAM i idle. Det er klart tungere end Authelia (ingen database, enkelt Go-binary, <50 MB RAM), men til gengæld får man en fuld UI, bruger-admin og indbyggede outposts.

Arkitektur

Native OIDC-apps taler direkte med Authentik. Apps uden SSO-support (Shaarli, Kanboard, WebDAV) sidder bag en Proxy Outpost, som agerer selvstændig reverse proxy — det er den vej, der passer bedst til Synology DSM’s reverse proxy, da DSM’s GUI ikke understøtter custom nginx-direktiver som auth_request.

graph LR
  Internet -->|HTTPS 443| DSM[Synology Reverse Proxy]

  DSM -->|forgejo.4nton.dk| Forgejo[Forgejo]
  DSM -->|jellyfin.4nton.dk| Jellyfin[Jellyfin]

  DSM -->|shaarli.4nton.dk| Outpost[Authentik Proxy Outpost]
  DSM -->|kanboard.4nton.dk| Outpost
  DSM -->|n8n.4nton.dk| Outpost

  DSM -->|dav.4nton.dk| WebDAV[WebDAV - uden for SSO-planen]

  Outpost -->|header-auth, ægte SSO| Kanboard
  Outpost -->|dobbelt login| Shaarli
  Outpost -->|dobbelt login| N8N[n8n]

  Forgejo -.OIDC.-> Authentik[(Authentik Server)]
  Jellyfin -.OIDC.-> Authentik
  Outpost -.auth check.-> Authentik

  Authentik --- DB[(PostgreSQL)]
  Authentik --- Cache[(Redis)]

Login-flow, native OIDC-app (fx Forgejo)

sequenceDiagram
  participant Bruger
  participant Forgejo
  participant Authentik

  Bruger->>Forgejo: Ã…bner forgejo.4nton.dk
  Forgejo->>Bruger: Redirect til Authentik (authorize)
  Bruger->>Authentik: Login + 2FA
  Authentik->>Bruger: Redirect med authorization code
  Bruger->>Forgejo: Code
  Forgejo->>Authentik: Exchange code for token
  Authentik->>Forgejo: ID token + access token
  Forgejo->>Bruger: Logget ind

Login-flow, app uden SSO-support (fx Shaarli, via outpost)

sequenceDiagram
  participant Bruger
  participant DSM as DSM Reverse Proxy
  participant Outpost as Authentik Outpost
  participant Shaarli
  participant Authentik

  Bruger->>DSM: GET shaarli.4nton.dk
  DSM->>Outpost: Forward request
  Outpost->>Outpost: Gyldig session?
  alt Ingen session
    Outpost->>Bruger: Redirect til Authentik login
    Bruger->>Authentik: Login + 2FA
    Authentik->>Outpost: Session cookie sat
  end
  Outpost->>Shaarli: Forward original request
  Shaarli->>Bruger: Side vises

Setup

1. Docker Compose

services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${PG_PASS}
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik

  redis:
    image: docker.io/library/redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis:/data

  server:
    image: ghcr.io/goauthentik/server:2024.10.1  # opdater til nyeste stabile tag fra GitHub releases
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_REDIS__HOST: redis
    volumes:
      - media:/media
      - templates:/templates
    ports:
      - "9000:9000"
      - "9443:9443"
    depends_on:
      - postgresql
      - redis

  worker:
    image: ghcr.io/goauthentik/server:2024.10.1  # samme tag som server
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_REDIS__HOST: redis
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - media:/media
      - templates:/templates
    depends_on:
      - postgresql
      - redis

volumes:
  database:
  redis:
  media:
  templates:

.env skal indeholde:

PG_PASS=<random, lang streng>
AUTHENTIK_SECRET_KEY=<openssl rand -base64 36>

2. Første opstart

  1. docker compose up -d
  2. Åbn https://<intern-ip>:9443/if/flow/initial-setup/ og sæt admin-password.
  3. Log ind pÃ¥ admin-UI’et.

3. Native OIDC-apps (Forgejo, Jellyfin)

Pr. app i Authentik:

  1. Applications → Create — giv den et navn og slug.
  2. Providers → Create → OAuth2/OpenID Provider — sæt redirect URI til appens callback-URL (fx https://forgejo.4nton.dk/user/oauth2/authentik/callback).
  3. Kobl provideren til applikationen.
  4. Indsæt Client ID/Secret i appens egen OIDC/OAuth2-konfiguration (Forgejo: app.ini eller admin-UI under Authentication Sources; Jellyfin: SSO-plugin).

n8n er udeladt her: SSO (SAML/OIDC) er en Enterprise-feature i n8n og er ikke med i min licens. n8n kan derfor ikke være en native OIDC-app — den er i stedet lagt i gruppen nedenfor, bag outposten.

4. Apps uden SSO-support (Shaarli, Kanboard, n8n)

  1. Providers → Create → Proxy Provider — vælg Forward auth (single application) eller Proxy mode.
  2. Outposts → Create — tilknyt provideren, lad Authentik generere en outpost-container.
  3. Kør outpost-containeren i Docker (Authentik giver et docker-compose-snippet med token).
  4. Peg DSM’s reverse proxy for shaarli.4nton.dk / kanboard.4nton.dk / n8n.4nton.dk pÃ¥ outpost-containerens interne port, ikke direkte pÃ¥ appen længere.
  5. Tilføj en 2FA-stage (TOTP/WebAuthn) til login-flowet.

Ægte SSO vs. dobbelt login — det er forskelligt pr. app

App Resultat Hvorfor
Kanboard Ægte SSO, ét login Understøtter REVERSE_PROXY_AUTH — den stoler på en header fra outposten i stedet for at vise sin egen login-side
Shaarli Dobbelt login Ingen dokumenteret mulighed for header-baseret auth-bypass — har kun sin egen formular-login
n8n Dobbelt login Community-edition har ingen SSO/header-support (Enterprise-feature)

For Kanboard, sæt i dens config (eller env-variabler):

REVERSE_PROXY_AUTH=true
REVERSE_PROXY_USER_HEADER=HTTP_X_AUTHENTIK_USERNAME
REVERSE_PROXY_EMAIL_HEADER=HTTP_X_AUTHENTIK_EMAIL
TRUSTED_PROXY_NETWORKS=<outpost-containerens interne IP/CIDR>

Verificer det eksakte header-navn Authentiks proxy-outpost sender i din version (typisk X-authentik-username/X-authentik-email), før du låser TRUSTED_PROXY_NETWORKS til kun outpostens IP — ellers kan en klient der går uden om outposten forfalske headeren og udgive sig for en anden bruger.

Shaarli og n8n beholder deres eget login bag outposten — det er en accepteret UX-trade-off, da begge allerede har deres egen 2FA.

5. WebDAV er bevidst udeladt fra SSO-planen

Authentiks forward-auth virker ved at omdirigere en browser til en interaktiv login-side med 2FA. WebDAV-klienter (kalender-/kontakt-sync, Finder/Explorer-netværksdrev) er ikke browsere — de sender HTTP Basic/Digest-credentials direkte og kan ikke følge en redirect eller indtaste en 2FA-kode. At lægge outposten foran WebDAV vil sandsynligvis ødelægge disse klienter, ikke bare give dobbelt login.

WebDAV fortsætter derfor som i dag: eget, random genereret password på 35+ tegn, ingen SSO/outpost.

Checkliste

  • .env med unikke secrets, ikke committed til git
  • Pin Authentik-versionen (ikke :latest) — tjek GitHub releases for nyeste stabile tag
  • 2FA-stage tilføjet til default login-flow
  • Native OIDC konfigureret for Forgejo, Jellyfin
  • Proxy outpost kørende for Shaarli, Kanboard, WebDAV, n8n (n8n fÃ¥r dobbelt login — accepteret trade-off)
  • DSM reverse proxy opdateret til at pege pÃ¥ outpost i stedet for direkte pÃ¥ apps
  • Gammelt direkte login (uden SSO) deaktiveret pr. app, sÃ¥ Authentik bliver den eneste vej ind