Une supervision dit qu'un service va mal. Elle ne dit presque jamais pourquoi. La réponse est écrite quelque part, dans un journal, sur l'une des quarante machines concernées, et elle aura disparu à la prochaine rotation si personne ne va la chercher à temps. Centraliser les journaux, c'est pouvoir poser une seule question à toute l'infrastructure : « qu'est-ce qui s'est passé à 3 h 12 ? »
01Ce que les métriques ne disent pas
- La cause. La courbe montre que PostgreSQL a refusé des connexions à 3 h 12. Le journal dit « too many clients already », et celui de l'application dit lequel des pools s'est emballé.
- Ce qui ne laisse pas de trace numérique. Une tentative de connexion SSH refusée, une sauvegarde qui saute un fichier, un disque qui signale une erreur de lecture corrigée : rien de cela ne fait bouger une courbe.
- La chronologie entre machines. Le noeud a perdu le quorum, puis le service de haute disponibilité a déplacé trois machines, puis l'une n'a pas redémarré. Seule une vue centralisée et horodatée permet de lire cette histoire dans l'ordre.
- La preuve. Après un incident de sécurité, les journaux de la machine compromise sont les premiers à disparaître. Une copie ailleurs est souvent la seule qui reste.
02Loki, Graylog ou autre
Deux philosophies s'affrontent. Graylog, comme Elasticsearch avant lui, indexe le contenu de chaque ligne : toute recherche plein texte est rapide, au prix d'un stockage et d'une mémoire conséquents. Loki n'indexe que quelques étiquettes (la machine, le service) et parcourt le texte au moment de la requête : il coûte une fraction du stockage, et s'intègre naturellement à Grafana, à côté des métriques.
| Critère | Loki et Alloy | Graylog | VictoriaLogs |
|---|---|---|---|
| Ce qui est indexé | Les étiquettes seulement | Tout le contenu | Les champs, sans schéma |
| Ressources pour 50 hôtes | 2 vCPU, 4 Go | 8 vCPU, 16 Go et plus | 2 vCPU, 4 Go |
| Dépendances | Aucune en mode simple | MongoDB, OpenSearch ou Data Node | Aucune |
| Recherche plein texte sur un an | Lente | Rapide | Rapide |
| Analyse et transformation des lignes | À la requête | Pipelines, très complètes | À la requête |
| Intégration Grafana | Native | Par source de données | Par greffon |
| Maturité | Grande | Grande | Plus jeune |
Notre choix par défaut est Loki, pour une raison simple : nos clients ont déjà Grafana, et voir le journal d'une machine sous la courbe qui a décroché, dans le même tableau de bord, change la vitesse de diagnostic. Graylog s'impose quand les journaux sont un sujet en soi : une équipe sécurité qui cherche des chaînes arbitraires sur douze mois, ou des formats hétérogènes à normaliser par pipeline. VictoriaLogs est une alternative légère prometteuse, à suivre si vous utilisez déjà VictoriaMetrics.
03Installer Loki
Loki s'installe en mode monolithique, un seul processus, sur le serveur de supervision de la pile Grafana. Ce mode tient sans difficulté quelques dizaines de gigaoctets de journaux par jour, ce qui couvre largement la plupart des infrastructures de PME.
loki:
# relever la version 3.x courante et l'epingler
image: grafana/loki:3.x.y
restart: unless-stopped
command: -config.file=/etc/loki/loki.yml
volumes:
- ./loki:/etc/loki:ro
- ./loki-regles:/loki/rules:ro
- loki_data:/loki
ports:
- "127.0.0.1:3100:3100"
auth_enabled: false
server:
http_listen_port: 3100
common:
instance_addr: 127.0.0.1
path_prefix: /loki
replication_factor: 1
ring:
kvstore:
store: inmemory
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
schema_config:
configs:
- from: 2026-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 90d
# protege Loki d'un emetteur emballe
ingestion_rate_mb: 8
ingestion_burst_size_mb: 16
compactor:
working_directory: /loki/compactor
# sans ces deux lignes, retention_period n'efface rien
retention_enabled: true
delete_request_store: filesystem
ruler:
alertmanager_url: http://alertmanager:9093
enable_api: true
C'est le piège classique de Loki : une durée de rétention déclarée dans les limites, mais un compacteur sans rétention activée. Les journaux s'accumulent alors indéfiniment, jusqu'au disque plein, alors que la configuration semble correcte.
Les agents des serveurs écrivent dans Loki : exposez-le derrière le proxy inverse, en TLS, et
protégez l'écriture. Loki n'a pas d'authentification propre en mode simple ; une authentification
de base sur le chemin /loki/api/v1/push, côté Nginx, suffit pour une infrastructure
interne.
04Collecter avec Grafana Alloy
Grafana Alloy est l'agent de collecte de Grafana. Il remplace Promtail, arrivé en fin de vie au début de 2026 : les tutoriels qui l'installent encore sont à éviter pour une installation neuve. Alloy lit le journal systemd, des fichiers, ou reçoit du syslog, et sait aussi collecter des métriques, ce qui permet à terme de n'avoir qu'un agent par serveur.
# depot Grafana : suivre la procedure officielle, puis apt install alloy # l'agent doit pouvoir lire le journal systemd et /var/log usermod -aG adm,systemd-journal alloy
// destination : le Loki central
loki.write "central" {
endpoint {
url = "https://loki.exemple.fr/loki/api/v1/push"
basic_auth {
username = "alloy"
password = sys.env("LOKI_PASSWORD")
}
}
}
// le journal systemd, avec le nom du service en etiquette
loki.relabel "journal" {
forward_to = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
rule {
source_labels = ["__journal_priority_keyword"]
target_label = "niveau"
}
}
loki.source.journal "systeme" {
forward_to = [loki.write.central.receiver]
relabel_rules = loki.relabel.journal.rules
max_age = "12h"
labels = {job = "journal", host = constants.hostname}
}
// des fichiers classiques, ici les journaux Nginx
local.file_match "nginx" {
path_targets = [{
__path__ = "/var/log/nginx/*.log",
job = "nginx",
host = constants.hostname,
}]
}
loki.source.file "nginx" {
targets = local.file_match.nginx.targets
forward_to = [loki.write.central.receiver]
}
echo 'LOKI_PASSWORD=...' >> /etc/default/alloy
systemctl enable --now alloy
journalctl -u alloy -n 30 --no-pager
# interface de diagnostic locale : etat de chaque composant
curl -s http://127.0.0.1:12345/-/ready
Commutateurs, pare-feu, onduleurs et NAS savent rarement faire autre chose qu'envoyer du syslog. Le composant loki.source.syslog d'Alloy les reçoit directement ; vérifiez seulement le format, RFC 5424 par défaut, alors que beaucoup d'équipements émettent encore l'ancien RFC 3164. Installez cette réception sur un Alloy du réseau d'administration, jamais sur une interface publique : syslog en UDP n'a ni authentification ni chiffrement.
05Les étiquettes, piège numéro un
Chaque combinaison distincte d'étiquettes crée un flux séparé dans Loki. Quelques centaines de flux, c'est parfait ; des centaines de milliers, et Loki s'effondre. Toute valeur qui varie beaucoup va donc dans le texte de la ligne, jamais dans une étiquette.
| Bonne étiquette | Mauvaise étiquette |
|---|---|
host, le nom de la machine | L'adresse IP du client qui se connecte |
unit, le service systemd | L'identifiant de session ou de requête |
job, la source de collecte | L'URL complète demandée |
niveau, la gravité | Le nom de l'utilisateur |
Ce que l'on perd en ne mettant pas l'adresse IP en étiquette, on le retrouve à la requête : un filtre sur le texte, ou une extraction à la volée, retrouve tous les accès d'une adresse donnée. C'est plus lent qu'un index, et c'est le compromis assumé de Loki.
06Chercher dans les journaux
Loki s'interroge en LogQL, depuis l'onglet Explore de Grafana. La syntaxe ressemble volontairement à celle de Prometheus : on sélectionne des flux par étiquettes, puis on filtre et on transforme.
# toutes les erreurs d'un noeud, tous services confondus {host="pve-01", niveau=~"err|crit|alert|emerg"} # ce que corosync a raconte pendant la perte de quorum {unit="corosync.service"} |= "link" # les reponses 5xx de Nginx, sur toutes les machines {job="nginx"} |~ "\" 5[0-9]{2} " # echecs SSH par machine, comptes par tranche de 5 minutes sum by (host) (count_over_time({unit="ssh.service"} |= "Failed password" [5m])) # ce qui s'est passe partout entre 3 h 10 et 3 h 15 : regler la plage dans Grafana {job="journal"} != "systemd-timesyncd"
Dans un tableau de bord Grafana, ajoutez sous les courbes d'un hôte un panneau de journaux filtré sur la même machine, et liez la plage de temps. Le jour de l'incident, on sélectionne le pic sur la courbe et les lignes de journal de ce moment-là s'affichent juste en dessous. C'est la raison principale de notre préférence pour Loki.
07Alerter sur un journal
Le composant ruler de Loki évalue des règles au format Prometheus, en LogQL, et envoie les alertes au même Alertmanager que vos métriques. Elles suivent donc les mêmes routes, vers les mêmes canaux, y compris ntfy.
# sans authentification, Loki range les regles du locataire unique sous fake/
groups:
- name: journaux
rules:
- alert: ForceBruteSSH
expr: |
sum by (host) (count_over_time({unit="ssh.service"} |= "Failed password" [5m])) > 30
for: 0m
labels: {severity: alerte}
annotations:
summary: "Plus de 30 echecs SSH en 5 minutes sur {{ $labels.host }}"
- alert: ErreurDisqueNoyau
expr: |
sum by (host) (count_over_time({job="journal"} |~ "I/O error|Medium Error|UNC" [10m])) > 0
labels: {severity: critique}
annotations:
summary: "Erreurs d'entree-sortie dans le noyau de {{ $labels.host }}"
- alert: JournauxMuets
expr: |
sum by (host) (count_over_time({job="journal"}[15m])) == 0
for: 15m
labels: {severity: alerte}
annotations:
summary: "{{ $labels.host }} n'envoie plus de journaux"
Une requête qui compte des lignes ne renvoie rien pour une machine disparue : il n'y a plus de série à comparer à zéro. Pour détecter un agent Alloy arrêté, comptez plutôt sur la supervision de l'agent lui-même, par exemple son service systemd dans Zabbix ou ses métriques internes dans Prometheus.
08Combien de temps garder
Les journaux contiennent des adresses IP, des identifiants, parfois des adresses de messagerie : ce sont des données personnelles au sens du RGPD. Leur durée de conservation doit donc être définie, justifiée et respectée, ce qui exclut le « on garde tout, on verra ». Pour la journalisation de sécurité, la CNIL recommande en règle générale une durée de six mois à un an. Certaines activités ont leurs propres obligations : un hébergeur, par exemple, conserve les données d'identification de ceux qui publient un contenu.
| Journaux | Durée que nous retenons | Raison |
|---|---|---|
| Système et services, tous serveurs | 90 jours | Diagnostic, comparaison avec le trimestre |
| Authentifications et accès d'administration | 1 an | Enquête après incident de sécurité |
| Journaux applicatifs verbeux | 14 à 30 jours | Volume, faible valeur au-delà |
| Accès web des sites hébergés | Selon vos obligations d'hébergeur | À valider avec votre conseil |
Dans Loki, la durée se règle globalement par retention_period, et par flux grâce
à retention_stream dans les limites, qui permet par exemple de garder un an
{unit="ssh.service"} et trente jours le reste. Documentez ces durées dans votre
registre des traitements : c'est une ligne, et c'est la première question posée lors d'un
contrôle.
Les durées ci-dessus sont nos choix d'exploitant pour des infrastructures courantes. Votre secteur, vos contrats et votre statut d'hébergeur peuvent imposer d'autres durées : faites-les valider par votre délégué à la protection des données ou votre conseil.
Une supervision qui veille pendant que vous dormez
Nous concevons, installons et exploitons des plateformes de supervision pour des PME, des hébergeurs et des collectivités : Zabbix, Prometheus et Grafana, ou plus léger quand le besoin l'est. Reprise d'une supervision existante, réglage des alertes qui sonnent pour rien, astreinte : nous intervenons au forfait comme au long cours.