Jaeger Traefik setup with HTTP basic auth & Badger data store

In our previous example Basic Jaeger v2 docker-compose deployment with Traefik as reverse proxy we set up Jaeger with Traefik as a reverse proxy, but in a very basic way without any authentication and without persistent storage.

docker-compose.yml
services:
  jaeger:
    image: jaegertracing/jaeger:2.11.0
    container_name: jaeger
    restart: "unless-stopped"
    command:
      - "--config"
      - "/etc/jaeger/config.yaml"
    volumes:
      - ./jaeger_badger:/badger
      - ./jaeger.yml:/etc/jaeger/config.yaml
      - ./jaeger-ui.json:/etc/jaeger/config-ui.json
    # ports: # Exposed ports for direct access (not needed with Traefik)
    #  - "5778:5778"
    #  - "16686:16686"
    #  - "4317:4317"
    #  - "4318:4318"
    #  - "14250:14250"
    #  - "14268:14268"f
    #  - "9411:9411"
    labels:
      - "traefik.enable=true"
      # Jaeger web UI
      - "traefik.http.routers.jaeger.rule=Host(`jaeger.mydomain.com`)"
      - "traefik.http.routers.jaeger.entrypoints=websecure"
      - "traefik.http.routers.jaeger.tls.certresolver=cloudflare"
      - "traefik.http.routers.jaeger.tls.domains[0].main=jaeger.mydomain.com"
      - "traefik.http.routers.jaeger.tls.domains[0].sans=*.jaeger.mydomain.com"
      - "traefik.http.routers.jaeger.service=jaeger"
      - "traefik.http.services.jaeger.loadbalancer.server.port=16686"
      # Enable HTTP Basic Auth for the Jaeger UI via Traefik middleware.
      # Generate an htpasswd hash with: htpasswd -n USER | sed 's/\$/\$\$/g'
      - "traefik.http.routers.jaeger.middlewares=jaeger-auth"
      - "traefik.http.middlewares.jaeger-auth.basicauth.users=myuser:$$apr1$$0Dxx4cqa$$U37ZOFeqIFbI4xHJemmwO/"
      # gRPC (OTLP) receiver via Traefik
      - "traefik.http.routers.jaeger-grpc.rule=Host(`grpc.jaeger.mydomain.com`)"
      - "traefik.http.routers.jaeger-grpc.entrypoints=websecure"
      - "traefik.http.routers.jaeger-grpc.tls.certresolver=cloudflare"
      - "traefik.http.routers.jaeger-grpc.tls.domains[0].main=jaeger.mydomain.com"
      - "traefik.http.routers.jaeger-grpc.tls.domains[0].sans=*.jaeger.mydomain.com"
      - "traefik.http.routers.jaeger-grpc.service=jaeger-grpc"
      - "traefik.http.services.jaeger-grpc.loadbalancer.server.port=4317"
      - "traefik.http.services.jaeger-grpc.loadbalancer.server.scheme=h2c"
      - "traefik.http.routers.jaeger-grpc.middlewares=jaeger-http-auth"
      # HTTP (OTLP) receiver via Traefik
      - "traefik.http.routers.jaeger-http.rule=Host(`http.jaeger.mydomain.com`)"
      - "traefik.http.routers.jaeger-http.entrypoints=websecure"
      - "traefik.http.routers.jaeger-http.tls.certresolver=cloudflare"
      - "traefik.http.routers.jaeger-http.tls.domains[0].main=jaeger.mydomain.com"
      - "traefik.http.routers.jaeger-http.tls.domains[0].sans=*.jaeger.mydomain.com"
      - "traefik.http.routers.jaeger-http.service=jaeger-http"
      - "traefik.http.services.jaeger-http.loadbalancer.server.port=4318"
      # Enable HTTP Basic Auth for the Jaeger OTLP HTTP endpoint via Traefik middleware.
      # Generate an htpasswd hash with: htpasswd -n OTLP_USER | sed 's/\$/\$\$/g'
      - "traefik.http.routers.jaeger-http.middlewares=jaeger-http-auth"
      - "traefik.http.middlewares.jaeger-http-auth.basicauth.users=myclient:$$apr1$$cIvXP5Y8$$FENUYFinb/ACisg75hVDS1"
    depends_on:
      prepare-data-dir:
        condition: service_completed_successfully
  prepare-data-dir:
    # Run this step as root so that we can change the directory owner.
    user: root
    image: alpine:3.20
    command: "/bin/sh -c 'chown -R 10001:10001 /badger'"
    volumes:
      - ./jaeger_badger:/badger
jaeger.yml
service:
  extensions: [jaeger_storage, jaeger_query, healthcheckv2]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [jaeger_storage_exporter]
  telemetry:
    resource:
      service.name: jaeger
    metrics:
      level: detailed
      readers:
        - pull:
            exporter:
              prometheus:
                host: 0.0.0.0
                port: 8888
    logs:
      level: info
    # TODO Initialize telemetry tracer once OTEL released new feature.
    # https://github.com/open-telemetry/opentelemetry-collector/issues/10663

extensions:
  healthcheckv2:
    use_v2: true
    http:

  jaeger_query:
    storage:
      traces: badger
      traces_archive: badger_archive
    ui:
      config_file: /etc/jaeger/config-ui.json

  jaeger_storage:
    backends:
      badger:
        badger:
          directories:
            keys: "/badger/data"
            values: "/badger/data"
          ephemeral: false
          ttl:
            spans: 168h # 7 days
      badger_archive:
        badger:
          directories:
            keys: "/badger/data_archive/"
            values: "/badger/data_archive/"
          ephemeral: false
          ttl:
            spans: 720h # 30 days

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:

exporters:
  jaeger_storage_exporter:
    trace_storage: badger
jaeger-ui.json
{
  "dependencies": {
    "dagMaxNumServices": 200,
    "menuEnabled": true
  },
  "monitor": {
    "menuEnabled": true
  },
  "archiveEnabled": true,
  "menu": [
  ],
  "search": {
    "maxLookback": {
      "label": "7 Days",
      "value": "7d"
    },
    "maxLimit": 1500
  },
  "linkPatterns": [],
  "traceIdDisplayLength": 20
}

You can use it with the example from Logfire example which connects to SigNoz instead of Logfire but with the following OLTP endpoint (use the credentials you set in the Traefik configuration):

test-signoz.py
os.environ['OTEL_EXPORTER_OTLP_ENDPOINT'] = 'https://myclient:[email protected]/'

Check out similar posts by category: Monitoring, Docker