# Managed by Ansible — do not edit manually services: sso-db: image: postgres:{{ keycloak_db_version }} container_name: sso-db restart: unless-stopped environment: POSTGRES_USER: keycloak POSTGRES_PASSWORD: "{{ keycloak_db_password }}" POSTGRES_DB: keycloak volumes: - {{ sso_data_dir }}/db:/var/lib/postgresql/data networks: - sso_internal healthcheck: test: ["CMD-SHELL", "pg_isready -U keycloak"] interval: 10s timeout: 5s retries: 5 sso-keycloak: image: quay.io/keycloak/keycloak:{{ keycloak_version }} container_name: sso-keycloak command: start restart: unless-stopped environment: # Database KC_DB: postgres KC_DB_URL: jdbc:postgresql://sso-db:5432/keycloak KC_DB_USERNAME: keycloak KC_DB_PASSWORD: "{{ keycloak_db_password }}" # Hostname — Traefik handles TLS, Keycloak listens plain HTTP internally KC_HOSTNAME: "{{ domain_sso }}" KC_HTTP_ENABLED: "true" KC_PROXY_HEADERS: xforwarded # Health endpoint (used by Docker healthcheck) KC_HEALTH_ENABLED: "true" # Bootstrap admin — only used on first start; change password via UI afterwards KEYCLOAK_ADMIN: "{{ keycloak_admin_user }}" KEYCLOAK_ADMIN_PASSWORD: "{{ keycloak_admin_password }}" networks: - traefik_public - sso_internal labels: - "traefik.enable=true" - "traefik.http.routers.sso.rule=Host(`{{ domain_sso }}`)" - "traefik.http.routers.sso.entrypoints=websecure" - "traefik.http.routers.sso.tls.certresolver=letsencrypt" - "traefik.http.services.sso.loadbalancer.server.port=8080" - "traefik.http.routers.sso.middlewares=rate-limit@docker" healthcheck: test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/localhost/9000"] interval: 30s timeout: 10s retries: 5 start_period: 90s depends_on: sso-db: condition: service_healthy networks: traefik_public: external: true sso_internal: internal: true