services: postgres_ory: image: postgres:${ORY_POSTGRES_TAG:-17-alpine} container_name: ory_postgres environment: - POSTGRES_USER=${ORY_POSTGRES_USER:-ory} - POSTGRES_PASSWORD=${ORY_POSTGRES_PASSWORD:-secret} - POSTGRES_DB=${ORY_POSTGRES_DB:-ory} volumes: - ./docker/ory/init-db:/docker-entrypoint-initdb.d - ory_postgres_data:/var/lib/postgresql/data networks: - ory-net healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${ORY_POSTGRES_USER:-ory} -d ${KRATOS_DB:-ory_kratos}", ] interval: 5s timeout: 5s retries: 5 kratos-migrate: image: oryd/kratos:${KRATOS_VERSION:-v26.2.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20 - KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL} - KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL} - KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL} - KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${USERFRONT_URL}"]} volumes: - ../config/.generated/ory/kratos:/etc/config/kratos command: migrate sql up -e -c /etc/config/kratos/kratos.yml --yes depends_on: postgres_ory: condition: service_healthy networks: - ory-net kratos: image: oryd/kratos:${KRATOS_VERSION:-v26.2.0} container_name: ory_kratos environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KRATOS_DB:-ory_kratos}?sslmode=disable&max_conns=20 - COOKIE_SECRET=${COOKIE_SECRET:-localcookie123} - KRATOS_SERVE_PUBLIC_BASE_URL=${KRATOS_BROWSER_URL} - KRATOS_SERVE_ADMIN_BASE_URL=${KRATOS_ADMIN_URL} - KRATOS_SELFSERVICE_DEFAULT_BROWSER_RETURN_URL=${KRATOS_UI_URL} - KRATOS_SELFSERVICE_ALLOWED_RETURN_URLS=${KRATOS_ALLOWED_RETURN_URLS_JSON:-["${KRATOS_UI_URL}","${USERFRONT_URL}"]} volumes: - ../config/.generated/ory/kratos:/etc/config/kratos command: serve -c /etc/config/kratos/kratos.yml depends_on: kratos-migrate: condition: service_completed_successfully networks: - ory-net - kratosnet hydra-migrate: image: oryd/hydra:${HYDRA_VERSION:-v26.2.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20 command: migrate sql up -e --yes depends_on: postgres_ory: condition: service_healthy networks: - ory-net hydra: image: oryd/hydra:${HYDRA_VERSION:-v26.2.0} container_name: ory_hydra environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${HYDRA_DB:-ory_hydra}?sslmode=disable&max_conns=20 - URLS_SELF_ISSUER=${HYDRA_PUBLIC_URL} - URLS_LOGIN=${HYDRA_LOGIN_URL:-${USERFRONT_URL}/login} - URLS_CONSENT=${HYDRA_CONSENT_URL:-${USERFRONT_URL}/consent} - URLS_ERROR=${HYDRA_ERROR_URL:-${USERFRONT_URL}/error} - SECRETS_SYSTEM=${ORY_POSTGRES_PASSWORD} volumes: - ../config/.generated/ory/hydra:/etc/config/hydra command: serve -c /etc/config/hydra/hydra.yml all --dev depends_on: hydra-migrate: condition: service_completed_successfully networks: - ory-net - hydranet keto-migrate: image: oryd/keto:${KETO_VERSION:-v26.2.0} environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20 volumes: - ../config/.generated/ory/keto:/etc/config/keto command: ["migrate", "up", "-c", "/etc/config/keto/keto.yml", "--yes"] depends_on: postgres_ory: condition: service_healthy networks: - ory-net keto: image: oryd/keto:${KETO_VERSION:-v26.2.0} container_name: ory_keto environment: - DSN=postgres://${ORY_POSTGRES_USER}:${ORY_POSTGRES_PASSWORD}@postgres_ory:5432/${KETO_DB:-ory_keto}?sslmode=disable&max_conns=20 volumes: - ../config/.generated/ory/keto:/etc/config/keto command: serve -c /etc/config/keto/keto.yml depends_on: keto-migrate: condition: service_completed_successfully networks: - ory-net oathkeeper: image: oryd/oathkeeper:${OATHKEEPER_VERSION:-v26.2.0} container_name: oathkeeper restart: unless-stopped depends_on: kratos: condition: service_started environment: - APP_ENV=${APP_ENV:-development} - LOG_LEVEL=debug - OATHKEEPER_INTROSPECT_CLIENT_ID=${OATHKEEPER_INTROSPECT_CLIENT_ID:-oathkeeper-introspect} - OATHKEEPER_INTROSPECT_CLIENT_SECRET=${OATHKEEPER_INTROSPECT_CLIENT_SECRET:-oathkeeper-secret} volumes: - ../config/.generated/ory/oathkeeper:/etc/config/oathkeeper - oathkeeper_logs:/var/log/oathkeeper entrypoint: ["/etc/config/oathkeeper/entrypoint.sh"] networks: - ory-net - baron_net - public_net ports: - "4455:4455" - "4456:4456" healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4456/health/ready"] interval: 5s timeout: 5s retries: 5 ory_stack_check: image: alpine:latest container_name: ory_stack_check command: > /bin/sh -c " apk add --no-cache curl; echo 'Wait for services...'; check_ready() { name=\"$$1\"; url=\"$$2\"; max=\"$${ORY_STACK_CHECK_MAX_ATTEMPTS:-60}\"; i=1; while [ \"$$i\" -le \"$$max\" ]; do if curl --connect-timeout 2 --max-time 3 -fsS \"$$url\" >/dev/null; then echo \"Ory service ready: $$name\"; return 0; fi; echo \"Waiting for Ory service: $$name ($$i/$$max)\"; i=$$((i + 1)); sleep 1; done; echo \"ERROR: Ory service not ready: $$name after $$max attempts ($$url)\" >&2; echo \"ERROR: Check service logs: docker logs ory_$$name\" >&2; return 1; }; check_ready kratos http://kratos:4433/health/ready || exit 1; check_ready hydra http://hydra:4444/health/ready || exit 1; check_ready keto http://keto:4466/health/ready || exit 1; echo 'Ory Stack is fully operational!';" depends_on: - kratos - hydra - keto networks: - ory-net init-rp: image: alpine:latest container_name: init-rp env_file: - ../.env command: - /bin/sh - -ec - | apk add --no-cache curl tar HYDRA_CLI_VERSION="$${HYDRA_VERSION:-v26.2.0}" HYDRA_CLI_VERSION="$${HYDRA_CLI_VERSION%-distroless}" HYDRA_CLI_ARCHIVE_VERSION="$${HYDRA_CLI_VERSION#v}" curl -fsSLo /tmp/hydra.tar.gz "https://github.com/ory/hydra/releases/download/$${HYDRA_CLI_VERSION}/hydra_$${HYDRA_CLI_ARCHIVE_VERSION}-linux_64bit.tar.gz" tar -xzf /tmp/hydra.tar.gz -C /usr/local/bin hydra rm /tmp/hydra.tar.gz echo "Creating/Updating OAuth2 Clients..." hydra create oauth2-client \ --endpoint "$${HYDRA_ADMIN_URL}" \ --id adminfront \ --name "AdminFront" \ --grant-type authorization_code,refresh_token \ --response-type code \ --scope openid,offline_access,profile,email \ --token-endpoint-auth-method none \ --redirect-uri "$${ADMINFRONT_CALLBACK_URLS}" hydra create oauth2-client \ --endpoint "$${HYDRA_ADMIN_URL}" \ --id devfront \ --name "DevFront" \ --grant-type authorization_code,refresh_token \ --response-type code \ --scope openid,offline_access,profile,email \ --token-endpoint-auth-method none \ --redirect-uri "$${DEVFRONT_CALLBACK_URLS}" hydra create oauth2-client \ --endpoint "$${HYDRA_ADMIN_URL}" \ --id orgfront \ --name "OrgFront" \ --grant-type authorization_code,refresh_token \ --response-type code \ --scope openid,offline_access,profile,email \ --token-endpoint-auth-method none \ --redirect-uri "$${ORGFRONT_CALLBACK_URLS}" echo "All RP clients initialized successfully." depends_on: ory_stack_check: condition: service_completed_successfully networks: - ory-net - hydranet volumes: ory_postgres_data: oathkeeper_logs: networks: ory-net: external: true name: ory-net hydranet: external: true name: hydranet kratosnet: external: true name: kratosnet public_net: external: true name: public_net baron_net: external: true name: baron_net