# WebAuthn Server Complete Stack with Zero-Trust Architecture
# Auto-generated by @vmenon25/mcp-server-webauthn-client
#
# This docker-compose file provides a complete zero-trust WebAuthn stack:
# - Envoy Gateway (entry point with JWT verification)
# - WebAuthn Server (FIDO2/Passkey authentication + JWT issuer)
# - Example Service (Python FastAPI demonstrating JWT verification)
# - PostgreSQL 15 (with auto-schema initialization)
# - Redis 7 (session storage)
#
# Security: Passwords are stored as Docker secrets in ./secrets/
# Secrets are mounted as read-only files at /run/secrets/ in containers
#
# Architecture:
#   Client → Envoy Gateway (port 8000) → WebAuthn Server (JWT for /api/*)
#                                      → Example Service (protected endpoints)

services:
  # Envoy Gateway - Entry point for all traffic
  envoy-gateway:
    image: envoyproxy/envoy:v1.29-latest
    container_name: envoy-gateway
    ports:
      - "{{gateway_host_port}}:8000"  # Main gateway proxy
      - "{{gateway_admin_port}}:9901"  # Admin interface
    volumes:
      - ./envoy-gateway.yaml:/etc/envoy/envoy.yaml:ro
      - ./certs:/etc/envoy/certs:ro  # mTLS certificates
    command: ["-c", "/etc/envoy/envoy.yaml", "--service-cluster", "gateway"]
    depends_on:
      - webauthn-server
      - example-service-sidecar
    restart: unless-stopped
  postgres:
    image: postgres:15-alpine
    container_name: webauthn-postgres
    environment:
      POSTGRES_DB: webauthn
      POSTGRES_USER: webauthn_user
      POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
    secrets:
      - postgres_password
    ports:
      - "{{postgres_host_port}}:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      # Auto-run schema initialization on first startup (PostgreSQL executes in alphabetical order)
      # Mount entire migrations directory for easier maintenance (add new migrations without updating docker-compose)
      - ./migrations:/docker-entrypoint-initdb.d:ro
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U webauthn_user -d webauthn"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: webauthn-redis
    command: sh -c 'redis-server --requirepass "$$(cat /run/secrets/redis_password)"'
    secrets:
      - redis_password
    ports:
      - "{{redis_host_port}}:6379"
    volumes:
      - redis_data:/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # Jaeger - Distributed tracing (always included)
  jaeger:
    image: jaegertracing/all-in-one:1.53
    container_name: webauthn-jaeger
    ports:
      - "{{jaeger_ui_port}}:16686"                      # Jaeger UI
      - "{{jaeger_collector_http_port}}:14268"          # Collector HTTP
      - "{{jaeger_collector_grpc_port}}:14250"          # Collector gRPC
      - "{{jaeger_otlp_grpc_port}}:4317"                # OTLP gRPC
      - "{{jaeger_otlp_http_port}}:4318"                # OTLP HTTP
      - "{{jaeger_agent_compact_port}}:6831/udp"        # Agent compact thrift
      - "{{jaeger_agent_binary_port}}:6832/udp"         # Agent binary thrift
      - "{{jaeger_agent_config_port}}:5778"             # Agent config
    environment:
      - COLLECTOR_OTLP_ENABLED=true
    restart: unless-stopped

  # WebAuthn Server - JWT issuer and FIDO2 authentication
  webauthn-server:
    image: hitoshura25/webauthn-server:latest
    container_name: webauthn-server
    # Note: No direct port exposure - access only through Envoy Gateway
    # Use entrypoint override to read secrets and set environment variables
    entrypoint:
      - sh
      - -c
      - |
        export MPO_AUTHN_DB_PASSWORD=$$(cat /run/secrets/postgres_password)
        export MPO_AUTHN_REDIS_PASSWORD=$$(cat /run/secrets/redis_password)
        export MPO_AUTHN_JWT_MASTER_ENCRYPTION_KEY=$$(cat /run/secrets/jwt_master_key)
        exec java $$JAVA_OPTS -jar /app/app.jar
    environment:
      # JVM optimization for containerized environments (from Dockerfile)
      JAVA_OPTS: "-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+OptimizeStringConcat -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djava.security.egd=file:/dev/./urandom"
      # Database configuration
      MPO_AUTHN_DB_HOST: postgres
      MPO_AUTHN_DB_PORT: 5432
      MPO_AUTHN_DB_NAME: webauthn
      MPO_AUTHN_DB_USERNAME: webauthn_user
      # Redis configuration
      MPO_AUTHN_REDIS_HOST: redis
      MPO_AUTHN_REDIS_PORT: 6379
      # WebAuthn configuration
      MPO_AUTHN_APP_RELYING_PARTY_ID: {{relying_party_id}}
      MPO_AUTHN_APP_RELYING_PARTY_NAME: "{{relying_party_name}}"
      # JWT Key Rotation Configuration (HOCON duration format)
      MPO_AUTHN_JWT_KEY_ROTATION_ENABLED: "{{jwt_rotation_enabled}}"
      MPO_AUTHN_JWT_KEY_ROTATION_INTERVAL: "{{jwt_rotation_interval}}"
      MPO_AUTHN_JWT_KEY_GRACE_PERIOD: "{{jwt_grace_period}}"
      MPO_AUTHN_JWT_KEY_RETENTION: "{{jwt_retention}}"
      MPO_AUTHN_JWT_KEY_SIZE: "2048"
      MPO_AUTHN_JWT_KEY_ID_PREFIX: "webauthn"
    secrets:
      - postgres_password
      - redis_password
      - jwt_master_key
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped

  # Example Service Sidecar - Envoy proxy with mTLS termination
  example-service-sidecar:
    image: envoyproxy/envoy:v1.29-latest
    container_name: example-service-sidecar
    volumes:
      - ./istio/example-service-envoy.yaml:/etc/envoy/envoy.yaml:ro
      - ./certs:/etc/certs:ro  # mTLS certificates
    command: ["-c", "/etc/envoy/envoy.yaml", "--service-cluster", "example-service"]
    restart: unless-stopped

  # Example Service - Demonstrates JWT verification (runs behind mTLS sidecar)
  example-service:
    build:
      context: ../example-service
      dockerfile: Dockerfile
    container_name: example-service
    network_mode: "service:example-service-sidecar"  # Share network with sidecar
    environment:
      APP_PORT: 9001  # App listens on 9001, Envoy sidecar exposes 9000
      WEBAUTHN_JWKS_URL: "http://webauthn-server:8080/.well-known/jwks.json"
    depends_on:
      - webauthn-server
      - example-service-sidecar
    restart: unless-stopped

volumes:
  postgres_data:
    name: webauthn_postgres_data
  redis_data:
    name: webauthn_redis_data

# Docker secrets configuration
# Secrets are read from files in ./secrets/ directory
# These are auto-generated with secure random passwords by the MCP server
secrets:
  postgres_password:
    file: ./secrets/postgres_password
  redis_password:
    file: ./secrets/redis_password
  jwt_master_key:
    file: ./secrets/jwt_master_key
