• January 21, 2026

How to Deploy Tempo – Distributed Tracing Backend

How to Deploy Tempo – Distributed Tracing Backend

Deploy Tempo with Docker Compose and Traefik for secure, persistent distributed tracing.

Tempo is an open-source distributed tracing backend that stores and queries traces from your applications. It integrates seamlessly with distributed systems to help you understand request flows, identify performance bottlenecks, and troubleshoot issues across microservices architectures. Tempo requires only object storage and is designed for cost-efficient, high-volume trace data.

In this article, you will deploy Tempo using Docker Compose, configure persistent storage for trace data, and set up Traefik as a reverse proxy to securely access your Tempo instance.

Prerequisites

Before you begin, you need to:

  • Have access to an Ubuntu 24.04-based server as a non-root user with sudo privileges.
  • Install Docker and Docker Compose.
  • Configure a domain A record pointing to your server’s IP address (for example, tempo.example.com).

Set Up the Directory Structure and Environment Variables

In this section, you prepare the required directory structure for Tempo and define environment variables in a .env file.

  1. Create the directory structure for Tempo.
    console
    $ mkdir -p ~/tempo-tracing/{tempo-data,tempo-config}

    These directories store Tempo’s trace blocks and configuration files.

  2. Navigate into the tempo-tracing directory.
    console
    $ cd ~/tempo-tracing
  3. Set proper ownership for the Tempo data directory. Tempo runs as the tempo user (UID 10001) inside the container.
    console
    $ sudo chown -R 10001:10001 tempo-data
  4. Create a .env file.
    console
    $ nano .env

    Add the following variables:

    ini
    DOMAIN=tempo.example.com
    LETSENCRYPT_EMAIL=admin@example.com

    Replace:

    • tempo.example.com with your domain.
    • admin@example.com with your email.

    Save and close the file.

  5. Create a Tempo configuration file.
    console
    $ nano tempo-config/tempo-config.yaml
  6. Add the following content.
    yaml
    server:
      http_listen_port: 3200
    
    distributor:
      receivers:
        jaeger:
          protocols:
            thrift_http:
            grpc:
        otlp:
          protocols:
            http:
            grpc:
    
    storage:
      trace:
        backend: local
        local:
          path: /var/tempo/traces
        wal:
          path: /var/tempo/wal
    
    compactor:
      compaction:
        block_retention: 168h

    Save and close the file.

    This configuration enables trace ingestion via Jaeger and OpenTelemetry protocols, configures local filesystem storage for trace data, and sets a 7-day retention period. The distributor accepts traces in multiple formats while the storage backend persists them to the mounted data directory.

Deploy with Docker Compose

In this section, you create and deploy the Docker Compose stack that runs Tempo behind Traefik. Docker Compose manages both containers, applies the environment variables from your .env file, and automatically configures HTTPS routing through Traefik.

  1. Create a new Docker Compose manifest.
    console
    $ nano docker-compose.yaml
  2. Add the following content.
    yaml
    services:
      traefik:
        image: traefik:v3.6
        container_name: traefik
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "letsencrypt:/letsencrypt"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
        restart: unless-stopped
    
      tempo:
        image: grafana/tempo:latest
        container_name: tempo
        hostname: tempo
        expose:
          - "3200"
          - "4317"
          - "4318"
          - "14250"
          - "14268"
        volumes:
          - "./tempo-config/tempo-config.yaml:/etc/tempo/tempo.yaml"
          - "./tempo-data:/var/tempo"
        command: -config.file=/etc/tempo/tempo.yaml
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.tempo.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.tempo.entrypoints=websecure"
          - "traefik.http.routers.tempo.tls.certresolver=letsencrypt"
          - "traefik.http.services.tempo.loadbalancer.server.port=3200"
        restart: unless-stopped
    
    volumes:
      letsencrypt:

    Save and close the file.

    Key components in this configuration:

    • services: Two cooperating containers implement the tracing backend:
      • traefik: Handles HTTP/HTTPS traffic, automatically obtains Let’s Encrypt certificates, and proxies requests to Tempo.
      • tempo: Collects trace spans, archives them for querying, and exposes APIs for retrieval.
    • image: Container registries on Docker Hub supply the official images.
    • container_name: Static naming facilitates service identification during debugging and administrative operations.
    • command (Traefik): Establishes behavior including Docker integration, port configuration (80/443), protocol enforcement (HTTPS), and automated Let’s Encrypt certificate requests via HTTP validation.
    • command (Tempo): Identifies the configuration file path for service initialization.
    • ports (Traefik): Binds host ports 80 and 443 for client connectivity.
    • expose (Tempo): Makes multiple ports accessible within the container network without public exposure. Port 3200 handles HTTP queries, while ports 4317, 4318, 14250, and 14268 receive trace data from different protocol implementations.
    • volumes:
      • File system mounts ensure configuration and trace storage persists beyond container lifecycles.
      • Certificate information survives container recreation through the letsencrypt named volume.
      • Traefik accesses Docker’s control socket to perform automatic service detection and routing updates.
    • labels (Tempo): Traefik routing metadata that enables proxy behavior, associates domain names with backends, designates the TLS provider, and specifies port 3200 for load balancing.
    • restart: unless-stopped: Maintains service continuity by auto-restarting containers following failures or reboots, except when manually terminated.
  3. Create and start the services.
    console
    $ docker compose up -d
  4. Verify that the services are running.
    console
    $ docker compose ps

    Output:

    NAME      IMAGE                  COMMAND                  SERVICE   CREATED          STATUS          PORTS
    tempo     grafana/tempo:latest   "/tempo -config.file…"   tempo     18 seconds ago   Up 17 seconds   3200/tcp, 4317/tcp, 4318/tcp, 14250/tcp, 14268/tcp
    traefik   traefik:v3.6           "/entrypoint.sh --pr…"   traefik   18 seconds ago   Up 17 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:443->443/tcp, [::]:443->443/tcp

    Both containers are running successfully. Tempo is ready to accept trace data while Traefik accepts connections on ports 80 and 443.

  5. View the logs of the services.
    console
    $ docker compose logs

    For more information on managing a Docker Compose stack, see the How To Use Docker Compose article.

Access Tempo

In this section, you access the Tempo API to verify your installation by checking service readiness and querying available trace endpoints.

  1. Check the service readiness endpoint.
    console
    $ curl https://tempo.example.com/ready

    Output:

    ready

    This confirms Tempo is operational and accepting requests.

  2. Query the service status to view configuration details.
    console
    $ curl https://tempo.example.com/status

    Output displays Tempo’s current configuration, including enabled modules, storage backend, and ingestion settings. This endpoint is useful for verifying your deployment configuration.

  3. Check the build information to verify the Tempo version.
    console
    $ curl https://tempo.example.com/api/status/buildinfo

    Output:

    {"version":"v2.9.0","revision":"032d47627","branch":"main","buildUser":"","buildDate":"","goVersion":"go1.25.1"}

    This confirms Tempo is responding correctly to API requests and displays version information for troubleshooting purposes.

Conclusion

You have successfully deployed Tempo for distributed tracing with HTTPS encryption. The Docker Compose architecture delivers both the tracing backend and reverse proxy with filesystem persistence ensuring trace data durability. Let’s Encrypt automation maintains valid certificates while Traefik performs intelligent traffic management. Tempo now stands ready to accept distributed trace spans from microservices using Jaeger, OpenTelemetry, or alternative instrumentation frameworks through its protocol-agnostic ingestion APIs.

Leave a Reply

Your email address will not be published. Required fields are marked *