Add staged Authentik stack and Grafana OIDC wiring
This commit is contained in:
6
identity-authentik/.env.example
Normal file
6
identity-authentik/.env.example
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
AUTHENTIK_POSTGRES_DB=authentik
|
||||||
|
AUTHENTIK_POSTGRES_USER=authentik
|
||||||
|
AUTHENTIK_POSTGRES_PASSWORD=CHANGE_ME
|
||||||
|
AUTHENTIK_SECRET_KEY=CHANGE_ME
|
||||||
|
AUTHENTIK_BOOTSTRAP_PASSWORD=CHANGE_ME
|
||||||
|
AUTHENTIK_BOOTSTRAP_TOKEN=CHANGE_ME
|
||||||
64
identity-authentik/README.md
Normal file
64
identity-authentik/README.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Identity / SSO - Authentik
|
||||||
|
|
||||||
|
This stack stages an Authentik migration in parallel with the current Authelia deployment so cutover can happen app-by-app with easy rollback.
|
||||||
|
|
||||||
|
Current design choices:
|
||||||
|
|
||||||
|
- Authentik server + worker only
|
||||||
|
- shared Postgres for durable storage
|
||||||
|
- embedded outpost for Traefik forward-auth
|
||||||
|
- no Redis dependency
|
||||||
|
- no Docker socket mount
|
||||||
|
- keep Authelia alive until all apps validate cleanly
|
||||||
|
|
||||||
|
Why this shape:
|
||||||
|
|
||||||
|
- it future-proofs the identity plane without turning migration into a flag day
|
||||||
|
- it preserves easy rollback while Authentik is proven per app
|
||||||
|
- it matches the homelab preference for shared database infra over one-off local state
|
||||||
|
- embedded outpost is enough for this size and avoids extra moving parts
|
||||||
|
|
||||||
|
Files:
|
||||||
|
|
||||||
|
- docker-compose.yaml
|
||||||
|
- .env.example
|
||||||
|
- custom-templates/.gitkeep
|
||||||
|
|
||||||
|
Bootstrap:
|
||||||
|
|
||||||
|
1. Copy this directory to PD at /mnt/docker-ssd/docker/compose/identity-authentik
|
||||||
|
2. Copy .env.example to .env and replace every CHANGE_ME
|
||||||
|
3. Create the Authentik database/user in shared Postgres
|
||||||
|
4. Validate and start:
|
||||||
|
|
||||||
|
cd /mnt/docker-ssd/docker/compose/identity-authentik
|
||||||
|
docker compose --env-file .env config
|
||||||
|
docker compose --env-file .env up -d
|
||||||
|
|
||||||
|
5. Verify readiness:
|
||||||
|
|
||||||
|
docker compose ps
|
||||||
|
docker logs authentik-server --tail=50
|
||||||
|
curl -fsS http://127.0.0.1:9000/-/health/ready/
|
||||||
|
|
||||||
|
6. Complete initial login with the bootstrap admin on the internal URL first, then wire the public auth route.
|
||||||
|
7. Build providers before cutover:
|
||||||
|
|
||||||
|
- Grafana: OAuth2/OIDC provider
|
||||||
|
- Gitea: proxy provider, forward auth, single application
|
||||||
|
- Technitium: proxy provider, forward auth, single application
|
||||||
|
- Traefik dashboard: proxy provider, forward auth, single application
|
||||||
|
|
||||||
|
8. Bind those proxy providers to the embedded outpost.
|
||||||
|
9. Cut apps over one at a time from Authelia forward-auth to Authentik forward-auth.
|
||||||
|
10. Only remove Authelia after every migrated app and logout flow is verified.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Authentik listens internally on port 9000 for HTTP and serves the embedded outpost paths there too.
|
||||||
|
- The Traefik middleware should call:
|
||||||
|
http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
|
||||||
|
- Each forward-auth protected app also needs a higher-priority router for:
|
||||||
|
PathPrefix(`/outpost.goauthentik.io/`)
|
||||||
|
routed to Authentik, or the login flow will break.
|
||||||
|
- Grafana should end on native OIDC instead of remaining behind forward-auth long-term.
|
||||||
0
identity-authentik/custom-templates/.gitkeep
Normal file
0
identity-authentik/custom-templates/.gitkeep
Normal file
70
identity-authentik/docker-compose.yaml
Normal file
70
identity-authentik/docker-compose.yaml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
name: identity-authentik
|
||||||
|
|
||||||
|
services:
|
||||||
|
authentik-server:
|
||||||
|
image: ghcr.io/goauthentik/server:2026.5.0
|
||||||
|
container_name: authentik-server
|
||||||
|
command: server
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
|
environment:
|
||||||
|
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||||
|
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST: shared-postgres
|
||||||
|
AUTHENTIK_POSTGRESQL__PORT: 5432
|
||||||
|
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB}
|
||||||
|
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER}
|
||||||
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD}
|
||||||
|
AUTHENTIK_POSTGRESQL__SSLMODE: disable
|
||||||
|
AUTHENTIK_BOOTSTRAP_PASSWORD: ${AUTHENTIK_BOOTSTRAP_PASSWORD}
|
||||||
|
AUTHENTIK_BOOTSTRAP_TOKEN: ${AUTHENTIK_BOOTSTRAP_TOKEN}
|
||||||
|
volumes:
|
||||||
|
- /mnt/tank/docker/appdata/authentik:/data
|
||||||
|
- /mnt/docker-ssd/docker/compose/identity-authentik/custom-templates:/templates
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9000/-/health/ready/ >/dev/null || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 5
|
||||||
|
start_period: 45s
|
||||||
|
shm_size: 512mb
|
||||||
|
networks:
|
||||||
|
- ix-databases_shared-databases
|
||||||
|
- pangolin
|
||||||
|
|
||||||
|
authentik-worker:
|
||||||
|
image: ghcr.io/goauthentik/server:2026.5.0
|
||||||
|
container_name: authentik-worker
|
||||||
|
command: worker
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||||
|
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
|
||||||
|
AUTHENTIK_POSTGRESQL__HOST: shared-postgres
|
||||||
|
AUTHENTIK_POSTGRESQL__PORT: 5432
|
||||||
|
AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB}
|
||||||
|
AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER}
|
||||||
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD}
|
||||||
|
AUTHENTIK_POSTGRESQL__SSLMODE: disable
|
||||||
|
AUTHENTIK_BOOTSTRAP_PASSWORD: ${AUTHENTIK_BOOTSTRAP_PASSWORD}
|
||||||
|
AUTHENTIK_BOOTSTRAP_TOKEN: ${AUTHENTIK_BOOTSTRAP_TOKEN}
|
||||||
|
volumes:
|
||||||
|
- /mnt/tank/docker/appdata/authentik:/data
|
||||||
|
- /mnt/docker-ssd/docker/compose/identity-authentik/custom-templates:/templates
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "ak healthcheck >/dev/null 2>&1 || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 30s
|
||||||
|
retries: 5
|
||||||
|
start_period: 60s
|
||||||
|
shm_size: 512mb
|
||||||
|
networks:
|
||||||
|
- ix-databases_shared-databases
|
||||||
|
- pangolin
|
||||||
|
|
||||||
|
networks:
|
||||||
|
ix-databases_shared-databases:
|
||||||
|
external: true
|
||||||
|
pangolin:
|
||||||
|
external: true
|
||||||
@@ -5,9 +5,10 @@ GF_ADMIN_USER=admin
|
|||||||
GF_ADMIN_PASS=CHANGE_ME
|
GF_ADMIN_PASS=CHANGE_ME
|
||||||
GF_HOST=grafana.paccoco.com
|
GF_HOST=grafana.paccoco.com
|
||||||
LOKI_HOST=loki.paccoco.com
|
LOKI_HOST=loki.paccoco.com
|
||||||
AUTHELIA_HOST=auth.paccoco.com
|
AUTHENTIK_HOST=auth.paccoco.com
|
||||||
|
GF_AUTHENTIK_APP_SLUG=grafana
|
||||||
GF_AUTH_GENERIC_OAUTH_ENABLED=true
|
GF_AUTH_GENERIC_OAUTH_ENABLED=true
|
||||||
GF_AUTH_GENERIC_OAUTH_NAME=Authelia
|
GF_AUTH_GENERIC_OAUTH_NAME=Authentik
|
||||||
GF_AUTH_GENERIC_OAUTH_ICON=signin
|
GF_AUTH_GENERIC_OAUTH_ICON=signin
|
||||||
GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana
|
GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana
|
||||||
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=CHANGE_ME
|
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=CHANGE_ME
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ services:
|
|||||||
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: ${GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET}
|
GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET: ${GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET}
|
||||||
GF_AUTH_GENERIC_OAUTH_SCOPES: ${GF_AUTH_GENERIC_OAUTH_SCOPES}
|
GF_AUTH_GENERIC_OAUTH_SCOPES: ${GF_AUTH_GENERIC_OAUTH_SCOPES}
|
||||||
GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES: ${GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES}
|
GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES: ${GF_AUTH_GENERIC_OAUTH_EMPTY_SCOPES}
|
||||||
GF_AUTH_GENERIC_OAUTH_AUTH_URL: https://${AUTHELIA_HOST}/api/oidc/authorization
|
GF_AUTH_GENERIC_OAUTH_AUTH_URL: https://${AUTHENTIK_HOST}/application/o/authorize/
|
||||||
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: https://${AUTHELIA_HOST}/api/oidc/token
|
GF_AUTH_GENERIC_OAUTH_TOKEN_URL: https://${AUTHENTIK_HOST}/application/o/token/
|
||||||
GF_AUTH_GENERIC_OAUTH_API_URL: https://${AUTHELIA_HOST}/api/oidc/userinfo
|
GF_AUTH_GENERIC_OAUTH_API_URL: https://${AUTHENTIK_HOST}/application/o/userinfo/
|
||||||
|
GF_AUTH_SIGNOUT_REDIRECT_URL: https://${AUTHENTIK_HOST}/application/o/${GF_AUTHENTIK_APP_SLUG}/end-session/
|
||||||
GF_AUTH_GENERIC_OAUTH_USE_PKCE: ${GF_AUTH_GENERIC_OAUTH_USE_PKCE}
|
GF_AUTH_GENERIC_OAUTH_USE_PKCE: ${GF_AUTH_GENERIC_OAUTH_USE_PKCE}
|
||||||
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: ${GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP}
|
GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP: ${GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP}
|
||||||
GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN: ${GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN}
|
GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN: ${GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN}
|
||||||
|
|||||||
Reference in New Issue
Block a user