---
networks:
  default:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 247.16.14.0/24
        - subnet: fd1c:8ce3:6fb:1::/64
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-akvorado

volumes:
  akvorado-kafka:
  akvorado-geoip:
  akvorado-clickhouse:
  akvorado-run:
  akvorado-console-db:

services:
  kafka:
    extends:
      file: versions.yml
      service: kafka
    environment:
      # KRaft settings
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: controller,broker
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
      # Listeners
      KAFKA_LISTENERS: CLIENT://:9092,CONTROLLER://:9093
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CLIENT:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_ADVERTISED_LISTENERS: CLIENT://kafka:9092
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: CLIENT
      # Misc
      KAFKA_DELETE_TOPIC_ENABLE: "true"
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_SHARE_COORDINATOR_STATE_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_SHARE_COORDINATOR_STATE_TOPIC_MIN_ISR: 1
      KAFKA_LOG_DIRS: /var/lib/kafka/data
    restart: unless-stopped
    volumes:
      - akvorado-kafka:/var/lib/kafka/data
    healthcheck:
      interval: 20s
      test: ["CMD",
             "/opt/kafka/bin/kafka-topics.sh", "--list", "--bootstrap-server", "kafka:9092"]

  kafka-ui:
    extends:
      file: versions.yml
      service: kafka-ui
    restart: unless-stopped
    depends_on:
      - kafka
    environment:
      KAFKA_CLUSTERS_0_NAME: local
      KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
      KAFKA_CLUSTERS_0_READONLY: true
      SERVER_SERVLET_CONTEXT_PATH: /kafka-ui
    labels:
      - traefik.enable=true
      - traefik.http.routers.kafka-ui.rule=PathPrefix(`/kafka-ui`)

  redis:
    extends:
      file: versions.yml
      service: redis
    restart: unless-stopped
    healthcheck:
      interval: 20s
      test:
        - CMD-SHELL
        - "timeout 3 redis-cli ping | grep -q PONG"

  akvorado-orchestrator:
    extends:
      file: versions.yml
      service: akvorado
    restart: unless-stopped
    depends_on:
      kafka:
        condition: service_healthy
    command: orchestrator /etc/akvorado/akvorado.yaml
    volumes:
      - ../config:/etc/akvorado:ro
      - akvorado-geoip:/usr/share/GeoIP:ro
    labels:
      - traefik.enable=true
      # Disable access logging of /api/v0/orchestrator/metrics
      - traefik.http.routers.akvorado-orchestrator-metrics.rule=PathPrefix(`/api/v0/orchestrator/metrics`)
      - traefik.http.routers.akvorado-orchestrator-metrics.service=akvorado-orchestrator
      - traefik.http.routers.akvorado-orchestrator-metrics.observability.accesslogs=false
      # Everything else is exposed to private entrypoint in /api/v0/orchestrator
      - traefik.http.routers.akvorado-orchestrator.entrypoints=private
      - traefik.http.routers.akvorado-orchestrator.rule=PathPrefix(`/api/v0/orchestrator`)
      - traefik.http.services.akvorado-orchestrator.loadbalancer.server.port=8080
      - metrics.port=8080
      - metrics.path=/api/v0/metrics
  akvorado-console:
    extends:
      file: versions.yml
      service: akvorado
    restart: unless-stopped
    depends_on:
      akvorado-orchestrator:
        condition: service_healthy
      redis:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
    command: console http://akvorado-orchestrator:8080
    volumes:
      - akvorado-console-db:/run/akvorado
    environment:
      AKVORADO_CFG_CONSOLE_DATABASE_DSN: /run/akvorado/console.sqlite
      AKVORADO_CFG_CONSOLE_BRANDING: ${AKVORADO_CFG_CONSOLE_BRANDING-false}
    healthcheck:
      disable: ${CONSOLE_HEALTHCHECK_DISABLED-false}
    labels:
      - traefik.enable=true
      # Only expose /debug endpoint on the private entrypoint.
      - traefik.http.routers.akvorado-console-debug.rule=PathPrefix(`/debug`)
      - traefik.http.routers.akvorado-console-debug.entrypoints=private
      - traefik.http.routers.akvorado-console-debug.service=akvorado-console
      # Disable access logging of /api/v0/console/metrics
      - traefik.http.routers.akvorado-console-metrics.rule=PathPrefix(`/api/v0/console/metrics`)
      - traefik.http.routers.akvorado-console-metrics.service=akvorado-console
      - traefik.http.routers.akvorado-console-metrics.observability.accesslogs=false
      # For anything else...
      - "traefik.http.routers.akvorado-console.rule=!PathPrefix(`/debug`)"
      - traefik.http.routers.akvorado-console.priority=1
      - traefik.http.routers.akvorado-console.middlewares=console-auth
      - traefik.http.services.akvorado-console.loadbalancer.server.port=8080
      - traefik.http.middlewares.console-auth.headers.customrequestheaders.Remote-User=alfred
      - traefik.http.middlewares.console-auth.headers.customrequestheaders.Remote-Name=Alfred Pennyworth
      - traefik.http.middlewares.console-auth.headers.customrequestheaders.Remote-Email=alfred@example.com
      - metrics.port=8080
      - metrics.path=/api/v0/metrics
  akvorado-inlet:
    extends:
      file: versions.yml
      service: akvorado
    ports:
      - 2055:2055/udp
      - 4739:4739/udp
      - 6343:6343/udp
    restart: unless-stopped
    depends_on:
      akvorado-orchestrator:
        condition: service_healthy
      kafka:
        condition: service_healthy
    command: inlet http://akvorado-orchestrator:8080
    volumes:
      - akvorado-run:/run/akvorado
    labels:
      - traefik.enable=true
      # Disable access logging of /api/v0/inlet/metrics
      - traefik.http.routers.akvorado-inlet-metrics.rule=PathPrefix(`/api/v0/inlet/metrics`)
      - traefik.http.routers.akvorado-inlet-metrics.service=akvorado-inlet
      - traefik.http.routers.akvorado-inlet-metrics.observability.accesslogs=false
      # Everything else is exposed to private entrypoint in /api/v0/inlet
      - traefik.http.routers.akvorado-inlet.entrypoints=private
      - traefik.http.routers.akvorado-inlet.rule=PathPrefix(`/api/v0/inlet`)
      - traefik.http.services.akvorado-inlet.loadbalancer.server.port=8080
      - metrics.port=8080
      - metrics.path=/api/v0/metrics
  akvorado-outlet:
    extends:
      file: versions.yml
      service: akvorado
    ports:
      - 10179:10179/tcp
    restart: unless-stopped
    stop_grace_period: 30s
    depends_on:
      akvorado-orchestrator:
        condition: service_healthy
      kafka:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
    command: outlet http://akvorado-orchestrator:8080
    volumes:
      - akvorado-run:/run/akvorado
    environment:
      AKVORADO_CFG_OUTLET_METADATA_CACHEPERSISTFILE: /run/akvorado/metadata.cache
      AKVORADO_CFG_OUTLET_FLOW_STATEPERSISTFILE: /run/akvorado/flow.state
    labels:
      - traefik.enable=true
      # Disable access logging of /api/v0/outlet/metrics
      - traefik.http.routers.akvorado-outlet-metrics.rule=PathPrefix(`/api/v0/outlet/metrics`)
      - traefik.http.routers.akvorado-outlet-metrics.service=akvorado-outlet
      - traefik.http.routers.akvorado-outlet-metrics.observability.accesslogs=false
      # Everything else is exposed to private entrypoint in /api/v0/outlet
      - traefik.http.routers.akvorado-outlet.entrypoints=private
      - traefik.http.routers.akvorado-outlet.rule=PathPrefix(`/api/v0/outlet`)
      - traefik.http.services.akvorado-outlet.loadbalancer.server.port=8080
      - metrics.port=8080
      - metrics.path=/api/v0/metrics

  clickhouse:
    extends:
      file: versions.yml
      service: clickhouse
    volumes:
      - akvorado-clickhouse:/var/lib/clickhouse
      - ./clickhouse/observability.xml:/etc/clickhouse-server/config.d/observability.xml
      - ./clickhouse/server.xml:/etc/clickhouse-server/config.d/akvorado.xml
    environment:
      CLICKHOUSE_INIT_TIMEOUT: 60
      CLICKHOUSE_SKIP_USER_SETUP: 1
    cap_add:
      - SYS_NICE
    restart: unless-stopped
    stop_grace_period: 30s
    healthcheck:
      interval: 20s
      test: ["CMD", "wget", "-T", "1", "--spider", "--no-proxy", "http://127.0.0.1:8123/ping"]
    labels:
      - traefik.enable=true
      - traefik.http.routers.clickhouse.entrypoints=private
      - traefik.http.routers.clickhouse.rule=PathPrefix(`/clickhouse`)
      - traefik.http.routers.clickhouse.middlewares=clickhouse-strip
      - traefik.http.middlewares.clickhouse-strip.stripprefix.prefixes=/clickhouse
      - metrics.port=8123

  traefik:
    extends:
      file: versions.yml
      service: traefik
    restart: unless-stopped
    environment:
      TRAEFIK_API: "true"
      TRAEFIK_API_BASEPATH: "/traefik"
      TRAEFIK_METRICS_PROMETHEUS: "true"
      TRAEFIK_METRICS_PROMETHEUS_MANUALROUTING: "true"
      TRAEFIK_METRICS_PROMETHEUS_ADDROUTERSLABELS: "true"
      TRAEFIK_PROVIDERS_DOCKER: "true"
      TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "false"
      TRAEFIK_ENTRYPOINTS_private_ADDRESS: ":8080" # all services
      TRAEFIK_ENTRYPOINTS_private_HTTP_MIDDLEWARES: compress@docker
      TRAEFIK_ENTRYPOINTS_public_ADDRESS: ":8081"  # public services only
      TRAEFIK_ENTRYPOINTS_public_HTTP_MIDDLEWARES: compress@docker
      TRAEFIK_ACCESSLOG: "true"
    labels:
      - traefik.enable=true
      - "traefik.http.routers.traefik.rule=PathPrefix(`/traefik`) && !PathPrefix(`/traefik/debug`)"
      - traefik.http.routers.traefik.service=api@internal
      - traefik.http.routers.traefik-metrics.rule=PathPrefix(`/traefik/metrics`)
      - traefik.http.routers.traefik-metrics.priority=200
      - traefik.http.routers.traefik-metrics.service=prometheus@internal
      - traefik.http.middlewares.compress.compress=true
      - "traefik.http.middlewares.compress.compress.includedcontenttypes=\
        application/javascript,\
        application/json,\
        application/xml,\
        image/svg+xml,\
        text/css,\
        text/csv,\
        text/javascript,\
        text/markdown,\
        text/plain,\
        text/xml"
      - metrics.port=8080
      - metrics.path=/traefik/metrics
    expose:
      - 8080/tcp
    ports:
      # Port 8080 is considered private as it exposes sensible unauthenticated
      # services (ClickHouse, configuration, ...). Therefore, it is only exposed
      # on the loopback. Port 8081 is the one you can expose to users. Check
      # docker-compose-local.yml if you want to expose directly on port 80.
      - 127.0.0.1:8080:8080/tcp
      - 8081:8081/tcp
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
