Files
nuzlocke-tracker/docker-compose.yml
Julian Tabel 177c02006a
All checks were successful
CI / backend-tests (pull_request) Successful in 28s
CI / frontend-tests (pull_request) Successful in 28s
feat: migrate JWT verification from HS256 shared secret to JWKS
Replace symmetric HS256 JWT verification with asymmetric RS256 using JWKS.
Backend now fetches and caches public keys from Supabase's JWKS endpoint
instead of using a shared secret.

- Add cryptography dependency for RS256 support
- Use PyJWKClient to fetch/cache JWKS from {SUPABASE_URL}/.well-known/jwks.json
- Remove SUPABASE_JWT_SECRET from config, docker-compose, deploy workflow, .env
- Update tests to use RS256 tokens with mocked JWKS client

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 14:01:36 +01:00

102 lines
3.1 KiB
YAML

services:
api:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8080:8000"
volumes:
- ./backend/src:/app/src:cached
- ./backend/alembic.ini:/app/alembic.ini:cached
- ./frontend/public:/frontend/public
environment:
- DEBUG=true
- DATABASE_URL=postgresql://postgres:postgres@db:5432/nuzlocke
# Auth - uses JWKS from GoTrue for JWT verification
- SUPABASE_URL=http://gotrue:9999
depends_on:
db:
condition: service_healthy
gotrue:
condition: service_healthy
restart: unless-stopped
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "5173:5173"
volumes:
- ./frontend/src:/app/src:cached
- ./frontend/public:/app/public:cached
- ./frontend/index.html:/app/index.html:cached
environment:
- VITE_API_URL=http://localhost:8080
# Local GoTrue auth
- VITE_SUPABASE_URL=http://localhost:9999
- VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzc0MDQwNjEzLCJleHAiOjIwODk0MDA2MTN9.EV6tRj7gLqoiT-l2vDFw_67myqRjwpcZTuRb3Xs1nr4
depends_on:
- api
- gotrue
restart: unless-stopped
db:
image: postgres:18-alpine
ports:
- "5432:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=nuzlocke
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/init:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
gotrue:
image: supabase/gotrue:v2.188.1
ports:
- "9999:9999"
environment:
# API settings
- GOTRUE_API_HOST=0.0.0.0
- GOTRUE_API_PORT=9999
- API_EXTERNAL_URL=http://localhost:9999
- GOTRUE_SITE_URL=http://localhost:5173
# Database
- GOTRUE_DB_DRIVER=postgres
- GOTRUE_DB_DATABASE_URL=postgres://postgres:postgres@db:5432/nuzlocke?sslmode=disable&search_path=auth
# JWT - must match backend's SUPABASE_JWT_SECRET
- GOTRUE_JWT_SECRET=super-secret-jwt-token-with-at-least-32-characters-long
- GOTRUE_JWT_AUD=authenticated
- GOTRUE_JWT_EXP=3600
- GOTRUE_JWT_ADMIN_ROLES=service_role
# Email auth (auto-confirm for local dev)
- GOTRUE_EXTERNAL_EMAIL_ENABLED=true
- GOTRUE_MAILER_AUTOCONFIRM=true
- GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED=false
# Disable external OAuth providers (not configured locally)
- GOTRUE_EXTERNAL_GOOGLE_ENABLED=false
- GOTRUE_EXTERNAL_DISCORD_ENABLED=false
# Disable phone auth
- GOTRUE_EXTERNAL_PHONE_ENABLED=false
- GOTRUE_SMS_AUTOCONFIRM=false
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9999/health"]
interval: 5s
timeout: 5s
retries: 3
restart: unless-stopped
volumes:
postgres_data: