Authentik ile Homelab SSO Kurdum: 60 Gunluk Notlarim
Homelab'ım büyüdükçe gardırobumdan da daha kalabalık bir login ekranı koleksiyonum oldu: Grafana, Uptime Kuma, Vaultwarden, AdGuard, MCP dashboard, Portainer, SearXNG admin paneli, n8n, Authentik'in kendisi, Proxmox, Headscale UI ve birkaç ic dashboard daha. Bitwarden'da "homelab" klasoru 30 girise dayandi. Mart sonunda dedim ki yeter — bir SSO katmani koymam lazim. 60 gun once Authentik kurdum. Bu yazi o 60 gunun durust ozeti: neyin calistigi, neyin calismadigi, kac MB RAM yedigi ve niye Authelia'yi iki haftada birakttim.
Once Authelia Denedim, Iki Haftada Vazgectim
Konuya Authentik ile baslamadim. Ilk tercih Authelia idi cunku daha hafif goruluyordu (~50MB RAM, Authentik ~800MB), Go ile yazilmis ve docker-compose'da iki container ile cikiyor. Iki hafta sonra braktim ve sebebi performans degildi — kullanim deneyimi idi.
Authelia, tum konfigurasyonunu tek bir configuration.yml icinde toparlar. Yeni bir kullanici, yeni bir kural, yeni bir client ekleyecekseniz YAML editor'unu aciyorsunuz. Bunu CI/CD ile Git'e baglayip "infrastructure as code" yapan insanlar var, hayranlikla okuyorum, ama benim isim her sefer kucuk bir kural eklemek icin SSH + vim + reload. Bir hafta sonunda farkettim ki AdGuard'da bir kullaniciyi suspend etmek 5 saniye, Authelia'da 90 saniye. Bu psikolojik bir engel. Otomatize ederim, evet — ama 12 servislik bir homelab icin overkill.
Ek olarak Authelia'nin OIDC implementasyonu bekleyen feature listesinde "experimental" idi (Authelia v4.38 sirasinda). Grafana'yi OIDC ile baglamak istediğimde olmadi. Forward auth calisiyordu, ama Grafana'nin "role mapping" ozelliği OIDC claim'lerine bagliydi ve Authelia'nin token'inda istediğim claim yoktu. O gece Authentik'e gectim.
Authentik'in Calistirma Maliyeti
Authentik, PostgreSQL + Redis + iki container (server, worker) ile geliyor. Ilk RAM olcumum (idle, 0 aktif kullanici):
| Container | RAM | CPU (idle) | |---|---|---| | authentik-server | ~280 MB | %0.5 | | authentik-worker | ~180 MB | %0.2 | | postgres (sadece authentik icin) | ~110 MB | %0.1 | | redis (sadece authentik icin) | ~25 MB | %0.0 | | Toplam | ~595 MB | — |
Yuk altinda (5 paralel login simulasyonu, Vegeta ile) toplam RAM yaklasik 800 MB'a cikti. Authelia'nin ~50 MB'lik figurune kiyasla 16 kat fazla. Ama Mac Mini M4'um 24 GB RAM ile geliyor ve Authentik o kapasiteyi rahatsiz etmeden tutuyor. Senin Raspberry Pi Zero ile homelab calistiriyorsan Authelia hala daha akilli secim.
Docker Compose dosyamin onemli kisimlari:
# docker-compose.yml (authentik)
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
volumes:
- ./pg-data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: authentik
POSTGRES_DB: authentik
redis:
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
restart: unless-stopped
volumes:
- ./redis-data:/data
server:
image: ghcr.io/goauthentik/server:2026.4.2
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
volumes:
- ./media:/media
- ./custom-templates:/templates
ports:
- "9000:9000"
- "9443:9443"
depends_on:
postgresql: { condition: service_healthy }
redis: { condition: service_started }
worker:
image: ghcr.io/goauthentik/server:2026.4.2
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./media:/media
- ./certs:/certs
- ./custom-templates:/templates
Secret'leri Vault'tan cekiyorum (secret/services/authentik), .env icin AppRole token kullaniyorum. Ilk hatam buydu zaten — postgres parolasini direkt .env'e gomdum, ertesi gun git status'ta gordum. git rm --cached .env, .gitignore'a ekleme, Vault'tan tekrar cekme — 20 dakikalik bir egzersiz. Bunu yazmaya utaniyorum ama gercek olan budur.
Forward Auth vs Proxy Provider: Hangisi?
Authentik iki farkli yontem sunuyor:
- Proxy Provider (Outpost) — Authentik kendi proxy outpost'unu calistiriyor, servisinizin onunde duruyor. Servisinizi direkt expose etmiyorsunuz; outpost expose oluyor.
- Forward Auth — Mevcut reverse proxy'niz (Caddy, Traefik, Nginx) her istegin oncesinde Authentik'e "bu kullanici icerde mi?" diye soruyor.
Ben Caddy kullaniyorum ve forward auth'u sectim. Sebep: ek bir proxy katmani daha eklemek istemedim ve Caddy'nin forward_auth directive'i 4 satirda hallediyor.
# Caddyfile - Grafana SSO arkasinda
grafana.efa.local {
forward_auth authentik-server:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-authentik-username X-authentik-groups X-authentik-email X-authentik-name X-authentik-uid X-authentik-jwt
trusted_proxies private_ranges
}
reverse_proxy grafana:3000
}
Tek dikkat noktasi trusted_proxies private_ranges satiri. Bu olmadan Caddy X-Forwarded-For header'ini sanitize etmiyor ve Authentik kullanici IP'sini "172.18.0.3" gibi Docker network IP'si olarak goruyor. Login geo-lokasyon kuralinizi calistirinca herkes "bilinmeyen IP" diye flag oluyor ve MFA promptu duser. Bu hatayi 4 gun sonra fark ettim, "neden her login'de tekrar 2FA istiyor" diye kullanici loglari okurken yakaladim.
OIDC ile Grafana: Authentik'in Asil Kazandirdigi Yer
Forward auth iyi guzel, ama bazi servisler (Grafana, Vaultwarden, n8n) OIDC ile dogal entegre olabiliyor. Bu durumda kullanici Authentik tarafinda hangi grupta ise Grafana'da otomatik olarak Admin/Editor/Viewer rolu aliyor. Forward auth'da bunu yapamiyorsunuz; oturum acaniyor ama rol yonetimi ayri.
Grafana grafana.ini:
[auth.generic_oauth]
enabled = true
name = Authentik
client_id = REPLACE_WITH_CLIENT_ID
client_secret = REPLACE_WITH_CLIENT_SECRET
scopes = openid profile email
auth_url = https://authentik.efa.local/application/o/authorize/
token_url = https://authentik.efa.local/application/o/token/
api_url = https://authentik.efa.local/application/o/userinfo/
role_attribute_path = contains(groups[*], 'grafana-admin') && 'Admin' || contains(groups[*], 'grafana-editor') && 'Editor' || 'Viewer'
allow_assign_grafana_admin = true
role_attribute_path Grafana'nin JMESPath ifadesini kullaniyor. Authentik tarafinda iki grup actim (grafana-admin, grafana-editor), kendimi admin'e ekledim, esime editor (Uptime Kuma dashboard'umu izlemek istemis), kalanlar viewer. Bunun guzel tarafi: Authentik'te bir kullaniciyi gruptan cikardigimda Grafana'ya bir sonraki login'inde yeni rolu otomatik aliyor. Ayni mantik n8n ve Vaultwarden icinde calisiyor.
Yari-Basarisiz Olan Iki Deneme
1. AdGuard'i SSO Arkasina Almak
Bu hayalim vardi: AdGuard Home admin paneline Authentik ile login. Iki problemle karsilastim:
- AdGuard'in kendi basic auth'unu kapatamiyorsunuz. WebUI uzerinden basic auth wrapper'i siliyor ve forward auth gecsin bekliyorsunuz, ama AdGuard internal API endpoint'leri (
/control/statusgibi) hala basic auth bekliyor. iOS uygulamasi bu endpoint'leri kullaniyor ve forward auth gormeyince patliyor. - Forward auth ile mobile uygulama uyumsuz. AdGuard'in iOS uygulamasi cookie-based auth'u takip etmiyor.
Bir hafta tirnak yedim, sonra vazgectim. AdGuard'in onunde "internal-only" subnet kurali ekledim (sadece yerel ag), basic auth'i guclendirdim ve ettim. Homelab'da her seyi SSO arkasina alma zorunlulugu yok; bazi servisler buna mimari olarak hazir degil ve zorlamak vakit kaybi.
2. LDAP Outpost ile Vaultwarden
Vaultwarden, OIDC'yi resmen desteklemiyor (upstream Bitwarden Enterprise feature olarak). Authentik'in LDAP outpost'u var; Vaultwarden'in LDAP login plugin'i de var. Birlestirdigimde teoride calismasi gerekirdi. Pratikte:
- LDAP outpost ek bir container (~150 MB RAM)
- Vaultwarden'in LDAP plugin'i unofficial fork
- Hata mesajlari "bind failed" gibi generik
Iki gunden sonra Vaultwarden'i SSO disinda biraktim. Sadece master password + 2FA ile, ama 2FA'yi Authentik'in TOTP'siyle ayni Yubikey'e bagladim. Bu yarim cozum, ama Vaultwarden zaten "kasayi acan tek anahtar" oldugu icin ek SSO ekstra surtunmedir.
Performans: 60 Gunluk Olcumler
Authentik kurulumumdan 60 gun sonraki gercek sayilar:
- Login latency (forward auth ilk istek): p50 ~85ms, p95 ~210ms, p99 ~480ms
- Login latency (OIDC redirect-flow ilk login): ~1.2-1.8 saniye (kullanicinin tarafinda)
- Sonraki istekler (cookie cached): p95 ~12ms (cunku Caddy'nin forward auth cache'i devrede)
- Toplam Authentik RAM (8 servis arkasinda, aktif kullanim): ~850 MB
- Disk kullanimi (60 gun): PostgreSQL 78 MB, log dosyalari 240 MB (debug seviyesinde)
Login latency'sinin p99'u (480ms) ilk basta beni rahatsiz etti, ama incelediğimde Redis'in disk persistence ayari yuzunden donmus oldugunu gordum (--save 60 1 her dakikada disk yaziyor; eski SSD'mde ara sira jitter). --save "" ile in-memory yapinca p99 ~180ms'ye dustu. Authentik session'larini kaybetmek istemiyorsan PostgreSQL'i kullaniyor, Redis sadece cache; bu cozum guvenli.
Su Anki Servis Listesi (SSO Arkasinda)
| Servis | Yontem | Notlar | |---|---|---| | Grafana | OIDC | Group → Role mapping calisiyor | | n8n | OIDC | Yine group-based | | Uptime Kuma | Forward Auth | OIDC desteklemiyor | | MCP Dashboard | Forward Auth | Kendi yazdigim panel | | Portainer | OIDC | Team mapping | | SearXNG admin | Forward Auth | Admin panel sade | | Headscale UI | Forward Auth | UI ucuncu parti | | Authentik (self) | Yerel admin | Recursive dependency riski yok |
12 servisten 8'i SSO arkasinda, 4'u (AdGuard, Vaultwarden, Proxmox web UI, Tailscale admin) kendi auth'larinda. Bu oran benim icin yeterli.
Notlar ve Cikarimlar
- Authentik vs Authelia: 30+ kullanici veya OIDC ile karmasik role mapping istiyorsan Authentik. Sade YAML konfigurasyonu yeten 5 kullaniciliksa Authelia.
- Forward auth, OIDC olmayan tum servisler icin gercekten kurtarici. Ama header sanitization'i (
trusted_proxies) atlama. - Her servisi SSO arkasina almak zorunda degilsin. AdGuard ve Vaultwarden gibi mobile-first / vault-first servislerde dirsek yorulur, kazanc azdir.
- PostgreSQL volume'unu yedeklemeyi unutma. Authentik DB'sini kaybedersen tum group mapping'leri tekrar kurmak gerekiyor; 8 servisin role config'i tek bir SQL dump'ta. Ben Restic ile gece 03:30'da PostgreSQL dump'ini Backblaze'e gonderiyorum.
- MFA'yi gun bir kurup unut. TOTP zorunlu yaptim, Yubikey'i de Authentik'in WebAuthn'u ile ekledim. Eski parolalarimi Bitwarden'dan silmedim ama artik bir yerde calismasin diye disable ettim.
Bir sonraki adim Headscale'i Authentik OIDC ile baglamak. Halen self-hosted Tailscale alternatifimle ayri auth katmaninda calisiyorum ve bu son tutarsizlik beni rahatsiz ediyor. O bittiginde belki bir yazi daha yazarim. Eger Authentik kurmus ve farkli entegrasyon yapmis biriyseniz, GitHub uzerinden config'lerinizi okumayi cok isterim.