• January 21, 2026

How to Deploy Loki – Log Aggregation System

How to Deploy Loki – Log Aggregation System

Deploy Loki with Docker Compose and Traefik for secure, scalable log aggregation.

Loki is an open-source log aggregation system designed for efficiently storing and querying logs from your applications and infrastructure. Unlike traditional log management systems, Loki indexes only label key-value pairs rather than the full-text log content, making it cost-effective and highly scalable for cloud-native environments.

In this article, you will deploy Loki using Docker Compose, configure persistent storage for log data, and set up Traefik as a reverse proxy to securely access your Loki 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, loki.example.com).

Set Up the Directory Structure and Environment Variables

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

  1. Create the directory structure for Loki.
    console
    $ mkdir -p ~/loki-logging/{loki-data,loki-config}

    These directories store Loki’s log chunks, indexes, and configuration files.

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

    Add the following variables:

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

    Replace:

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

    Save and close the file.

  5. Create a Loki configuration file.
    console
    $ nano loki-config/loki-config.yaml
  6. Add the following content.
    yaml
    auth_enabled: false
    
    server:
      http_listen_port: 3100
    
    common:
      path_prefix: /loki
      storage:
        filesystem:
          chunks_directory: /loki/chunks
          rules_directory: /loki/rules
      replication_factor: 1
      ring:
        kvstore:
          store: inmemory
    
    schema_config:
      configs:
        - from: 2020-10-24
          store: tsdb
          object_store: filesystem
          schema: v13
          index:
            prefix: index_
            period: 24h

    Save and close the file.

    This configuration enables local filesystem storage and sets up the indexing schema. The tsdb index store provides efficient time-series based querying of log metadata, while the filesystem object store saves the actual log chunks and metadata in the mounted data directory.

Deploy with Docker Compose

In this section, you create and deploy the Docker Compose stack that runs Loki 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
    
      loki:
        image: grafana/loki:latest
        container_name: loki
        hostname: loki
        expose:
          - "3100"
        volumes:
          - "./loki-config/loki-config.yaml:/etc/loki/loki-config.yaml"
          - "./loki-data:/loki"
        command: -config.file=/etc/loki/loki-config.yaml
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.loki.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.loki.entrypoints=websecure"
          - "traefik.http.routers.loki.tls.certresolver=letsencrypt"
        restart: unless-stopped
    
    volumes:
      letsencrypt:

    Save and close the file.

    The manifest structure consists of:

    • services: Two service definitions create the log aggregation infrastructure:
      • traefik: Receives client connections, administers TLS certificates, and directs traffic to Loki endpoints.
      • loki: Ingests, indexes, and stores log streams from distributed sources.
    • image: Docker Hub provides the official images for both service containers.
    • container_name: Fixed container identifiers streamline monitoring and troubleshooting workflows.
    • command (Traefik): Defines runtime parameters for Docker service watching, dual-port operation (80/443), automatic HTTP-to-HTTPS upgrades, and Let’s Encrypt integration through HTTP challenge verification.
    • command (Loki): Points to the configuration file location within the container filesystem.
    • ports (Traefik): Publishes ports 80 and 443 to the host for client request handling.
    • expose (Loki): Opens port 3100 for inter-container communication while maintaining isolation from external networks.
    • volumes:
      • Host directory bindings preserve configuration files and log chunk storage across deployments.
      • The letsencrypt volume maintains certificate persistence through container updates.
      • Docker socket access grants Traefik the ability to detect containers and configure routes automatically.
    • labels (Loki): Annotation-based Traefik settings that activate proxying, map domain names to services, and assign the appropriate certificate authority.
    • restart: unless-stopped: Guarantees service availability by restarting containers after unexpected shutdowns or system reboots, barring manual termination.
  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
    loki      grafana/loki:latest    "/usr/bin/loki -conf…"   loki      22 seconds ago   Up 21 seconds   3100/tcp
    traefik   traefik:v3.6           "/entrypoint.sh --pr…"   traefik   22 seconds ago   Up 21 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. Loki is ready to accept log streams 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 Loki

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

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

    Output:

    ready

    This confirms Loki is operational and accepting requests.

  2. Query available label names in Loki.
    console
    $ curl https://loki.example.com/loki/api/v1/labels

    Output:

    {"status":"success","data":[]}

    An empty array is expected on a fresh installation with no log data. When logs are ingested, the endpoint returns label names like jobinstance, and any custom labels you have configured.

  3. Verify the Loki version and build information.
    console
    $ curl https://loki.example.com/loki/api/v1/status/buildinfo

    Output:

    {"version":"3.6.0","revision":"bc9cd763","branch":"k277","buildUser":"root@buildkitsandbox","buildDate":"2025-11-17T20:53:46Z","goVersion":""}

    Output displays the version, Go version, and build timestamp. This confirms Loki is responding correctly to API requests.

Conclusion

You have successfully deployed Loki for log aggregation with HTTPS encryption. Container orchestration through Docker Compose ensures reliable operation, while volume mounts preserve log chunks and indexes permanently. Automated TLS certificate provisioning from Let’s Encrypt maintains secure communications as Traefik efficiently routes requests. The system now awaits log ingestion from distributed applications and infrastructure services via its RESTful API interface.

Leave a Reply

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