# FreeIPA + Keycloak + PostgreSQL constellation # # Setup: # cp .env.example .env && $EDITOR .env # docker compose up -d # docker compose logs -f freeipa # watch first-boot install (~10 min) # # Once freeipa is healthy: # ./keycloak-configure.sh # wire Keycloak → FreeIPA LDAP # # To run without Keycloak: # docker compose up -d freeipa # # To scale out (clients enroll against the same IPA server): # docker compose --profile clients up volumes: freeipa-data: keycloak-db: networks: ipa-net: ipam: config: - subnet: 172.30.0.0/24 services: # ── FreeIPA ───────────────────────────────────────────────────────────────── freeipa: build: context: . dockerfile: Dockerfile image: freeipa-server:local container_name: freeipa hostname: ${IPA_HOSTNAME:-ipa.example.com} privileged: true tmpfs: - /run - /tmp volumes: - freeipa-data:/data - /sys/fs/cgroup:/sys/fs/cgroup:rw environment: IPA_DOMAIN: ${IPA_DOMAIN:?set IPA_DOMAIN in .env} IPA_REALM: ${IPA_REALM:-} IPA_ADMIN_PASSWORD: ${IPA_ADMIN_PASSWORD:?set IPA_ADMIN_PASSWORD in .env} IPA_DM_PASSWORD: ${IPA_DM_PASSWORD:?set IPA_DM_PASSWORD in .env} IPA_SETUP_DNS: ${IPA_SETUP_DNS:-false} IPA_DNS_FORWARDER: ${IPA_DNS_FORWARDER:-} IPA_SETUP_KRA: ${IPA_SETUP_KRA:-false} ports: - "389:389" - "636:636" - "88:88" - "88:88/udp" - "464:464" - "464:464/udp" - "443:443" networks: ipa-net: ipv4_address: 172.30.0.10 healthcheck: test: ["CMD-SHELL", "ipactl status 2>/dev/null | grep -q 'running'"] interval: 30s timeout: 15s retries: 20 start_period: 600s # ── PostgreSQL (Keycloak backend) ──────────────────────────────────────────── postgres: image: postgres:16-alpine container_name: keycloak-db restart: unless-stopped environment: POSTGRES_DB: keycloak POSTGRES_USER: keycloak POSTGRES_PASSWORD: ${KC_DB_PASSWORD:?set KC_DB_PASSWORD in .env} volumes: - keycloak-db:/var/lib/postgresql/data networks: ipa-net: healthcheck: test: ["CMD", "pg_isready", "-U", "keycloak"] interval: 10s retries: 5 # ── Keycloak ───────────────────────────────────────────────────────────────── # After first start, run ./keycloak-configure.sh to wire FreeIPA LDAP federation. keycloak: image: quay.io/keycloak/keycloak:latest container_name: keycloak restart: unless-stopped # Use 'start' (not start-dev) for production; requires a TLS certificate. command: start-dev environment: KC_DB: postgres KC_DB_URL: jdbc:postgresql://postgres/keycloak KC_DB_USERNAME: keycloak KC_DB_PASSWORD: ${KC_DB_PASSWORD:?set KC_DB_PASSWORD in .env} KC_HOSTNAME: ${KC_HOSTNAME:-localhost} KC_HTTP_PORT: 8080 KC_HTTPS_PORT: 8443 KC_HTTP_ENABLED: "true" KC_FEATURES: preview KEYCLOAK_ADMIN: ${KC_ADMIN:-admin} KEYCLOAK_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:?set KC_ADMIN_PASSWORD in .env} extra_hosts: - "${IPA_HOSTNAME:-ipa.example.com}:172.30.0.10" ports: - "8080:8080" - "8443:8443" depends_on: postgres: condition: service_healthy networks: ipa-net: healthcheck: test: ["CMD-SHELL", "curl -fs http://localhost:8080/health/ready || exit 1"] interval: 20s timeout: 10s retries: 20 start_period: 90s