name: khorde-hub

services:
  hub:
    image: docker.io/khorde/hub:latest
    ports:
      - "8085:8085"
      - "4222:4222"
    volumes:
      - zitadel-machinekey:/machinekey:ro
    configs:
      - source: hub
        target: /opt/scada-service/config.yaml
    extra_hosts:
      # So the Hub container can reach the IdP the same way your browser does.
      - "auth.localhost:host-gateway"
    depends_on:
      zitadel: { condition: service_healthy }
      postgres: { condition: service_healthy }
      questdb: { condition: service_started }
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8085/health"]
      interval: "1s"
      timeout: "30s"
      retries: 30
      start_period: "5s"

  questdb:
    image: "questdb/questdb:9.4.2"
    ports:
      - "8812:8812"

  zitadel:
    restart: "unless-stopped"
    image: "ghcr.io/zitadel/zitadel:v4.15.1"
    command: >-
      start-from-init
      --masterkey "MasterkeyNeedsToHave32Characters"
      --tlsMode disabled
      --config /config/zitadel.yaml
      --steps /config/zitadel.yaml
    ports:
      - "9310:9310"
    depends_on:
      postgres: { condition: service_healthy }
    volumes:
      - zitadel-machinekey:/machinekey/:rw
    configs:
      - source: zitadel
        target: /config/zitadel.yaml
    healthcheck:
      test: ["CMD", "/app/zitadel", "ready", "--config", "/config/zitadel.yaml"]
      interval: "5s"
      timeout: "5s"
      retries: 24
      start_period: "60s"

  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=control_plane
      - PGUSER=postgres
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready", "-d", "control_plane", "-U", "postgres"]
      interval: "5s"
      timeout: "30s"
      retries: 5
      start_period: "20s"

volumes:
  # tmpfs is the only local-driver volume that can be uid 1000 so the IdP can
  # write MachineKeyPath without a host bind
  zitadel-machinekey:
    driver: local
    driver_opts:
      type: tmpfs
      device: tmpfs
      o: uid=1000,gid=1000,mode=0700

configs:
  hub:
    content: |
      bind_address: 0.0.0.0
      port: 8085
      # URL the IdP uses to reach the Hub.
      # Required when the IdP cannot reach bind_address (e.g. running in Docker).
      external_url: http://hub:8085
      # Origin opened in a browser (OIDC redirect URIs). Defaults to bind_address:port.
      public_url: http://localhost:8085
      tsdb:
        ip: questdb
        port: 8812
        username: admin
        password: quest
      db:
        addr: postgres
        port: 5432
        username: postgres
        password: postgres
      zitadel:
        url: http://auth.localhost:9310
        service_account_file: /machinekey/service-account.json

  zitadel:
    content: |
      Port: 9310
      # Lets the Docker network and your browser reach the IdP through the same name.
      ExternalDomain: auth.localhost
      ExternalPort: 9310
      ExternalSecure: false
      TLS:
        Enabled: false

      Database:
        postgres:
          Host: postgres
          Port: 5432
          Database: zitadel
          User:
            Username: zitadel
            Password: zitadel
            SSL:
              Mode: disable
          Admin:
            Username: postgres
            Password: postgres
            SSL:
              Mode: disable

      Eventstore:
        MaxRetries: 10

      HTTPClient:
        DenyList: []

      DefaultInstance:
        Features:
          LoginV2:
            Required: false

      FirstInstance:
        MachineKeyPath: /machinekey/service-account.json
        Org:
          Machine:
            Machine:
              Username: zitadel-admin-sa
              Name: Admin
            MachineKey:
              Type: 1
