Setting Up Your Observability Stack

Before you can collect metrics or centralize logs, you need somewhere to store and visualize them — and an agent to collect the data. This post sets up all four components of a Grafana observability stack:

  • Prometheus — metrics storage
  • Loki — log storage
  • Grafana — visualization
  • Grafana Alloy — telemetry collection agent

Prometheus

Prometheus is a time-series database that stores metrics. We’ll enable the remote write receiver so Alloy can push metrics directly to it.

Create a directory and Docker Compose file:

BASH
mkdir prometheus
nano prometheus/docker-compose.yml
Click to expand and view more
docker-compose.yml
services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    environment:
      - TZ=Europe/Amsterdam
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=90d'
      - '--storage.tsdb.retention.size=100GB'
      - '--web.enable-lifecycle'
      - '--web.enable-remote-write-receiver'
    restart: unless-stopped
    networks:
      - backend

networks:
  backend:
    name: backend

volumes:
  prometheus:
    name: prometheus
Click to expand and view more

Create the Prometheus config file:

BASH
nano prometheus/prometheus.yml
Click to expand and view more
prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs: []
Click to expand and view more

scrape_configs is empty because Alloy pushes metrics via remote write. Adjust retention.time and retention.size to match your available disk space — whichever limit is hit first triggers cleanup.

Start Prometheus:

BASH
docker compose -f prometheus/docker-compose.yml up -d
Click to expand and view more

Verify it’s ready:

BASH
curl -s http://localhost:9090/-/ready
Click to expand and view more

Loki

Loki stores logs indexed by labels rather than full-text, making it storage-efficient and fast for label-based queries.

Create a directory and Docker Compose file:

BASH
mkdir loki
nano loki/docker-compose.yml
Click to expand and view more
docker-compose.yml
services:
  loki:
    image: grafana/loki
    container_name: loki
    restart: unless-stopped
    environment:
      - TZ=Europe/Amsterdam
    volumes:
      - ./loki-config.yaml:/etc/loki/loki-config.yaml:ro
      - loki-data:/loki
    command: -config.file=/etc/loki/loki-config.yaml
    networks:
      - backend

networks:
  backend:
    name: backend

volumes:
  loki-data:
    name: loki-data
Click to expand and view more

Create the Loki config file:

BASH
nano loki/loki-config.yaml
Click to expand and view more
loki-config.yaml
auth_enabled: false

server:
  http_listen_address: 0.0.0.0
  http_listen_port: 3100
  grpc_listen_port: 9095
  log_level: info

common:
  instance_addr: 127.0.0.1
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: memberlist

schema_config:
  configs:
    - from: 2020-10-24
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  query_timeout: 600s
  retention_period: "365d"
  ingestion_rate_mb: 4
  ingestion_burst_size_mb: 6
  max_streams_per_user: 10000
  max_line_size: 256000
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  creation_grace_period: 15m
  discover_log_levels: false
Click to expand and view more

Adjust retention_period based on your available disk space.

Start Loki:

BASH
docker compose -f loki/docker-compose.yml up -d
Click to expand and view more

Verify it’s ready:

BASH
curl -s http://localhost:3100/ready
Click to expand and view more

Grafana

Grafana is the visualization layer — it connects to Prometheus and Loki and lets you build dashboards and explore data.

Create a directory and Docker Compose file:

BASH
mkdir grafana
nano grafana/docker-compose.yml
Click to expand and view more
docker-compose.yml
services:
  grafana:
    image: grafana/grafana
    container_name: grafana
    hostname: ${HOSTNAME}
    environment:
      - TZ=Europe/Amsterdam
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
    restart: unless-stopped
    ports:
      - 3000:3000
    networks:
      - backend

networks:
  backend:
    name: backend

volumes:
  grafana_data:
    name: grafana_data
Click to expand and view more

Change GF_SECURITY_ADMIN_PASSWORD to a secure password before starting.

Start Grafana:

BASH
docker compose -f grafana/docker-compose.yml up -d
Click to expand and view more

Open http://<HOST_IP>:3000 and log in with username admin and your password.

Add Datasources

Connect Grafana to Prometheus and Loki:

Prometheus:

  1. Click Connections → search for PrometheusAdd new Datasource
  2. Set name prometheus, URL http://prometheus:9090
  3. Click Save & Test

Loki:

  1. Click Connections → search for LokiAdd new Datasource
  2. Set name loki, URL http://loki:3100
  3. Click Save & Test

Grafana Alloy

Alloy is the telemetry collection agent that replaces Promtail and Grafana Agent. It collects metrics, logs, and traces and forwards them to Prometheus and Loki using a modular config — each collector lives in its own .alloy file.

Create a directory for Alloy and its config files:

BASH
mkdir -p alloy/config
nano alloy/docker-compose.yml
Click to expand and view more
docker-compose.yml
services:
  alloy:
    image: grafana/alloy:latest
    container_name: alloy
    hostname: ${HOSTNAME}
    restart: unless-stopped
    environment:
      - TZ=Europe/Amsterdam
    ports:
      - "12345:12345"
    volumes:
      - ./config/:/etc/alloy/config/:ro
      - alloy-data:/var/lib/alloy/data
    command:
      - run
      - --server.http.listen-addr=0.0.0.0:12345
      - --storage.path=/var/lib/alloy/data
      - /etc/alloy/config/
    networks:
      - backend

networks:
  backend:
    name: backend

volumes:
  alloy-data:
    name: alloy-data
Click to expand and view more

Alloy loads every .alloy file in the config/ directory automatically — adding a new collector is as simple as dropping in a new file. Port 12345 is the Alloy web UI for debugging component status.

Endpoints

Create endpoint.alloy to centralize write destinations. All collector configs reference these by name:

BASH
nano alloy/config/endpoint.alloy
Click to expand and view more
endpoint.alloy
loki.write "default" {
  endpoint {
    url = "http://loki:3100/loki/api/v1/push"
  }
}

prometheus.remote_write "default" {
  endpoint {
    url = "http://prometheus:9090/api/v1/write"
  }
}
Click to expand and view more

Self-Monitoring

Create self.alloy so Alloy reports its own health metrics to Prometheus:

BASH
nano alloy/config/self.alloy
Click to expand and view more
self.alloy
prometheus.exporter.self "alloy_metrics" {}

prometheus.scrape "alloy_metrics" {
  targets         = prometheus.exporter.self.alloy_metrics.targets
  scrape_interval = "60s"
  forward_to      = [prometheus.remote_write.default.receiver]
}
Click to expand and view more

Start Alloy:

BASH
docker compose -f alloy/docker-compose.yml up -d
Click to expand and view more

Open the Alloy web UI at http://<HOST_IP>:12345 to verify all components are green.

What’s Next

With the full stack running, start adding collectors:

Copyright Notice

Author: Sven van Ginkel

Link: https://svenvg.com/posts/setting-up-your-observability-stack/

License: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

Start searching

Enter keywords to search articles

↑↓
ESC
⌘K Shortcut