services:
  alert-receiver:
    image: python:3.14.6-alpine3.23@sha256:b165067c5afc37fa5608a3c05609cc3d51aafd808a30fbfd822ee594fef55ad4
    command: ["python", "/opt/who-need-help/alert-receiver.py"]
    volumes:
      - ./scripts/alert-receiver.py:/opt/who-need-help/alert-receiver.py:ro
    healthcheck:
      test:
        [
          "CMD",
          "python",
          "-c",
          "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=2).read()",
        ]
      interval: 2s
      timeout: 3s
      retries: 20
    user: "65532:65532"
    read_only: true
    tmpfs:
      - /tmp
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    networks: [internal]
    restart: unless-stopped
    profiles: [observability]

  alertmanager:
    image: quay.io/prometheus/alertmanager:v0.33.1@sha256:9e082985f56f4c8c9f724e18f2288c6708f472e56a5286b8863d080434ea065d
    command:
      - --config.file=/etc/alertmanager/alertmanager.yml
      - --storage.path=/alertmanager
    volumes:
      - ./ops/observability/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
      - alertmanager_data:/alertmanager
    ports:
      - target: 9093
        published: "${OBSERVABILITY_ALERTMANAGER_PORT:-0}"
        host_ip: 127.0.0.1
        protocol: tcp
    healthcheck:
      test: ["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:9093/-/ready"]
      interval: 2s
      timeout: 3s
      retries: 20
    depends_on:
      alert-receiver:
        condition: service_healthy
    read_only: true
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    networks: [internal, observability_host]
    restart: unless-stopped
    profiles: [observability]

  prometheus:
    image: quay.io/prometheus/prometheus:v3.13.1@sha256:3c42b892cf723fa54d2f262c37a0e1f80aa8c8ddb1da7b9b0df9455a35a7f893
    command:
      - --config.file=/runtime/prometheus.yml
      - --storage.tsdb.path=/prometheus
    volumes:
      - ${OBSERVABILITY_RUNTIME_DIR:?Set OBSERVABILITY_RUNTIME_DIR for the observability profile}/prometheus:/runtime:ro
      - ./ops/observability/rules.yml:/etc/prometheus/rules.yml:ro
      - prometheus_data:/prometheus
    ports:
      - target: 9090
        published: "${OBSERVABILITY_PROMETHEUS_PORT:-0}"
        host_ip: 127.0.0.1
        protocol: tcp
    healthcheck:
      test: ["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:9090/-/ready"]
      interval: 2s
      timeout: 3s
      retries: 20
    depends_on:
      alertmanager:
        condition: service_healthy
    read_only: true
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    networks: [internal, observability_host]
    restart: unless-stopped
    profiles: [observability]

  grafana:
    image: grafana/grafana:13.1.0@sha256:121a7a9ece6dc10b969f1f96eed64b4f07dfac0d0b8abc070f7cb83bbde86f63
    environment:
      GF_SECURITY_ADMIN_USER: ${OBSERVABILITY_GRAFANA_ADMIN_USER:?Set OBSERVABILITY_GRAFANA_ADMIN_USER}
      GF_SECURITY_ADMIN_PASSWORD__FILE: /run/wnh-secrets/admin-password
      GF_USERS_ALLOW_SIGN_UP: "false"
      GF_AUTH_ANONYMOUS_ENABLED: "false"
      GF_ANALYTICS_REPORTING_ENABLED: "false"
      GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
      GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: "false"
      GF_PLUGINS_PREINSTALL_DISABLED: "true"
      GF_UNIFIED_ALERTING_ENABLED: "false"
    volumes:
      - ${OBSERVABILITY_RUNTIME_DIR:?Set OBSERVABILITY_RUNTIME_DIR for the observability profile}/grafana:/run/wnh-secrets:ro
      - ./ops/observability/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro
      - ./ops/observability/grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards:ro
      - ./ops/observability/grafana/dashboards:/var/lib/grafana/dashboards:ro
      - grafana_data:/var/lib/grafana
    ports:
      - target: 3000
        published: "${OBSERVABILITY_GRAFANA_PORT:-0}"
        host_ip: 127.0.0.1
        protocol: tcp
    healthcheck:
      test: ["CMD", "wget", "--spider", "--quiet", "http://127.0.0.1:3000/api/health"]
      interval: 2s
      timeout: 3s
      retries: 30
    depends_on:
      prometheus:
        condition: service_healthy
    read_only: true
    tmpfs:
      - /tmp
      - /var/log/grafana
    cap_drop: [ALL]
    security_opt:
      - no-new-privileges:true
    networks: [internal, observability_host]
    restart: unless-stopped
    profiles: [observability]

networks:
  observability_host:

volumes:
  alertmanager_data:
  prometheus_data:
  grafana_data:
