Logs centralisés avec Grafana Loki + Promtail

Logs centralisés avec Grafana Loki + Promtail

Centralisez les logs de tous vos VPS dans une seule UI Grafana avec Loki. Léger, performant, requêtage façon Prometheus (LogQL), et beaucoup moins gourmand qu'ELK. Le standard moderne pour le multi-serveurs.

Introduction

Quand vous avez 1 VPS, grep /var/log/syslog suffit. À 3+ VPS, naviguer entre les serveurs devient pénible. À 10+, c'est impossible. Solution : centraliser les logs.

Stack classique : ELK (Elasticsearch + Logstash + Kibana). Lourd, complexe, mange de la RAM. Alternative moderne : Grafana Loki :

  • Léger : indexe les labels, pas le contenu → 10x moins de stockage
  • Pensé comme Prometheus : même UX, même langage de query (LogQL)
  • Intégré à Grafana : un seul outil pour metrics + logs
  • Open-source par Grafana Labs

Ce tuto installe Loki sur un VPS central + Promtail (agent) sur chaque VPS source.

Prérequis

  • 1 VPS "central" pour Loki + Grafana (1 Go RAM mini)
  • N VPS sources dont vous voulez les logs
  • Docker installé sur le VPS central
  • Réseau entre les VPS (WireGuard recommandé pour ne pas exposer Loki publiquement)

Étape 1 : Architecture cible

   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
   │ VPS Web 1        │  │ VPS Web 2        │  │ VPS DB           │
   │  + Promtail      │  │  + Promtail      │  │  + Promtail      │
   └────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘
            │                     │                     │
            └─────────────────────┼─────────────────────┘
                                  │
                          ┌───────▼────────┐
                          │  VPS Central   │
                          │  ┌──────────┐  │
                          │  │  Loki    │  │
                          │  └──────────┘  │
                          │  ┌──────────┐  │
                          │  │ Grafana  │  │
                          │  └──────────┘  │
                          └────────────────┘

Étape 2 : Déployer Loki + Grafana (VPS central)

sudo mkdir -p /opt/loki-stack
cd /opt/loki-stack
sudo nano docker-compose.yml
services:
  loki:
    image: grafana/loki:3.0.0
    container_name: loki
    restart: unless-stopped
    ports:
      - "3100:3100"
    volumes:
      - ./loki-config.yml:/etc/loki/local-config.yaml:ro
      - loki_data:/loki
    command: -config.file=/etc/loki/local-config.yaml
    networks:
      - loki-net

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=UnMotDePasseFort
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
    networks:
      - loki-net
    depends_on:
      - loki

volumes:
  loki_data:
  grafana_data:

networks:
  loki-net:

Étape 3 : Config Loki minimale

sudo nano /opt/loki-stack/loki-config.yml
auth_enabled: false

server:
  http_listen_port: 3100
  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: inmemory

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

limits_config:
  retention_period: 720h     # 30 jours
  max_query_series: 100000

compactor:
  working_directory: /loki/compactor
  delete_request_store: filesystem

ruler:
  alertmanager_url: http://localhost:9093

Étape 4 : Démarrer la stack

sudo docker compose up -d
sudo docker compose logs -f

Vérifiez :

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

Étape 5 : Accès Grafana

Tunnel SSH :

ssh -L 3000:127.0.0.1:3000 user@IP_VPS_CENTRAL

Puis http://localhost:3000 → login admin / UnMotDePasseFort.

Pour exposer en HTTPS, ajoutez Nginx en frontal avec un certificat Let's Encrypt.

Étape 6 : Ajouter Loki comme datasource

Dans Grafana :

  1. Configuration → Data sources → Add data source
  2. Cherchez Loki
  3. URL : http://loki:3100 (nom du service Docker)
  4. Save & test → doit dire "Data source is working"

Étape 7 : Installer Promtail sur un VPS source

Sur chaque VPS dont vous voulez les logs :

wget https://github.com/grafana/loki/releases/download/v3.0.0/promtail-linux-amd64.zip
unzip promtail-linux-amd64.zip
sudo mv promtail-linux-amd64 /usr/local/bin/promtail
sudo chmod +x /usr/local/bin/promtail

Créez la config :

sudo nano /etc/promtail/config.yml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/lib/promtail/positions.yaml

clients:
  - url: http://IP_VPS_CENTRAL:3100/loki/api/v1/push
    # ou via WireGuard : http://10.66.66.1:3100/loki/api/v1/push

scrape_configs:
  # Syslog
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: syslog
          host: srv-web-01
          __path__: /var/log/syslog

  # Auth (SSH, sudo)
  - job_name: auth
    static_configs:
      - targets:
          - localhost
        labels:
          job: auth
          host: srv-web-01
          __path__: /var/log/auth.log

  # Nginx
  - job_name: nginx
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx_access
          host: srv-web-01
          __path__: /var/log/nginx/access.log
      - targets:
          - localhost
        labels:
          job: nginx_error
          host: srv-web-01
          __path__: /var/log/nginx/error.log

  # Tous les conteneurs Docker (auto-discovery)
  - job_name: docker
    static_configs:
      - targets:
          - localhost
        labels:
          job: docker
          host: srv-web-01
          __path__: /var/lib/docker/containers/*/*-json.log

  # Journald
  - job_name: journal
    journal:
      max_age: 12h
      labels:
        job: systemd-journal
        host: srv-web-01
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'
sudo mkdir -p /var/lib/promtail

Étape 8 : Service systemd pour Promtail

sudo nano /etc/systemd/system/promtail.service
[Unit]
Description=Promtail
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/config.yml
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now promtail
sudo systemctl status promtail

Vérifiez la connexion vers Loki :

sudo journalctl -u promtail -f

Doit lire les logs sans erreur réseau.

Étape 9 : Explorer les logs dans Grafana

Dans Grafana → Explore (icône boussole) → datasource Loki.

Requêtes type :

# Tous les logs nginx access du host srv-web-01
{host="srv-web-01", job="nginx_access"}

# Erreurs uniquement
{job="nginx_error"} |= "error"

# Logs avec regex
{job="auth"} |~ "Failed password"

# Compter les erreurs 5xx par minute
sum(rate({job="nginx_access"} | json | status >= 500 [1m])) by (host)

# Top des 404
sum(count_over_time({job="nginx_access"} |= " 404 " [1h])) by (host)

Étape 10 : Parser les logs structurés (JSON, regexp)

Logs nginx en format standard

{job="nginx_access"}
  | regexp `(?P<remote_addr>[\d\.]+) - - \[(?P<timestamp>[^\]]+)\] "(?P<method>\w+) (?P<path>[^ ]+) HTTP/[\d\.]+" (?P<status>\d+) (?P<bytes>\d+)`
  | status >= 500

Logs JSON (apps Node, Go)

{job="myapp"} | json | level="error"

Étape 11 : Dashboards Grafana

  1. Dashboards → Import → ID 13639 (dashboard Loki + Promtail communautaire)
  2. Sélectionnez votre datasource Loki
  3. Importez

Vous obtenez instantanément des graphes : top hosts, log rate par job, erreurs, etc.

Étape 12 : Alerting (logs → alertes)

Dans Grafana → Alerting :

  1. New alert rule
  2. Datasource Loki
  3. Query :
sum(count_over_time({job="auth"} |= "Failed password" [5m])) by (host) > 20
  1. Threshold : > 20 (= plus de 20 échecs SSH en 5 min)
  2. Notification → Email, Discord, Slack, Telegram

Étape 13 : Rétention et nettoyage

Loki garde les logs selon retention_period. Pour les anciennes données :

sudo docker compose exec loki ls -lh /loki/chunks/

Le compactor (configuré dans loki-config.yml) supprime automatiquement les anciens chunks.

Dépannage

Promtail ne push pas vers Loki

sudo journalctl -u promtail -n 50

Causes fréquentes :

  • Firewall qui bloque le port 3100 sur le VPS central
  • URL Loki erronée (ne pas oublier /loki/api/v1/push)
  • DNS qui ne résout pas

"context deadline exceeded"

Loki est surchargé ou Promtail trop agressif. Limitez :

clients:
  - url: http://...
    batchwait: 1s
    batchsize: 1048576

Aucun log dans Grafana

Vérifiez dans Grafana → Explore → Loki que la datasource fonctionne. Puis testez avec une requête générale {job=~".+"}.

Loki bouffe trop de disque

Réduisez retention_period. 7-30 jours est généralement suffisant.

Commandes utiles

# Statut Promtail
sudo systemctl status promtail
sudo journalctl -u promtail -f

# Tester la config Promtail
sudo promtail --check-syntax --config.file=/etc/promtail/config.yml

# Tester la connectivité vers Loki
curl http://IP_VPS_CENTRAL:3100/ready

# Métriques Promtail (combien de logs envoyés)
curl http://localhost:9080/metrics | grep promtail

# Forcer Promtail à relire les positions
sudo systemctl restart promtail

# Voir l'espace utilisé par Loki
sudo docker compose exec loki du -sh /loki

Conclusion

Avec Loki + Promtail vous obtenez :

  • Recherche unifiée sur tous vos VPS depuis une seule UI
  • Stockage 10x plus efficient que ELK
  • Requêtes LogQL puissantes et familières si vous connaissez PromQL
  • Alerting natif intégré à Grafana

Pour aller plus loin :

  • Migrez Loki vers stockage S3 / B2 pour stocker des années de logs à bas prix
  • Combinez avec Prometheus et Tempo pour la stack complète (metrics + logs + traces)
  • Utilisez Vector ou Fluent Bit comme alternative à Promtail (plus de transformations)

Ressources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members