Chapitre 1012 minIntermédiaire
Les journaux sous Linux : journalctl, rsyslog et logrotate
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- filtrer le journal de systemd par service, période, priorité ou motif ;
- maîtriser la place prise par les journaux et faire tourner les fichiers ;
- retrouver l'historique des connexions sous Debian 13 ;
- envoyer les journaux d'un serveur vers un serveur central en TLS.
3 exercices corrigés
Les journaux (logs) sont les messages que le noyau, les services et les programmes écrivent pour dire ce qu'ils font : démarrages, erreurs, connexions, refus. Sur Debian 13, ils sont collectés par systemd-journald et se lisent avec journalctl ; certains services écrivent aussi leurs propres fichiers dans /var/log. Ce chapitre montre comment filtrer les journaux pour trouver vite une information, conserver et faire tourner les fichiers de journaux, retrouver l'historique des connexions et envoyer les journaux vers un serveur central.
Le journal de systemd
systemd-journald reçoit tout : les messages du noyau, la sortie de chaque service, les messages syslog des programmes. Il les range dans des fichiers binaires indexés de /var/log/journal/, conservés d'un démarrage à l'autre. Depuis Debian 12, rsyslog n'est plus installé par défaut : les fichiers texte historiques /var/log/syslog et /var/log/auth.log n'existent pas sur une installation neuve, et tout passe par journalctl.
Un utilisateur ordinaire ne voit que ses propres messages : les membres des groupes adm ou systemd-journal voient tout, sinon on utilise sudo.
| Commande | Ce qu'elle affiche |
|---|---|
journalctl | Tout le journal, du plus ancien au plus récent, dans less |
journalctl -r | Du plus récent au plus ancien |
journalctl -f | Les nouveaux messages en direct |
journalctl -u nginx | Les messages d'un service |
journalctl -u ssh -u nginx | Plusieurs services mélangés, dans l'ordre chronologique |
journalctl -b | Depuis le dernier démarrage ; -b -1 le démarrage précédent ; --list-boots la liste |
journalctl -k | Les messages du noyau (disques, cartes réseau, AppArmor) |
journalctl -p err | Les messages de priorité err et plus graves |
journalctl --since "2026-11-04 08:00" --until "2026-11-04 09:00" | Une période ; --since "1 hour ago", --since today |
journalctl -g "Failed password" | Les messages qui contiennent un motif (--grep) |
journalctl _UID=1000 | Les messages d'un utilisateur |
journalctl -xeu nginx | La fin du journal d'un service, avec des explications : le réflexe après un échec de démarrage |
journalctl -o json-pretty -n 1 | Le dernier message avec tous ses champs |
Les priorités reprennent celles de syslog : emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), debug (7). -p warning affiche les niveaux 0 à 4.
Les options se combinent : « les erreurs de nginx depuis ce matin » s'écrit journalctl -u nginx -p err --since today.
La place prise par le journal
journalctl --disk-usage affiche la place occupée. Par défaut, le journal s'arrête à 10 % de la taille du système de fichiers (avec un plafond de 4 Gio) et efface ses messages les plus anciens au-delà. Pour fixer une politique, on crée une surcharge :
# /etc/systemd/journald.conf.d/sorbier.conf
[Journal]
SystemMaxUse=1G
MaxRetentionSec=3month
puis sudo systemctl restart systemd-journald. Pour libérer de la place tout de suite : sudo journalctl --vacuum-size=500M ou sudo journalctl --vacuum-time=4weeks.
Les fichiers de /var/log
Certains services écrivent encore leurs propres fichiers texte, en plus ou à la place du journal :
| Fichier ou dossier | Contenu |
|---|---|
/var/log/nginx/access.log, error.log | Chaque requête reçue par le serveur web, et ses erreurs |
/var/log/apt/history.log, term.log | Les commandes apt lancées et leur sortie |
/var/log/dpkg.log | Chaque paquet installé, mis à jour ou retiré |
/var/log/unattended-upgrades/ | Les mises à jour automatiques (chapitre 8) |
/var/log/fail2ban.log | Les adresses bannies par Fail2ban |
/var/log/installer/ | Le déroulement de l'installation |
Ces fichiers appartiennent en général à root et au groupe adm, en 640 : ajouter un technicien au groupe adm lui donne la lecture des journaux sans aucun droit d'administration.
logrotate : faire tourner les fichiers de journaux
Un fichier de journal grossit sans fin. logrotate, lancé chaque jour par logrotate.timer, le fait tourner : il renomme access.log en access.log.1, compresse les anciens, en garde un nombre fixé et supprime les plus vieux. Chaque paquet dépose sa règle dans /etc/logrotate.d/ ; celle de nginx garde 14 jours de journaux.
Sur srv-journaux, les journaux reçus des autres machines sont rangés dans /srv/journaux/distant/<machine>/. La règle qui les garde 90 jours :
# /etc/logrotate.d/journaux-distants
/srv/journaux/distant/*/*.log {
daily
rotate 90
dateext
compress
delaycompress
missingok
notifempty
create 0640 root adm
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
| Directive | Effet |
|---|---|
daily, rotate 90 | Une rotation par jour, 90 fichiers conservés |
dateext | Les anciens fichiers portent la date (web.log-20261104) au lieu d'un numéro |
compress, delaycompress | Compresser les anciens, sauf le plus récent (encore ouvert par certains programmes) |
missingok, notifempty | Pas d'erreur si le fichier manque, pas de rotation s'il est vide |
create 0640 root adm | Recréer un fichier vide avec ces droits |
postrotate … endscript | Commande lancée après la rotation : ici, prévenir rsyslog d'ouvrir les nouveaux fichiers |
sudo logrotate -d /etc/logrotate.d/journaux-distants simule la rotation et affiche ce qui serait fait ; -f la force immédiatement.
Qui s'est connecté ?
Debian 13 a retiré les commandes historiques last, lastb et lastlog, dont le format de fichier ne passait pas l'année 2038. Elles sont remplacées par :
| Besoin | Debian 13 | Ancien équivalent |
|---|---|---|
| Historique des sessions et redémarrages | wtmpdb last | last |
| Dernière connexion de chaque compte | lastlog2 | lastlog |
| Échecs de connexion | sudo lslogins --failed, ou journalctl -u ssh -g "Failed" | lastb |
| Sessions ouvertes maintenant | who, w |
Si la commande manque, installe wtmpdb et libpam-wtmpdb (respectivement lastlog2 et libpam-lastlog2) : le module PAM est nécessaire pour que les nouvelles sessions soient enregistrées.
Centraliser les journaux
Un journal resté sur la machine a deux défauts : il faut se connecter à chaque serveur pour le lire, et un attaquant qui prend la main sur le serveur peut l'effacer. Chez Sorbier, les serveurs envoient leurs journaux à srv-journaux (192.168.10.180) en syslog chiffré par TLS sur le port TCP 6514, comme le prévoit la matrice des flux du cours Cybersécurité des infrastructures ; les équipements réseau, eux, envoient les leurs en UDP 514 (cours Routage et commutation).
Côté srv-web, l'envoi se fait avec rsyslog, installé pour l'occasion avec son module TLS :
sudo apt install rsyslog rsyslog-gnutls
Une fois installé, rsyslog reçoit les messages du journal et recrée les fichiers texte classiques (/var/log/syslog, /var/log/auth.log). On ajoute le transfert :
# /etc/rsyslog.d/90-srv-journaux.conf
global(DefaultNetstreamDriverCAFile="/usr/local/share/ca-certificates/sorbier-ca.crt")
action(type="omfwd" target="192.168.10.180" port="6514" protocol="tcp"
StreamDriver="gtls" StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeers="srv-journaux.ad.sorbier.example"
queue.type="LinkedList" queue.filename="vers-journaux"
action.resumeRetryCount="-1")
StreamDriverMode="1" impose TLS ; x509/name et PermittedPeers vérifient que le certificat présenté est bien celui de srv-journaux, signé par l'autorité de l'entreprise ; la file d'attente sur disque (queue.filename) garde les messages si srv-journaux redémarre, et resumeRetryCount="-1" réessaie sans fin. On vérifie la syntaxe avec sudo rsyslogd -N1, puis sudo systemctl restart rsyslog, et logger "test depuis srv-web" envoie un message de test.
La réception côté srv-journaux, la corrélation des événements et la détection d'attaques à partir des journaux relèvent du SIEM : c'est le rôle de Wazuh, dont l'agent sait aussi lire le journal de systemd et l'envoyer chiffré à son serveur. La supervision des métriques (charge, disque, services) est traitée dans le cours Supervision.
Exercices
Exercice 1 sur 3 Écrire la bonne commande journalctl Réussi À revoir
- Les messages du service SSH depuis 8 h ce matin.
- Les erreurs et plus graves depuis le dernier démarrage.
- Les messages du noyau qui mentionnent AppArmor.
- Les messages de nginx pendant le démarrage précédent, qui a planté.
- Suivre en direct les messages de l'application
suivi-api.
Voir la réponseMasquer la réponse de l'exercice 1
journalctl -u ssh --since "08:00"(ou--since "2026-11-04 08:00").journalctl -b -p errjournalctl -k -g apparmorjournalctl -b -1 -u nginx(--list-bootspour vérifier que ce démarrage est bien conservé).journalctl -u suivi-api -f
Tu avais trouvé ?
Exercice 2 sur 3 Analyser des échecs de connexion (type E7) Réussi À revoir
Voici un extrait de journalctl -u ssh sur srv-web :
nov. 04 03:12:40 srv-web sshd-session[5120]: Invalid user admin from 192.168.10.209 port 50112
nov. 04 03:12:42 srv-web sshd-session[5120]: Connection closed by invalid user admin 192.168.10.209 port 50112 [preauth]
nov. 04 03:12:44 srv-web sshd-session[5122]: Invalid user test from 192.168.10.209 port 50114
nov. 04 03:12:46 srv-web sshd-session[5122]: Connection closed by invalid user test 192.168.10.209 port 50114 [preauth]
nov. 04 03:12:48 srv-web sshd-session[5124]: User root from 192.168.10.209 not allowed because none of user's groups are listed in AllowGroups
nov. 04 03:12:49 srv-web sshd-session[5124]: Connection closed by invalid user root 192.168.10.209 port 50116 [preauth]
nov. 04 03:13:02 srv-web sshd-session[5126]: Connection closed by authenticating user clambert 192.168.10.209 port 50118 [preauth]
- Que s'est-il passé ? D'où viennent les tentatives ?
- Pourquoi aucune tentative n'a-t-elle réussi ?
- Quelles actions proposes-tu ?
Voir la réponseMasquer la réponse de l'exercice 2
- En pleine nuit, une machine a essayé de se connecter en SSH avec plusieurs comptes (
admin,test,root, puisclambert) en quelques secondes : c'est une énumération de comptes, typique d'un outil automatique. Elle vient de192.168.10.209, le poste d'administration du VLAN 99 : soit il est compromis, soit quelqu'un l'utilise sans autorisation. C'est grave, car ce poste a accès à tous les serveurs. adminettestn'existent pas (Invalid user).rootest refusé d'emblée parAllowGroups(il n'est pas dansadmins-ssh), etPermitRootLogin nol'aurait de toute façon bloqué :sshdle traite alors comme un compte invalide. Pourclambert, la connexion se ferme pendant l'authentification ([preauth]) sans « Accepted » : le serveur n'accepte que les clés, et l'outil n'avait pas la bonne clé privée. L'authentification par clé,AllowGroupset le refus derootont joué leur rôle.- Isoler le poste d'administration du réseau et l'analyser (procédure de réponse à incident) ; vérifier sur tous les serveurs s'il y a eu des connexions réussies depuis ce poste (
journalctl -u ssh -g Accepted,wtmpdb last) ; changer la phrase de passe et la clé de Chloé Lambert si sa clé privée se trouve sur ce poste ; vérifier que ces journaux arrivent bien sursrv-journauxet qu'une alerte du SIEM se déclenche sur ce type de série d'échecs.
Tu avais trouvé ?
Exercice 3 sur 3 Une règle logrotate Réussi À revoir
Écris une règle logrotate pour /var/log/suivi/api.log : rotation chaque semaine, 12 semaines conservées, compression, aucune erreur si le fichier manque, nouveau fichier 0640 pour suivi:adm. Comment la tester sans attendre une semaine ?
Voir la réponseMasquer la réponse de l'exercice 3
# /etc/logrotate.d/suivi-api
/var/log/suivi/api.log {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
create 0640 suivi adm
}
sudo logrotate -d /etc/logrotate.d/suivi-api simule et affiche ce qui serait fait ; sudo logrotate -f /etc/logrotate.d/suivi-api force une rotation réelle pour vérifier le résultat (ls -l /var/log/suivi/). Si l'application garde le fichier ouvert, ajoute copytruncate ou un bloc postrotate qui lui demande de rouvrir son journal (par exemple systemctl reload suivi-api, si elle le gère).
Tu avais trouvé ?