Grafana Stack

Observability & Infrastructure Monitoring

Grafana Prometheus Loki Project E
0

What Are We Building?

Understanding the Grafana Observability Stack

🔗 Standalone Project (Enhances All Other Projects)
📊
See Everything. Know Everything.

Metrics, logs, and alerts in beautiful dashboards. Monitor your entire infrastructure!

How the Stack Works

🖥️
Your Apps
Metrics+Logs
🔥
Prometheus
Metrics
📊
Grafana
Visualize
🚨
Alerts
Notify
📝
Your Apps
Logs
📋
Loki
Log Store
📊
Grafana
Search

The Grafana Stack

📊
Grafana
Visualization & dashboards. The face of your monitoring.
🔥
Prometheus
Metrics collection. Time-series database for numbers.
📋
Loki
Log aggregation. Like Prometheus, but for logs.
📤
Promtail
Log shipper. Sends logs to Loki.
🎯

What You'll Have When Done

  • Beautiful real-time dashboards
  • CPU, memory, disk, network metrics
  • Docker container monitoring
  • Centralized log searching
  • Alerting via Slack, email, or webhook
  • SSO login via Authentik
  • Pre-built dashboards for common apps

⚡ The Problem This Solves

Without Observability:

  • "Is the server slow or is it just me?"
  • SSH into each server to check logs
  • Find out about problems from angry users
  • No historical data to debug issues

With Grafana Stack: See everything in dashboards, search logs from one place, get alerted before users notice!

⏱️

Time Investment

Phase Time Difficulty
Understanding Concepts 15-20 min Reading
Stack Installation 30-45 min Easy
Prometheus Setup 20-30 min Easy
Loki + Promtail 20-30 min Easy
Dashboard Creation 30-45 min Medium
Alerting Setup 20-30 min Medium

Total: 3-4 hours

1

Core Concepts

Understanding observability

🧠
The Three Pillars of Observability

Metrics, Logs, and Traces - the holy trinity of knowing what's happening

📈
Metrics
Numbers over time. CPU usage, request count, error rate, etc.
📝
Logs
Text events. What happened, when, and why. Debug info.
🔗
Traces
Request flow across services. Where did time go? (Advanced)
📊

Metrics vs Logs

Metrics (Prometheus) Logs (Loki)
Numbers: CPU is 85% Text: "Error connecting to database"
Aggregated: Average over time Individual: Each event
Low storage: Just numbers High storage: Full text
Good for: Dashboards, trends Good for: Debugging, investigation
Query: PromQL Query: LogQL
📚

Key Terms

Term Meaning
Exporter App that exposes metrics for Prometheus to scrape
Scrape Prometheus pulls metrics from exporters
Time Series Data points indexed by time
Label Key-value pair to identify metrics (e.g., host="server1")
Dashboard Collection of visualizations (panels) in Grafana
Data Source Where Grafana gets data (Prometheus, Loki, etc.)
💡
Real World Analogy

Metrics: Your car's speedometer, fuel gauge, RPM
Logs: Your car's detailed diagnostic codes
Dashboard: Your car's instrument cluster display

2

Prerequisites

What you need before starting

Before You Begin

This project can run standalone or enhance your existing stack

🖥️

Server Requirements

Resource Minimum Recommended
RAM 2 GB additional 4 GB additional
Storage 20 GB 50+ GB (for retention)
CPU 2 cores 4 cores
📋

Checklist

  • Ubuntu Server with Docker installed
  • Docker Compose available
  • Basic understanding of YAML
  • (Optional) Authentik for SSO (Project A)
  • (Optional) Traefik for reverse proxy
💡
Standalone OK!

Unlike some other projects, you can run this independently. But it's even better when combined with Projects A-D!

3

Install the Stack

Deploy Grafana, Prometheus, and Loki

⚠️ Run Commands on Your SERVER

SSH into your server first. These commands run on the server.

1
Create Directory Structure
⏱️ 2 min
📁 Create Directories
# Create monitoring stack directory
mkdir -p ~/monitoring/{grafana,prometheus,loki,promtail}
mkdir -p ~/monitoring/grafana/{data,provisioning/datasources,provisioning/dashboards}
mkdir -p ~/monitoring/prometheus/data
mkdir -p ~/monitoring/loki/data

# Set permissions
sudo chown -R 472:472 ~/monitoring/grafana/data
sudo chown -R 65534:65534 ~/monitoring/prometheus/data
sudo chown -R 10001:10001 ~/monitoring/loki/data

cd ~/monitoring
2
Create Prometheus Configuration
⏱️ 5 min
🔥 prometheus.yml
cat > ~/monitoring/prometheus/prometheus.yml << 'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: []

rule_files: []

scrape_configs:
  # Prometheus itself
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Node Exporter (system metrics)
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

  # Docker containers (cAdvisor)
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  # Traefik (if you have it)
  - job_name: 'traefik'
    static_configs:
      - targets: ['traefik:8080']
EOF
3
Create Loki Configuration
⏱️ 3 min
📋 loki-config.yml
cat > ~/monitoring/loki/loki-config.yml << 'EOF'
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: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /loki/boltdb-shipper-active
    cache_location: /loki/boltdb-shipper-cache
    shared_store: filesystem
  filesystem:
    directory: /loki/chunks

limits_config:
  retention_period: 720h  # 30 days
EOF
4
Create Promtail Configuration
⏱️ 3 min
📤 promtail-config.yml
cat > ~/monitoring/promtail/promtail-config.yml << 'EOF'
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  # Docker container logs
  - job_name: containers
    static_configs:
      - targets:
          - localhost
        labels:
          job: containerlogs
          __path__: /var/lib/docker/containers/*/*log

    pipeline_stages:
      - json:
          expressions:
            output: log
            stream: stream
            attrs:
      - json:
          expressions:
            tag:
          source: attrs
      - regex:
          expression: (?P(?:[a-zA-Z0-9][a-zA-Z0-9_.-]+))
          source: tag
      - labels:
          stream:
          container_name:
      - output:
          source: output

  # System logs
  - job_name: syslog
    static_configs:
      - targets:
          - localhost
        labels:
          job: syslog
          __path__: /var/log/syslog
EOF
5
Configure Grafana Data Sources
⏱️ 3 min
📊 datasources.yml
cat > ~/monitoring/grafana/provisioning/datasources/datasources.yml << 'EOF'
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: false

  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100
    editable: false
EOF
6
Create Docker Compose File
⏱️ 5 min
🐳 docker-compose.yml
cat > ~/monitoring/docker-compose.yml << 'EOF'
version: '3.8'

services:
  # ==========================================
  # GRAFANA - Visualization
  # ==========================================
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - ./grafana/data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    networks:
      - monitoring

  # ==========================================
  # PROMETHEUS - Metrics
  # ==========================================
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'
      - '--web.enable-lifecycle'
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/data:/prometheus
    networks:
      - monitoring

  # ==========================================
  # LOKI - Log Aggregation
  # ==========================================
  loki:
    image: grafana/loki:2.9.0
    container_name: loki
    restart: unless-stopped
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/loki-config.yml
    volumes:
      - ./loki/loki-config.yml:/etc/loki/loki-config.yml:ro
      - ./loki/data:/loki
    networks:
      - monitoring

  # ==========================================
  # PROMTAIL - Log Shipper
  # ==========================================
  promtail:
    image: grafana/promtail:2.9.0
    container_name: promtail
    restart: unless-stopped
    volumes:
      - ./promtail/promtail-config.yml:/etc/promtail/promtail-config.yml:ro
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    command: -config.file=/etc/promtail/promtail-config.yml
    networks:
      - monitoring

  # ==========================================
  # NODE EXPORTER - System Metrics
  # ==========================================
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    restart: unless-stopped
    ports:
      - "9100:9100"
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--path.rootfs=/rootfs'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    networks:
      - monitoring

  # ==========================================
  # cADVISOR - Container Metrics
  # ==========================================
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    privileged: true
    devices:
      - /dev/kmsg
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge
EOF
7
Start the Stack
⏱️ 5 min
🚀 Start All Services
cd ~/monitoring

# Pull all images
docker compose pull

# Start the stack
docker compose up -d

# Check all containers are running
docker compose ps

# View logs
docker compose logs -f
🎉
Stack is Running!

Access Grafana at http://YOUR_SERVER_IP:3000
Default login: admin / admin123

4

Prometheus Metrics

Collect and query metrics

🔥
Metrics Collection

Prometheus scrapes metrics from your services every 15 seconds

1
Verify Prometheus is Working
⏱️ 2 min
  1. Open http://YOUR_SERVER_IP:9090
  2. Go to Status → Targets
  3. All targets should show UP in green
2
Try Basic Queries (PromQL)
⏱️ 5 min

In Prometheus UI, try these queries:

📊 Example PromQL Queries
# CPU Usage (percentage)
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Memory Usage (percentage)
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# Disk Usage (percentage)
(1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100

# Network Received (bytes/sec)
rate(node_network_receive_bytes_total[5m])

# Docker Container CPU
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100

# Docker Container Memory
container_memory_usage_bytes{name!=""}
📦

Common Exporters to Add

Exporter Metrics For Port
node-exporter Linux system metrics 9100
cAdvisor Docker containers 8080
postgres-exporter PostgreSQL database 9187
blackbox-exporter HTTP/TCP/ICMP probes 9115
nginx-exporter Nginx web server 9113
5

Loki Log Aggregation

Search all your logs in one place

📋
Centralized Logging

No more SSH-ing into servers to read logs!

1
Verify Logs are Flowing
⏱️ 3 min
  1. Open Grafana at http://YOUR_SERVER_IP:3000
  2. Go to Explore (compass icon)
  3. Select Loki as the data source
  4. Click Log browser → Select a label → Show logs
2
LogQL Query Examples
⏱️ 5 min
🔍 Example LogQL Queries
# All logs from a specific container
{container_name="grafana"}

# Filter for errors
{container_name="grafana"} |= "error"

# Case-insensitive search
{container_name="grafana"} |~ "(?i)error"

# Exclude certain patterns
{container_name="grafana"} != "healthcheck"

# Multiple filters
{job="containerlogs"} |= "error" |= "database"

# Parse JSON logs
{container_name="authentik-server"} | json

# Count errors per minute
count_over_time({container_name="grafana"} |= "error" [1m])
💡
Pro Tip

Combine Loki with Prometheus! When you see a spike in error metrics, click through to see the actual error logs.

6

Create Dashboards

Visualize your data beautifully

📊
Dashboard Gallery

Import pre-built dashboards or create your own!

1
Import Pre-Built Dashboards
⏱️ 5 min

Import these popular dashboards from Grafana.com:

  1. In Grafana, go to Dashboards → Import
  2. Enter one of these Dashboard IDs:
    ID Dashboard
    1860 Node Exporter Full (System metrics)
    893 Docker & System Monitoring
    14282 cAdvisor Container Dashboard
    13639 Loki Dashboard
  3. Click Load, select Prometheus as data source, Import
2
Create a Custom Dashboard
⏱️ 10 min
  1. Go to Dashboards → New Dashboard
  2. Click Add visualization
  3. Select Prometheus data source
  4. Enter a query (e.g., CPU usage from above)
  5. Choose visualization type (Gauge, Graph, Stat, etc.)
  6. Click Apply and arrange on dashboard
🎨
Dashboard Ideas

Create dashboards for: Home Lab Overview, Docker Containers, Network Traffic, Security Events (from Wazuh), IAM Activity (from Authentik)

7

Configure Alerting

Get notified when things go wrong

🚨
Proactive Monitoring

Know about problems before your users do!

1
Create Alert Rule
⏱️ 10 min
  1. Go to Alerting → Alert rules → Create alert rule
  2. Name: "High CPU Usage"
  3. Query: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
  4. Condition: IS ABOVE 80
  5. Evaluate every: 1m for 5m
  6. Add labels and annotations
  7. Click Save and exit
2
Configure Notification Channel
⏱️ 5 min
  1. Go to Alerting → Contact points → Add contact point
  2. Choose type: Slack, Email, or Webhook
  3. Configure settings (webhook URL, email address, etc.)
  4. Click Test to verify
  5. Save
⚠️

Recommended Alert Rules

Alert Condition Severity
High CPU CPU > 80% for 5min Warning
High Memory Memory > 90% for 5min Warning
Disk Full Disk > 85% Critical
Container Down Container not running Critical
High Error Rate Errors > 10/min Warning
8

Testing & Verification

Make sure everything works

🧪
Verify Your Stack

Test all components are working correctly

Verification Checklist

  • Grafana accessible at port 3000
  • Prometheus targets all showing UP
  • Loki receiving logs
  • Node Exporter metrics available
  • cAdvisor container metrics available
  • Dashboards displaying data
  • Alert rules configured
Quick Health Checks
🔍 Test Commands
# Check all containers running
docker compose ps

# Test Prometheus
curl http://localhost:9090/-/healthy

# Test Loki
curl http://localhost:3100/ready

# Test Grafana
curl http://localhost:3000/api/health

# Check Prometheus targets
curl http://localhost:9090/api/v1/targets | jq '.data.activeTargets[].health'

# View container logs
docker compose logs grafana --tail=20
🔧

Common Issues

🔴 Prometheus Target Down

Cause: Exporter not running or network issue

Solution:
• Check container is running: docker ps
• Verify network connectivity between containers
• Check exporter logs

🔴 No Logs in Loki

Cause: Promtail not shipping logs

Solution:
• Check Promtail logs: docker logs promtail
• Verify log paths exist
• Check Promtail can reach Loki

🔴 Dashboard Shows No Data

Cause: Data source misconfigured or time range

Solution:
• Check data source URL in Grafana settings
• Adjust time range to last hour
• Test query in Explore first

🎉

Congratulations!

Your observability stack is live!

🏆
Observability Expert

You now have enterprise-grade monitoring for your infrastructure!

📊

Skills Demonstrated

  • Infrastructure monitoring with Prometheus
  • Log aggregation with Loki
  • Dashboard creation in Grafana
  • PromQL and LogQL querying
  • Alert configuration
  • Container monitoring
🚀

Next Steps

  • Add Authentik SSO to Grafana (OIDC)
  • Add more exporters for your services
  • Create dashboards for Projects A-D
  • Set up Alertmanager for advanced routing
  • Add Tempo for distributed tracing
  • Configure long-term storage (Thanos/Cortex)