name: keycloak-patterns services: postgres: image: postgres:16-alpine environment: POSTGRES_DB: ${POSTGRES_DB:-keycloak} POSTGRES_USER: ${POSTGRES_USER:-keycloak} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?copy .env.example to .env and set POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: - CMD-SHELL - pg_isready -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}" interval: 5s timeout: 5s retries: 12 networks: - keycloak-net restart: unless-stopped keycloak: image: quay.io/keycloak/keycloak:26.7.0 command: - start-dev - --import-realm environment: KC_DB: postgres KC_DB_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB:-keycloak} KC_DB_USERNAME: ${POSTGRES_USER:-keycloak} KC_DB_PASSWORD: ${POSTGRES_PASSWORD:?copy .env.example to .env and set POSTGRES_PASSWORD} KC_HOSTNAME: http://localhost:8080 KC_HTTP_ENABLED: "true" KC_HEALTH_ENABLED: "true" KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_BOOTSTRAP_ADMIN_USERNAME:?set KC_BOOTSTRAP_ADMIN_USERNAME in .env} KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_BOOTSTRAP_ADMIN_PASSWORD:?set KC_BOOTSTRAP_ADMIN_PASSWORD in .env} TOKEN_MEDIATING_CLIENT_SECRET: ${TOKEN_MEDIATING_CLIENT_SECRET:?set TOKEN_MEDIATING_CLIENT_SECRET in .env} BFF_CLIENT_SECRET: ${BFF_CLIENT_SECRET:?set BFF_CLIENT_SECRET in .env} EDGE_PROXY_CLIENT_SECRET: ${EDGE_PROXY_CLIENT_SECRET:?set EDGE_PROXY_CLIENT_SECRET in .env} ADMIN_USER_PASSWORD: ${ADMIN_USER_PASSWORD:?set ADMIN_USER_PASSWORD in .env} REGULAR_USER_PASSWORD: ${REGULAR_USER_PASSWORD:?set REGULAR_USER_PASSWORD in .env} ports: - "127.0.0.1:8080:8080" volumes: - keycloak_data:/opt/keycloak/data - ./keycloak/import:/opt/keycloak/data/import:ro depends_on: postgres: condition: service_healthy healthcheck: test: - CMD - bash - -c - "{ printf 'HEAD /health/ready HTTP/1.0\r\n\r\n' >&0; grep 'HTTP/1.0 200'; } 0<>/dev/tcp/localhost/9000" interval: 10s timeout: 5s retries: 18 start_period: 60s networks: - keycloak-net restart: unless-stopped app: build: context: ./backend environment: SERVER_PORT: "8081" SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: http://localhost:8080/realms/keycloak-patterns SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI: http://keycloak:8080/realms/keycloak-patterns/protocol/openid-connect/certs ports: - "127.0.0.1:8081:8081" depends_on: keycloak: condition: service_healthy healthcheck: test: - CMD-SHELL - wget -q -O - http://127.0.0.1:8081/actuator/health | grep -q '"status":"UP"' interval: 10s timeout: 5s retries: 12 start_period: 20s networks: - keycloak-net restart: unless-stopped oauth2-proxy: image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.2 command: - --http-address=0.0.0.0:4180 - --provider=keycloak-oidc - --oidc-issuer-url=http://localhost:8080/realms/keycloak-patterns - --skip-oidc-discovery=true - --login-url=http://localhost:8080/realms/keycloak-patterns/protocol/openid-connect/auth - --redeem-url=http://keycloak:8080/realms/keycloak-patterns/protocol/openid-connect/token - --oidc-jwks-url=http://keycloak:8080/realms/keycloak-patterns/protocol/openid-connect/certs - --profile-url=http://keycloak:8080/realms/keycloak-patterns/protocol/openid-connect/userinfo - --validate-url=http://keycloak:8080/realms/keycloak-patterns/protocol/openid-connect/userinfo - --redirect-url=http://localhost:8088/oauth2/callback - --upstream=http://app:8081 - --email-domain=* - --scope=openid profile email - --code-challenge-method=S256 - --reverse-proxy=true - --trusted-proxy-ip=172.30.40.10/32 - --cookie-name=AP4_SESSION - --cookie-secure=false - --cookie-samesite=lax - --cookie-expire=1h - --skip-provider-button=true - --set-xauthrequest=true - --pass-user-headers=true - --whitelist-domain=localhost:8088 - --whitelist-domain=localhost:8080 environment: OAUTH2_PROXY_CLIENT_ID: edge-proxy OAUTH2_PROXY_CLIENT_SECRET: ${EDGE_PROXY_CLIENT_SECRET:?set EDGE_PROXY_CLIENT_SECRET in .env} OAUTH2_PROXY_COOKIE_SECRET: ${OAUTH2_PROXY_COOKIE_SECRET:?set OAUTH2_PROXY_COOKIE_SECRET in .env} expose: - "4180" depends_on: keycloak: condition: service_healthy app: condition: service_healthy healthcheck: test: - CMD - /bin/oauth2-proxy - --version interval: 10s timeout: 5s retries: 3 start_period: 5s networks: - keycloak-net restart: unless-stopped nginx: build: context: ./frontend ports: - "127.0.0.1:${NGINX_PORT:-8088}:80" depends_on: oauth2-proxy: condition: service_healthy healthcheck: test: - CMD-SHELL - wget -q -O - http://127.0.0.1/health | grep -q '^ok$' interval: 10s timeout: 5s retries: 12 networks: keycloak-net: ipv4_address: 172.30.40.10 restart: unless-stopped volumes: keycloak_data: postgres_data: networks: keycloak-net: driver: bridge ipam: config: - subnet: 172.30.40.0/24