volumes:
  pg_data:
  redisinsight_store:
  ckh_data:

networks:
  router_net:

services:
  ### Dependencies
  prestart-hook:
    image: docker.io/curlimages/curl-base:latest
    container_name: prestart-hook
    environment:
      - ONE_CLICK_SETUP=${ONE_CLICK_SETUP:-false}
    entrypoint:
      [
        "/bin/sh",
        "-c",
        "apk add --no-cache bash && /bin/bash /prestart_hook.sh",
      ]
    volumes:
      - ./scripts/prestart_hook.sh:/prestart_hook.sh
    networks:
      - router_net

  pg:
    image: docker.io/postgres:latest
    ports:
      - "5432:5432"
    networks:
      - router_net
    volumes:
      - pg_data:/var/lib/postgresql
    environment:
      - POSTGRES_USER=db_user
      - POSTGRES_PASSWORD=db_pass
      - POSTGRES_DB=hyperswitch_db
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      interval: 5s
      retries: 3
      start_period: 5s
      timeout: 5s

  redis-standalone:
    image: docker.io/redis:7
    networks:
      - router_net
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep '^PONG$'"]
      interval: 5s
      retries: 3
      start_period: 5s
      timeout: 5s

  migration_runner:
    image: docker.io/debian:trixie-slim
    pull_policy: always
    command: >
      bash -c "
      apt-get update && apt-get install -y curl xz-utils &&
      curl --proto '=https' --tlsv1.2 -LsSf https://github.com/diesel-rs/diesel/releases/download/v2.3.5/diesel_cli-installer.sh | bash &&
      if ! command -v just >/dev/null 2>&1; then
        curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
      fi &&
      export PATH="$${PATH}:$${HOME}/.cargo/bin" &&
      just migrate"
    working_dir: /app
    networks:
      - router_net
    volumes:
      - ./:/app
    environment:
      # format -> postgresql://DB_USER:DB_PASSWORD@HOST:PORT/DATABASE_NAME
      - DATABASE_URL=postgresql://db_user:db_pass@pg:5432/hyperswitch_db

  superposition:
    image: ghcr.io/juspay/superposition-demo:0.113.0
    ports:
      - "8081:8080"
    networks:
      - router_net
    environment:
      - API_HOSTNAME=http://localhost:8081
      - REDIS_URL=redis://redis-standalone:6379
    depends_on:
      redis-standalone:
        condition: service_healthy

  superposition-init:
    image: alpine:latest
    depends_on:
      superposition:
        condition: service_started
    networks:
      - router_net
    volumes:
      - ./config/superposition_seed.toml:/seed.toml:ro
      - ./scripts/seed_superposition.sh:/seed_superposition.sh:ro
    environment:
      - SUPERPOSITION_URL=http://superposition:8080
      - SEED_FILE=/seed.toml
      - WORKSPACE_ID=dev
      - ORG_ID=localorg
    command: sh -c "apk add --no-cache curl jq yq && sh /seed_superposition.sh"
    restart: "no"

  mailhog:
    image: docker.io/mailhog/mailhog
    networks:
      - router_net
    profiles:
      - full_setup
    ports:
      - "1025:1025"
      - "8025:8025"

  ### Application services
  hyperswitch-server:
    image: docker.juspay.io/juspaydotin/hyperswitch-router:standalone
    pull_policy: always
    command: /local/bin/router -f /local/config/docker_compose.toml
    ports:
      - "8080:8080"
    networks:
      - router_net
    volumes:
      - ./config:/local/config
      - ./files:/local/bin/files
    depends_on:
      pg:
        condition: service_healthy
      redis-standalone:
        condition: service_healthy
      migration_runner:
        condition: service_completed_successfully
      superposition-init:
        condition: service_completed_successfully
    labels:
      logs: "promtail"
    healthcheck:
      test: curl --fail http://localhost:8080/health || exit 1
      interval: 5s
      retries: 3
      start_period: 5s
      timeout: 5s

  hyperswitch-producer:
    image: docker.juspay.io/juspaydotin/hyperswitch-producer:standalone
    pull_policy: always
    command: /local/bin/scheduler -f /local/config/docker_compose.toml
    networks:
      - router_net
    profiles:
      - scheduler
    volumes:
      - ./config:/local/config
    environment:
      - SCHEDULER_FLOW=producer
    depends_on:
      hyperswitch-consumer:
        condition: service_healthy
    labels:
      logs: "promtail"

  hyperswitch-consumer:
    image: docker.juspay.io/juspaydotin/hyperswitch-consumer:standalone
    pull_policy: always
    command: /local/bin/scheduler -f /local/config/docker_compose.toml
    networks:
      - router_net
    profiles:
      - scheduler
    volumes:
      - ./config:/local/config
    environment:
      - SCHEDULER_FLOW=consumer
    depends_on:
      hyperswitch-server:
        condition: service_healthy
    labels:
      logs: "promtail"
    healthcheck:
      test: (ps -e | grep scheduler) || exit 1
      interval: 10s
      retries: 3
      start_period: 5s
      timeout: 10s

  hyperswitch-drainer:
    image: docker.juspay.io/juspaydotin/hyperswitch-drainer:standalone
    pull_policy: always
    command: /local/bin/drainer -f /local/config/docker_compose.toml
    deploy:
      replicas: ${DRAINER_INSTANCE_COUNT:-1}
    networks:
      - router_net
    profiles:
      - full_kv
    volumes:
      - ./config:/local/config
    restart: unless-stopped
    depends_on:
      hyperswitch-server:
        condition: service_healthy
    labels:
      logs: "promtail"

  ### Web Client
  hyperswitch-web:
    image: docker.juspay.io/juspaydotin/hyperswitch-web:latest
    pull_policy: always
    ports:
      - "9050:9050"
    networks:
      - router_net
    depends_on:
      hyperswitch-server:
        condition: service_healthy
    environment:
      - ENABLE_LOGGING=true
      - SDK_ENV=local
      - ENV_LOGGING_URL=http://localhost:3103
      - ENV_BACKEND_URL=http://localhost:8080
    labels:
      logs: "promtail"

  ### Control Center
  hyperswitch-control-center:
    image: docker.juspay.io/juspaydotin/hyperswitch-control-center:latest
    pull_policy: always
    ports:
      - "9000:9000"
    environment:
      - configPath=/tmp/dashboard-config.toml
      - themeConfigPath=/tmp/dashboard-theme.json
    volumes:
      - ./config/dashboard.toml:/tmp/dashboard-config.toml
      - ./config/dashboard_theme.json:/tmp/dashboard-theme.json
    depends_on:
      hyperswitch-server:
        condition: service_healthy
      hyperswitch-web:
        condition: service_started
    labels:
      logs: "promtail"

  create-default-user:
    image: docker.io/curlimages/curl-base:latest
    container_name: create-default-user
    depends_on:
      hyperswitch-server:
        condition: service_healthy
      hyperswitch-control-center:
        condition: service_started
    environment:
      - HYPERSWITCH_SERVER_URL=http://hyperswitch-server:8080
      - HYPERSWITCH_CONTROL_CENTER_URL=http://hyperswitch-control-center:9000
    entrypoint:
      [
        "/bin/sh",
        "-c",
        "apk add --no-cache bash jq && /bin/bash /create_default_user.sh",
      ]
    volumes:
      - ./scripts/create_default_user.sh:/create_default_user.sh
    networks:
      - router_net

  poststart-hook:
    image: docker.io/curlimages/curl-base:latest
    container_name: poststart-hook
    depends_on:
      hyperswitch-server:
        condition: service_healthy # Ensures it only starts when `hyperswitch-server` is healthy
    environment:
      - ONE_CLICK_SETUP=${ONE_CLICK_SETUP:-false}
    entrypoint:
      [
        "/bin/sh",
        "-c",
        "apk add --no-cache bash jq && /bin/bash /poststart_hook.sh",
      ]
    volumes:
      - ./scripts/poststart_hook.sh:/poststart_hook.sh
    networks:
      - router_net

  ### Clustered Redis setup
  redis-cluster:
    image: docker.io/redis:7
    deploy:
      replicas: ${REDIS_CLUSTER_COUNT:-3}
    command: redis-server /usr/local/etc/redis/redis.conf
    profiles:
      - clustered_redis
    volumes:
      - ./config/redis.conf:/usr/local/etc/redis/redis.conf
    networks:
      - router_net
    ports:
      - "6379"
      - "16379"

  redis-init:
    image: docker.io/redis:7
    profiles:
      - clustered_redis
    depends_on:
      - redis-cluster
    networks:
      - router_net
    command: |-
      bash -c 'export COUNT=${REDIS_CLUSTER_COUNT:-3}
      if [ $$COUNT -lt 3 ]
      then
      echo \"Minimum 3 nodes are needed for redis cluster\"
      exit 1
      fi
      HOSTS=\"\"
      for ((c=1; c<=$$COUNT;c++))
      do
      NODE=$COMPOSE_PROJECT_NAME-redis-cluster-$$c:6379
      echo $$NODE
      HOSTS=\"$$HOSTS $$NODE\"
      done
      echo Creating a cluster with $$HOSTS
      redis-cli --cluster create $$HOSTS --cluster-yes
      '
  ### Monitoring
  grafana:
    image: docker.io/grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - router_net
    profiles:
      - monitoring
    restart: unless-stopped
    environment:
      - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
      - GF_AUTH_ANONYMOUS_ENABLED=true
      - GF_AUTH_BASIC_ENABLED=false
    volumes:
      - ./config/grafana.ini:/etc/grafana/grafana.ini
      - ./config/grafana-datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yml

  loki:
    image: docker.io/grafana/loki:latest
    ports:
      - "3100"
    command: -config.file=/etc/loki/loki.yaml
    networks:
      - router_net
    profiles:
      - monitoring
    volumes:
      - ./config:/etc/loki

  otel-collector:
    image: docker.io/otel/opentelemetry-collector-contrib:latest
    command: --config=/etc/otel-collector.yaml
    networks:
      - router_net
    profiles:
      - monitoring
    volumes:
      - ./config/otel-collector.yaml:/etc/otel-collector.yaml
    ports:
      - "4317"
      - "8888"
      - "8889"

  prometheus:
    image: docker.io/prom/prometheus:latest
    networks:
      - router_net
    profiles:
      - monitoring
    volumes:
      - ./config/prometheus.yaml:/etc/prometheus/prometheus.yml
    ports:
      - "9090"
    restart: unless-stopped

  tempo:
    image: docker.io/grafana/tempo:latest
    command: -config.file=/etc/tempo.yaml
    volumes:
      - ./config/tempo.yaml:/etc/tempo.yaml
    networks:
      - router_net
    profiles:
      - monitoring
    ports:
      - "3200" # tempo
      - "4317" # otlp grpc
    restart: unless-stopped

  redis-insight:
    image: docker.io/redislabs/redisinsight:latest
    networks:
      - router_net
    profiles:
      - monitoring
    ports:
      - "8001:8001"
    volumes:
      - redisinsight_store:/db

  kafka0:
    image: docker.io/confluentinc/cp-kafka:7.0.5
    hostname: kafka0
    networks:
      - router_net
    ports:
      - 9092:9092
      - 9093
      - 9997
      - 29092
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka0:29092,PLAINTEXT_HOST://localhost:9092
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_PROCESS_ROLES: "broker,controller"
      KAFKA_NODE_ID: 1
      KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka0:29093"
      KAFKA_LISTENERS: "PLAINTEXT://kafka0:29092,CONTROLLER://kafka0:29093,PLAINTEXT_HOST://0.0.0.0:9092"
      KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
      KAFKA_LOG_DIRS: "/tmp/kraft-combined-logs"
      JMX_PORT: 9997
      KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka0 -Dcom.sun.management.jmxremote.rmi.port=9997
    profiles:
      - olap
    volumes:
      - ./monitoring/kafka-script.sh:/tmp/update_run.sh
    command: 'bash -c ''if [ ! -f /tmp/update_run.sh ]; then echo "ERROR: Did you forget the update_run.sh file that came with this docker-compose.yml file?" && exit 1 ; else /tmp/update_run.sh && /etc/confluent/docker/run ; fi'''

  # Kafka UI for debugging kafka queues
  kafka-ui:
    image: docker.io/provectuslabs/kafka-ui:latest
    ports:
      - 8090:8080
    networks:
      - router_net
    depends_on:
      - kafka0
    profiles:
      - olap
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka0:29092
      KAFKA_CLUSTERS_0_JMXPORT: 9997

  clickhouse-server:
    image: docker.io/clickhouse/clickhouse-server:24.3
    networks:
      - router_net
    ports:
      - "9000"
      - "8123:8123"
    volumes:
      - ./crates/analytics/docs/clickhouse/scripts:/docker-entrypoint-initdb.d
    environment:
      - TZ=Asia/Kolkata
    profiles:
      - olap
    ulimits:
      nofile:
        soft: 262144
        hard: 262144

  opensearch:
    image: docker.io/opensearchproject/opensearch:2
    container_name: opensearch
    hostname: opensearch
    environment:
      - "discovery.type=single-node"
      - OPENSEARCH_INITIAL_ADMIN_PASSWORD=0penS3arc#
      - LOG_LEVEL=DEBUG
    profiles:
      - olap
    ports:
      - "9200:9200"
    networks:
      - router_net

  opensearch-dashboards:
    image: docker.io/opensearchproject/opensearch-dashboards:2
    ports:
      - 5601:5601
    profiles:
      - olap
    environment:
      OPENSEARCH_HOSTS: '["https://opensearch:9200"]'
    networks:
      - router_net

  vector:
    image: docker.io/timberio/vector:latest-debian
    ports:
      - "8686"
      - "9598"
      - "3103:3103"
    profiles:
      - olap
    environment:
      KAFKA_HOST: "kafka0:29092"
    networks:
      - router_net
    volumes:
      - ./config/vector.yaml:/etc/vector/vector.yaml
      - /var/run/docker.sock:/var/run/docker.sock

  hyperswitch-demo:
    image: docker.juspay.io/juspaydotin/hyperswitch-react-demo-app:latest
    pull_policy: always
    ports:
      - "9060:9060"
      - "5252:5252"
    networks:
      - router_net
    profiles:
      - full_setup
    depends_on:
      hyperswitch-server:
        condition: service_healthy
      hyperswitch-web:
        condition: service_started
    environment:
      - HYPERSWITCH_PUBLISHABLE_KEY=placeholder_publishable_key
      - HYPERSWITCH_SECRET_KEY=placeholder_api_key
      - PROFILE_ID=placeholder_profile_id
      - HYPERSWITCH_CLIENT_URL=http://localhost:9050
      - HYPERSWITCH_SERVER_URL=http://localhost:8080
    labels:
      logs: "promtail"
