# 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}
      SMB_SCAN_PASSWORD:   ${SMB_SCAN_PASSWORD:?set SMB_SCAN_PASSWORD in .env}
    ports:
      - "389:389"
      - "636:636"
      - "88:88"
      - "88:88/udp"
      - "464:464"
      - "464:464/udp"
      - "443:443"
      - "445:445"
      - "139:139"
      - "137:137/udp"
      - "138:138/udp"
    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
