mcvsphere/docker-compose.oauth.yml
Ryan Malloy 64ba7a69de fix OAuth token validation for Authentik opaque tokens
- Remove required_scopes validation (Authentik doesn't embed scopes in JWT)
- Add oauth_base_url config for proper HTTPS callback URLs
- Add docker-compose.dev.yml for host proxy via Caddy
- Update docker-compose.oauth.yml with unique domain label

Authentik uses opaque access tokens that don't include scope claims.
Authentication is enforced at the IdP level, so scope validation in
the token is unnecessary and was causing 401 errors.
2025-12-27 05:27:21 -07:00

163 lines
6.5 KiB
YAML

# OAuth-enabled deployment with Authentik
# Usage: docker compose -f docker-compose.yml -f docker-compose.oauth.yml up
#
# This overlay adds Authentik identity provider for OAuth authentication.
# Requires AUTHENTIK_* environment variables to be set.
services:
# ─────────────────────────────────────────────────────────────────────────
# mcvsphere MCP Server (with OAuth + HTTPS via Caddy)
# ─────────────────────────────────────────────────────────────────────────
mcvsphere:
build:
context: .
dockerfile: Dockerfile
container_name: mcvsphere
restart: unless-stopped
volumes:
- ./logs:/app/logs
env_file:
- .env.oauth
environment:
- MCP_TRANSPORT=streamable-http
- MCP_HOST=0.0.0.0
- MCP_PORT=8080
networks:
- mcvsphere-network
- caddy
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
labels:
# Caddy reverse proxy via caddy-docker-proxy
caddy: mcp.localhost
caddy.reverse_proxy: "{{upstreams 8080}}"
caddy.tls: internal
# ─────────────────────────────────────────────────────────────────────────
# PostgreSQL for Authentik
# ─────────────────────────────────────────────────────────────────────────
authentik-db:
image: postgres:16-alpine
container_name: mcvsphere-authentik-db
restart: unless-stopped
environment:
POSTGRES_DB: authentik
POSTGRES_USER: authentik
POSTGRES_PASSWORD: ${AUTHENTIK_DB_PASSWORD:?AUTHENTIK_DB_PASSWORD required}
volumes:
- authentik-db-data:/var/lib/postgresql/data
networks:
- authentik-internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U authentik"]
interval: 10s
timeout: 5s
retries: 5
# ─────────────────────────────────────────────────────────────────────────
# Redis for Authentik
# ─────────────────────────────────────────────────────────────────────────
authentik-redis:
image: redis:7-alpine
container_name: mcvsphere-authentik-redis
restart: unless-stopped
command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"]
volumes:
- authentik-redis-data:/data
networks:
- authentik-internal
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# ─────────────────────────────────────────────────────────────────────────
# Authentik Server
# ─────────────────────────────────────────────────────────────────────────
authentik-server:
image: ghcr.io/goauthentik/server:2024.10.4
container_name: mcvsphere-authentik-server
restart: unless-stopped
command: server
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?AUTHENTIK_SECRET_KEY required}
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-db
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD}
# Bootstrap admin user (first run only)
AUTHENTIK_BOOTSTRAP_EMAIL: ${AUTHENTIK_BOOTSTRAP_EMAIL:-admin@localhost}
AUTHENTIK_BOOTSTRAP_PASSWORD: ${AUTHENTIK_BOOTSTRAP_PASSWORD:-}
ports:
- "${AUTHENTIK_PORT:-9000}:9000"
- "${AUTHENTIK_HTTPS_PORT:-9443}:9443"
volumes:
- authentik-media:/media
- authentik-templates:/templates
depends_on:
authentik-db:
condition: service_healthy
authentik-redis:
condition: service_healthy
networks:
- authentik-internal
- mcvsphere-network
- caddy
healthcheck:
test: ["CMD", "ak", "healthcheck"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
labels:
# Caddy reverse proxy via caddy-docker-proxy
caddy: ${AUTHENTIK_HOST:-auth.l.supported.systems}
caddy.reverse_proxy: "{{upstreams 9000}}"
# ─────────────────────────────────────────────────────────────────────────
# Authentik Worker (background tasks)
# ─────────────────────────────────────────────────────────────────────────
authentik-worker:
image: ghcr.io/goauthentik/server:2024.10.4
container_name: mcvsphere-authentik-worker
restart: unless-stopped
command: worker
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-db
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD}
volumes:
- authentik-media:/media
- authentik-templates:/templates
depends_on:
authentik-db:
condition: service_healthy
authentik-redis:
condition: service_healthy
networks:
- authentik-internal
networks:
authentik-internal:
driver: bridge
mcvsphere-network:
external: true
name: ${COMPOSE_PROJECT_NAME:-mcvsphere}_default
caddy:
external: true
volumes:
authentik-db-data:
authentik-redis-data:
authentik-media:
authentik-templates: