Aller au contenu
L'heure et sa synchronisation

L'heure et sa synchronisation

À la fin, vous saurez

  • Expliquer les conséquences d'une horloge fausse sur TLS, les jetons, les journaux et les tâches planifiées
  • Distinguer horloge matérielle et horloge système, et choisir entre horloge réelle et horloge monotone pour mesurer une durée
  • Lire l'état de l'heure d'une machine avec timedatectl et régler son fuseau horaire
  • Identifier le démon de synchronisation actif sur Ubuntu 24.04 et Debian 13 et le configurer
  • Mettre en place un serveur de temps chrony pour un réseau privé et y raccorder les autres machines, avec des sources authentifiées par NTS
  • Interpréter chronyc tracking, sources et sourcestats pour diagnostiquer une synchronisation défaillante
  • Surveiller le décalage d'horloge d'un parc et justifier un seuil d'alerte

Prérequis

Testé avec chrony-debian 4.6.1 chrony-ubuntu 4.5 debian 13 systemd-debian 257 systemd-ubuntu 255 tzdata 2026c ubuntu 24.04 , vérifié le 7 octobre 2026

Pourquoi

Un mardi matin, le service informatique de la mairie vous transmet une réclamation : un agent affirme avoir traité un signalement de nid-de-poule « vers 9 h 10 », mais l'historique de Signalements indique 9 h 13, et le journal de sig-app-2 contient la requête à 9 h 12 min 58 s. Trois horodatages, trois heures. En cherchant, vous découvrez que sig-app-2 retarde de deux minutes et demie sur sig-app-1, et que le service de synchronisation de l'heure y est arrêté depuis une intervention de Camille, l'an dernier, dont personne ne connaît le motif.

L'anecdote paraît bénigne. Elle ne l'est pas, parce que presque tout ce qui fait la sécurité et l'exploitation d'un serveur repose sur l'heure :

  • TLS : un certificat porte une date de début (notBefore) et une date de fin (notAfter) de validité. Une machine en retard refuse un certificat tout juste émis (« pas encore valide ») ; une machine en avance considère comme expiré un certificat encore bon. Les certificats à durée de vie courte, de plus en plus répandus, réduisent la marge.
  • Les jetons : un JWT émis par le fournisseur d'identité OpenID Connect de la mairie porte des dates d'émission (iat), de début (nbf) et d'expiration (exp). Si sig-app-2 retarde, il rejette des jetons « émis dans le futur » ; s'il avance, il les juge expirés. Les bibliothèques prévoient une tolérance (leeway) de quelques secondes, pas de quelques minutes.
  • Kerberos, dans les environnements Active Directory des collectivités, refuse par défaut tout écart supérieur à cinq minutes entre client et serveur.
  • Les journaux : pour reconstituer un incident à partir de sig-app-1, sig-app-2, sig-outils et de la base managée, il faut que leurs horodatages soient comparables. L'ANSSI, dans ses recommandations sur l'architecture d'un système de journalisation, en fait une règle (R5) : synchroniser toutes les machines sur des sources de temps cohérentes entre elles, avec une précision d'au moins la seconde.
  • L'ordre des événements : une application qui compare deux dates produites par deux machines (« ce signalement a-t-il été modifié après sa clôture ? ») donne des réponses fausses si les horloges divergent.
  • Les tâches planifiées et les sauvegardes : l'export nocturne pour la mairie, la rotation des journaux, l'expiration des sauvegardes. Une horloge qui saute en arrière peut exécuter deux fois une tâche ; une horloge qui saute en avant peut en sauter une.
  • La traçabilité : en cas de litige, ou de demande d'une autorité, un journal dont l'horodatage est faux perd sa valeur de preuve.

Cette leçon explique comment une machine Linux tient l'heure, comment elle la corrige, et comment organiser la synchronisation des trois serveurs de Signalements pour qu'ils restent d'accord entre eux et avec le temps légal.

Les concepts

Deux horloges dans la machine

Un ordinateur possède deux horloges, qu'il faut distinguer.

L'horloge matérielle, ou RTC (Real-Time Clock, horloge temps réel) : un petit circuit alimenté par une pile, qui continue de compter quand la machine est éteinte. Elle ne stocke qu'une date et une heure, à la seconde près, sans fuseau horaire. Elle dérive : quelques secondes par jour pour un quartz ordinaire, davantage s'il fait chaud.

L'horloge système : un compteur tenu par le noyau en mémoire. Au démarrage, il est initialisé à partir de la RTC, puis il avance au rythme d'une source matérielle de cadence (le compteur du processeur, ou, dans une machine virtuelle, une horloge fournie par l'hyperviseur). C'est elle que lisent tous les programmes, et c'est elle que l'on synchronise.

Sur une instance Scaleway, comme sur toute machine virtuelle KVM, la RTC est émulée par l'hyperviseur, et la cadence vient généralement de kvm-clock, une horloge paravirtualisée que l'hôte partage avec l'invité. Cela n'exempte pas de synchronisation : l'horloge de l'invité dérive aussi, et elle peut faire un bond après une migration à chaud ou la restauration d'un instantané.

Les horloges que voit un programme

Le noyau ne présente pas une seule heure, mais plusieurs horloges, que l'on lit avec l'appel système clock_gettime(). Deux suffisent à comprendre l'essentiel :

HorlogeCe qu'elle comptePeut sauter ?Usage
CLOCK_REALTIMEles secondes depuis le 1er janvier 1970 à 0 h UTC (l'« époque Unix »)oui : quand on la règle, ou quand la synchronisation la corrige d'un coupdater un événement
CLOCK_MONOTONICles secondes depuis un point arbitraire (sous Linux, le démarrage), hors mise en veillenon : jamais de saut, seulement de légères variations de vitessemesurer une durée

La page clock_gettime(2) précise que CLOCK_MONOTONIC n'est pas affectée par les sauts de l'heure système, mais l'est par les ajustements de fréquence. Il existe aussi CLOCK_BOOTTIME (comme la monotone, mais en comptant le temps de veille), CLOCK_MONOTONIC_RAW (sans aucun ajustement) et CLOCK_TAI (le temps atomique international, sans secondes intercalaires : sous Linux, elle vaut l'heure système plus le décalage TAI-UTC que le démon de synchronisation communique au noyau, 37 secondes aujourd'hui, et se confond avec l'heure système tant que personne ne l'a fourni).

La conséquence pour le code est directe : une durée se mesure avec l'horloge monotone. Un délai d'expiration calculé par fin = time.time() + 30 en Python devient faux si l'horloge réelle est corrigée de 40 secondes en arrière pendant l'attente ; time.monotonic() ne l'est jamais. Les bons serveurs (Gunicorn pour ses délais de workers, systemd pour ses minuteries relatives) utilisent l'horloge monotone pour cette raison. Quand vous relisez le code de Signalements, une soustraction de deux datetime.now() pour mesurer un temps de réponse est un défaut, pas une question de style.

UTC, fuseaux horaires et tzdata

L'horloge système compte en UTC (temps universel coordonné), sans fuseau. Le fuseau n'intervient qu'à l'affichage : la bibliothèque C convertit l'heure UTC en heure locale grâce à la base des fuseaux horaires (tz database, paquet tzdata), qui décrit pour chaque région son décalage et l'historique de ses changements d'heure. Le fuseau de la machine est désigné par le lien symbolique /etc/localtime, qui pointe vers un fichier de /usr/share/zoneinfo/, par exemple Europe/Paris. Un processus peut afficher un autre fuseau grâce à la variable d'environnement TZ.

Sur un serveur, le choix recommandé est simple : le fuseau de la machine en UTC, et la conversion en heure de Paris faite par l'application ou l'outil d'affichage. Trois raisons :

  1. Pas de changement d'heure. En heure de Paris, la nuit du dernier dimanche d'octobre contient deux fois l'intervalle de 2 h à 3 h, et celle du dernier dimanche de mars ne le contient pas du tout. Un journal en heure locale devient ambigu une heure par an ; une tâche planifiée à 2 h 30 s'exécute deux fois ou jamais (la leçon 10 y revient).
  2. La corrélation. La base managée sig-db, les journaux de Scaleway, les outils de supervision raisonnent en UTC. La recommandation R4 de l'ANSSI demande d'homogénéiser les paramètres d'horodatage, fuseau compris, et suggère UTC quand on n'est pas certain que tous les systèmes gèrent correctement les changements d'heure.
  3. Les équipes réparties. Une alerte horodatée « 03:12Z » se lit de la même façon partout.

Le fuseau de l'utilisateur final, lui, reste Europe/Paris : c'est l'interface de Signalements qui affiche « 9 h 13 » à l'agent de la mairie, en convertissant une date stockée en UTC (dans PostgreSQL, une colonne timestamptz).

La RTC, enfin, doit aussi être en UTC. Garder la RTC à l'heure locale est un héritage des machines en double démarrage avec Windows ; timedatectl affiche un long avertissement quand c'est le cas.

NTP, le protocole de synchronisation

NTP (Network Time Protocol), dans sa version 4 décrite par la RFC 5905, permet à une machine de demander l'heure à des serveurs et d'en déduire l'erreur de sa propre horloge. Il fonctionne sur UDP, port 123.

La hiérarchie des strates. Les sources de temps forment un arbre. Au sommet, la strate 0 : des horloges de référence (horloge atomique, récepteur GPS, signal radio) qui ne parlent pas NTP. Un serveur directement relié à l'une d'elles est en strate 1. Un serveur synchronisé sur un serveur de strate 1 est en strate 2, et ainsi de suite. La strate 16 signifie « non synchronisé ». La strate mesure une distance dans l'arbre, pas une qualité : un serveur de strate 3 proche et stable vaut mieux qu'un serveur de strate 1 lointain et surchargé.

En France, le temps légal est établi par l'Observatoire de Paris (décret n° 2017-292 du 6 mars 2017), dont le département LNE-SYRTE produit l'échelle de temps UTC(OP). Il publie un serveur de strate 1, ntp-p1.obspm.fr, réservé à la synchronisation de serveurs de strate 2 importants, et un serveur de strate 2 en accès libre, ntp.obspm.fr.

La mesure. Le client envoie une requête datée T1 ; le serveur la reçoit à T2 et répond à T3 ; le client reçoit la réponse à T4. Le client en tire deux grandeurs :

délai aller-retour   d = (T4 - T1) - (T3 - T2)
décalage (offset)    θ = ((T2 - T1) + (T3 - T4)) / 2

Le calcul du décalage suppose que l'aller et le retour prennent le même temps. Une asymétrie du réseau se traduit donc en erreur, au plus de la moitié du délai aller-retour. C'est l'origine de la notion de distance à la racine (root distance) : la moitié du délai cumulé jusqu'à la strate 1, plus la dispersion accumulée en chemin. Elle borne l'erreur possible d'une source.

Plusieurs sources, et le vote. Un client complet interroge plusieurs serveurs, écarte ceux dont l'intervalle de confiance ne recoupe pas celui de la majorité (les falsetickers, « horloges menteuses »), et combine les autres. La RFC 8633, qui rassemble les bonnes pratiques NTP, recommande au moins quatre sources indépendantes et diverses : avec deux sources en désaccord, impossible de savoir laquelle a raison ; avec trois, une panne ramène au cas précédent.

SNTP. Une version simplifiée, Simple NTP, se contente d'interroger un serveur et d'appliquer sa réponse, sans filtrage ni vote. C'est ce que fait systemd-timesyncd.

Ajuster progressivement ou sauter

Corriger une horloge fausse peut se faire de deux façons :

  • le saut (step) : l'heure est réglée d'un coup à la bonne valeur. C'est immédiat, mais CLOCK_REALTIME fait un bond, éventuellement en arrière : des fichiers peuvent recevoir une date antérieure à celle de leur prédécesseur, un journal peut paraître remonter le temps ;
  • l'ajustement progressif (slew) : le noyau accélère ou ralentit légèrement l'horloge jusqu'à rattraper l'écart. Le temps reste continu et croissant, mais la correction est lente.

Les démons combinent les deux : un saut éventuel au démarrage, quand l'écart peut être grand et que peu de programmes tournent, puis uniquement des ajustements progressifs. Un démon NTP apprend aussi la dérive de l'horloge locale, exprimée en ppm (parties par million : 1 ppm, c'est 86,4 millisecondes par jour), et la compense en permanence. C'est pour cela qu'une machine bien synchronisée garde l'heure correcte pendant des heures, même si ses sources deviennent injoignables.

NTS, l'authentification

NTP, à l'origine, n'authentifie pas ses réponses : n'importe qui sur le chemin peut répondre à la place du serveur. NTS (Network Time Security, RFC 8915) corrige cela. Le client ouvre d'abord une session TLS vers le serveur sur le port TCP 4460 (l'échange de clés, NTS-KE), vérifie son certificat comme le ferait un navigateur, et reçoit des clés et des cookies (de petits jetons opaques que le serveur saura déchiffrer). Les échanges NTP suivants, toujours sur UDP 123, sont alors authentifiés par ces clés, sans que le serveur ait à garder d'état pour chaque client.

Un détail a des conséquences pratiques : TLS a besoin d'une heure à peu près juste pour vérifier la validité d'un certificat. Une machine dont l'horloge est très fausse au démarrage peut donc être incapable d'établir une session NTS. On y revient dans les pièges.

Qui synchronise quoi, selon la distribution

DistributionDémon par défautRemarques
Ubuntu 24.04 LTSsystemd-timesyncdclient SNTP ; serveur par défaut ntp.ubuntu.com
Ubuntu 25.10 et suivanteschronyNTS activé par défaut vers les serveurs d'Ubuntu, pour les nouvelles installations
Debian 13systemd-timesyncdpaquet de priorité standard ; serveurs par défaut 0.debian.pool.ntp.org à 3.debian.pool.ntp.org
RHEL, AlmaLinux, Rockychronydepuis RHEL 8

Ces valeurs par défaut sont fixées à la compilation de systemd : le fichier debian/rules du paquet systemd définit ntp.ubuntu.com pour Ubuntu et les quatre serveurs du pool Debian sinon. Une image cloud peut en décider autrement (les images officielles de Debian ajoutent par exemple le service de temps d'AWS sur EC2) : sur une instance héritée, constatez le démon actif plutôt que de le supposer.

systemd-timesyncd suffit sur un poste de travail. La FAQ de chrony résume ses limites : il n'interroge qu'un serveur à la fois, ne détecte pas les falsetickers, ne peut pas servir l'heure à d'autres machines, et ne prend pas en charge NTS dans les versions de systemd livrées par Ubuntu 24.04 et Debian 13. Pour un parc de serveurs qui doit rester cohérent, chrony est le choix raisonnable, et c'est celui que fait cette leçon.

En pratique

Constater l'état de l'heure

Sur chaque machine, commencez par timedatectl, qui interroge le service systemd-timedated :

$ timedatectl status

La sortie ressemble à ceci sur sig-app-2 :

               Local time: Tue 2026-10-06 07:12:41 UTC
           Universal time: Tue 2026-10-06 07:12:41 UTC
                 RTC time: Tue 2026-10-06 07:12:39
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: no
              NTP service: inactive
          RTC in local TZ: no

Ligne par ligne :

  • Local time et Universal time : l'heure système, dans le fuseau de la machine et en UTC. Identiques ici, puisque le fuseau est UTC.
  • RTC time : l'heure de l'horloge matérielle, sans fuseau. Un écart de quelques secondes avec l'heure système est normal sur une machine virtuelle.
  • Time zone : le fuseau, son abréviation et son décalage actuel.
  • System clock synchronized : yes si le noyau considère l'horloge comme disciplinée par un démon. Le code de timedated montre ce que cela veut dire exactement : l'erreur maximale estimée que tient le noyau est inférieure à 16 secondes. C'est un indicateur grossier, pas une garantie de précision à la milliseconde.
  • NTP service : active si l'un des services de synchronisation connus de systemd tourne (systemd-timesyncd, ou chrony, qui se déclare dans /usr/lib/systemd/ntp-units.d/).
  • RTC in local TZ : no, la RTC est en UTC, c'est ce qu'il faut.

no et inactive sur sig-app-2 : l'énigme de la réclamation est résolue. Ensuite, regardez quel démon est installé et ce qu'il raconte :

$ systemctl status systemd-timesyncd chrony --no-pager
$ journalctl -u systemd-timesyncd -n 20 --no-pager

Avec systemd-timesyncd actif, timedatectl sait aussi afficher le détail de sa dernière mesure :

$ timedatectl timesync-status

Sortie typique, d'après le format défini dans timedatectl.c :

       Server: 185.125.190.56 (ntp.ubuntu.com)
Poll interval: 34min 8s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C035676C
    Precision: 1us (-25)
Root distance: 1.144ms (max: 5s)
       Offset: -1.208ms
        Delay: 18.420ms
       Jitter: 2.117ms
 Packet count: 61
    Frequency: -3.884ppm

On y retrouve les notions de la section précédente : le serveur choisi, l'intervalle d'interrogation (qui s'allonge de 32 secondes à 34 minutes quand tout va bien), la strate, la distance à la racine et son maximum accepté (RootDistanceMaxSec=, 5 secondes par défaut), le décalage et le délai de la dernière mesure, et la dérive compensée. timedatectl show-timesync donne les mêmes informations sous forme de propriétés (SystemNTPServers=, FallbackNTPServers=, ServerName=...), plus commodes dans un script.

Régler le fuseau horaire

$ timedatectl list-timezones | grep -E '^(Europe/Paris|Etc/UTC)$'
$ sudo timedatectl set-timezone Etc/UTC
$ ls -l /etc/localtime

set-timezone remplace le lien /etc/localtime par un lien vers /usr/share/zoneinfo/Etc/UTC. Le changement est immédiat pour les nouveaux processus ; les services déjà lancés gardent souvent l'ancien fuseau en mémoire jusqu'à leur redémarrage. Si sig-outils avait été installé en Europe/Paris par Camille, notez-le dans la fiche du serveur avant de changer : les heures des tâches cron existantes vont se décaler d'une ou deux heures (la leçon 10 montre comment écrire un minuteur systemd dans un fuseau explicite).

Pour lire l'heure de Paris sans toucher au système :

$ TZ=Europe/Paris date
$ journalctl -u signalements --since "2026-10-06 07:00" --until "2026-10-06 07:20" --utc
$ date -u --iso-8601=seconds
$ date -d @1791270761 -u

TZ= ne change le fuseau que pour la commande qui suit. journalctl --utc affiche les dates en UTC quel que soit le fuseau de la machine, ce qui évite les erreurs quand on compare deux serveurs réglés différemment. --iso-8601=seconds produit un horodatage non ambigu, du type 2026-10-06T07:12:41+00:00, conforme au format de la RFC 3339 qu'utiliseront les journaux structurés de la leçon 12. -d @... convertit une date Unix, comme celles que l'on trouve dans les jetons JWT.

Note

Sur Ubuntu 24.04 comme sur Debian 13, les anciens noms de fuseaux (US/Eastern, et les variantes posix/ et right/) ont été déplacés dans le paquet tzdata-legacy. Europe/Paris et Etc/UTC restent dans tzdata. Un script ancien qui écrit TZ=right/UTC échoue en silence sans ce paquet : la bibliothèque C retombe sur UTC sans prévenir.

L'architecture retenue pour Signalements

Plutôt que de laisser chaque machine interroger Internet de son côté, on applique la recommandation R5 de l'ANSSI : des sources internes cohérentes, elles-mêmes raccordées à plusieurs sources externes fiables.

    flowchart TB
  subgraph ext["Sources externes"]
    S1["NTP Scaleway<br/>zone fr-par-1"]
    S2["ntp.obspm.fr<br/>(NTS)"]
    S3["1.ntp.ubuntu.com<br/>(NTS)"]
  end
  subgraph pn["Réseau privé pn-signalements 172.16.8.0/22"]
    O["sig-outils 172.16.8.20<br/>chrony client et serveur"]
    A1["sig-app-1 172.16.8.11<br/>chrony client"]
    A2["sig-app-2 172.16.8.12<br/>chrony client"]
  end
  S1 --> O
  S2 --> O
  S3 --> O
  O --> A1
  O --> A2
  S1 -. secours .-> A1
  S1 -. secours .-> A2
  
  • sig-outils interroge des sources diverses : les serveurs NTP que Scaleway met à disposition dans chaque zone (proches, donc faible délai), le serveur de l'Observatoire de Paris et ceux d'Ubuntu, authentifiés par NTS. Il sert l'heure au réseau privé, et à lui seul.
  • sig-app-1 et sig-app-2 se synchronisent en priorité sur sig-outils, et gardent les serveurs de Scaleway en secours : si sig-outils tombe, les deux serveurs d'application restent cohérents entre eux, puisqu'ils suivent les mêmes sources.

La page « Scaleway network information » de la documentation Scaleway liste, pour chaque zone, les adresses des serveurs de cache DNS et NTP ; pour fr-par-1, ce sont 51.159.69.162 et 51.159.69.156 en IPv4. Prenez celles de la zone où se trouve chaque machine, et revérifiez-les sur cette page : elles ne sont pas annoncées par un nom DNS.

Pourquoi chrony aussi sur sig-app-1 et sig-app-2, alors que systemd-timesyncd saurait suivre sig-outils ? Parce qu'avec deux sources (sig-outils et Scaleway), timesyncd n'en suivrait qu'une, sans détecter qu'elle dérive ; et parce qu'un seul outil sur tout le parc veut dire une seule façon de diagnostiquer, ce que demande aussi l'ANSSI (« la même version du protocole sur l'ensemble du SI »).

Installer chrony sur sig-outils

$ sudo apt install chrony

Le paquet chrony déclare un conflit avec le paquet virtuel time-daemon, que fournit aussi systemd-timesyncd : APT propose donc de retirer systemd-timesyncd. C'est voulu, deux démons qui corrigent la même horloge se contrediraient. Le service chrony est activé et démarré par l'installation.

La configuration se répartit ainsi :

FichierContenu
/etc/chrony/chrony.confle fichier principal livré par le paquet
/etc/chrony/sources.d/*.sourcesuniquement des lignes server, pool ou peer ; rechargeables sans redémarrage
/etc/chrony/conf.d/*.conftoute autre directive, lue dans l'ordre alphabétique
/var/lib/chrony/chrony.driftla dérive apprise, conservée entre deux démarrages

Sur Debian 13, le chrony.conf livré contient notamment :

pool 2.debian.pool.ntp.org iburst
sourcedir /run/chrony-dhcp
sourcedir /etc/chrony/sources.d
driftfile /var/lib/chrony/chrony.drift
ntsdumpdir /var/lib/chrony
rtcsync
makestep 1 3
leapseclist /usr/share/zoneinfo/leap-seconds.list
confdir /etc/chrony/conf.d

On ne modifie pas ce fichier, pour que les mises à jour du paquet s'appliquent sans conflit ; on ajoute les siens. Les directives qui comptent :

  • pool 2.debian.pool.ntp.org iburst : des serveurs bénévoles du projet NTP Pool, résolus par DNS. iburst envoie une rafale de 4 à 8 requêtes au démarrage pour obtenir une première mesure en quelques secondes au lieu de quelques minutes.
  • sourcedir /run/chrony-dhcp : des sources apprises par DHCP, si le serveur DHCP en annonce.
  • rtcsync : demande au noyau de recopier l'heure système dans la RTC toutes les 11 minutes.
  • makestep 1 3 : sauter si l'écart dépasse 1 seconde, mais seulement lors des 3 premières mises à jour de l'horloge ; ensuite, toujours ajuster progressivement.
  • leapseclist : la liste des secondes intercalaires, lue dans tzdata.

Créez /etc/chrony/sources.d/signalements.sources :

# Serveurs NTP Scaleway de la zone fr-par-1 (doc « Scaleway network information »)
server 51.159.69.162 iburst
server 51.159.69.156 iburst
# Sources authentifiées par NTS (TCP 4460 puis UDP 123)
server ntp.obspm.fr iburst nts
server 1.ntp.ubuntu.com iburst nts
server 2.ntp.ubuntu.com iburst nts

Puis /etc/chrony/conf.d/signalements.conf :

# Servir l'heure au seul réseau privé de Signalements
allow 172.16.8.0/22
# Ne mettre l'horloge à jour que si au moins deux sources sont d'accord
minsources 2
# Journaliser toute correction supérieure à 0,1 s
logchange 0.1
  • server ... nts : la ligne désigne le serveur d'échange de clés NTS ; chrony vérifie son certificat avec les autorités de certification du système. Le serveur de l'Observatoire propose NTS depuis le 4 août 2026, d'après sa page de présentation.
  • allow 172.16.8.0/22 : par défaut, chrony ne sert l'heure à personne. Cette directive l'autorise pour le réseau privé, et pour lui seul.
  • minsources 2 : la valeur par défaut est 1. Avec 2, une source unique qui se mettrait à dire n'importe quoi ne suffit plus à déplacer l'horloge.
  • logchange 0.1 : chrony écrit un avertissement dans le journal au-delà de ce seuil (1 seconde par défaut).

Vous pouvez laisser la ligne pool 2.debian.pool.ntp.org du fichier principal : elle ajoute de la diversité, et chrony écartera ses serveurs s'ils sont faux. Rechargez les sources et redémarrez pour la directive allow :

$ sudo chronyc reload sources
$ sudo systemctl restart chrony

Côté pare-feu, la leçon 8 a écrit la politique de sig-outils, qui accepte déjà UDP 123 depuis sig-app-1 et sig-app-2 uniquement ; vérifiez aussi que la sortie vers TCP 4460 est permise si vous filtrez le trafic sortant. Dans le groupe de sécurité Scaleway, le port 123 n'a aucune raison d'être ouvert vers Internet.

Raccorder sig-app-1 et sig-app-2

Sur Ubuntu 24.04 :

$ sudo apt install chrony

Même effet : systemd-timesyncd est retiré. Sur Ubuntu 24.04, le chrony.conf livré place ses sources directement dans le fichier principal :

pool ntp.ubuntu.com        iburst maxsources 4
pool 0.ubuntu.pool.ntp.org iburst maxsources 1
pool 1.ubuntu.pool.ntp.org iburst maxsources 1
pool 2.ubuntu.pool.ntp.org iburst maxsources 2

Pour que sig-app-1 suive sig-outils en priorité sans interroger huit serveurs publics, commentez ces quatre lignes (c'est la seule modification du fichier principal ; gardez-en la trace dans le journal des changements, car une mise à jour du paquet vous proposera de fusionner). Depuis Ubuntu 25.10, ces lignes ont été déplacées dans /etc/chrony/sources.d/ubuntu-ntp-pools.sources, ce qui permettra de simplement remplacer ce fichier lors du passage à la prochaine version LTS.

Créez /etc/chrony/sources.d/signalements.sources :

server 172.16.8.20 iburst prefer
server 51.159.69.162 iburst
server 51.159.69.156 iburst

prefer donne la priorité à sig-outils quand plusieurs sources sont valides. Trois sources dont deux du même fournisseur, ce n'est pas l'idéal de la RFC 8633 ; c'est un compromis assumé : sig-outils porte la diversité, et les serveurs de Scaleway assurent la continuité. Puis :

$ sudo chronyc reload sources
$ sudo systemctl restart chrony
$ timedatectl status

Tip

Si vous préférez garder systemd-timesyncd sur une machine (un poste d'administration, une petite instance de test), la configuration se fait par un fichier /etc/systemd/timesyncd.conf.d/signalements.conf contenant une section [Time] avec NTP=172.16.8.20 et FallbackNTP=51.159.69.162 51.159.69.156, suivi de sudo systemctl restart systemd-timesyncd. N'éditez pas /etc/systemd/timesyncd.conf lui-même : les fichiers de surcharge survivent aux mises à jour.

Lire chronyc tracking

chronyc dialogue avec chronyd. tracking résume l'état de l'horloge locale :

$ chronyc tracking

La sortie ressemble à ceci sur sig-app-1, quelques heures après la mise en place (format de chronyc(1)) :

Reference ID    : AC100814 (172.16.8.20)
Stratum         : 3
Ref time (UTC)  : Tue Oct 06 09:41:17 2026
System time     : 0.000021740 seconds fast of NTP time
Last offset     : +0.000018352 seconds
RMS offset      : 0.000047113 seconds
Frequency       : 11.902 ppm slow
Residual freq   : +0.003 ppm
Skew            : 0.071 ppm
Root delay      : 0.004712308 seconds
Root dispersion : 0.000903521 seconds
Update interval : 1031.6 seconds
Leap status     : Normal
  • Reference ID : la source suivie. Pour une adresse IPv4, l'identifiant est l'adresse écrite en hexadécimal : AC100814, c'est 172.16.8.20. La valeur 7F7F0101 sans nom signifie que chrony n'est synchronisé sur aucune source externe (mode local).
  • Stratum : 3, car sig-outils est lui-même en strate 2 (les serveurs de Scaleway ou de l'Observatoire sont en strate 1 ou 2, selon le cas).
  • System time : l'écart restant entre l'horloge système et l'estimation de l'heure juste par chrony. C'est la correction qui reste à appliquer progressivement. Si cette valeur est grande et diminue lentement, une correction est en cours.
  • Last offset et RMS offset : le décalage estimé à la dernière mise à jour, et sa moyenne quadratique sur la durée. C'est ce chiffre qui indique la qualité habituelle de la synchronisation.
  • Frequency : la dérive naturelle de l'horloge, que chrony compense : ici, sans correction, l'horloge retarderait d'environ 12 millionièmes, soit un peu plus d'une seconde par jour.
  • Residual freq et Skew : l'écart entre la fréquence mesurée sur la source et celle appliquée, et la marge d'erreur sur la fréquence. Des valeurs basses indiquent une estimation stable.
  • Root delay et Root dispersion : délai et dispersion cumulés jusqu'à la strate 1. La documentation de chrony donne la borne de l'erreur : |System time| + Root dispersion + Root delay / 2, soit ici environ 3,3 ms.
  • Update interval : l'intervalle entre les deux dernières mises à jour.
  • Leap status : Normal, Insert second, Delete second, ou Not synchronised. Cette dernière valeur est celle qui doit déclencher une alerte.

Lire chronyc sources et sourcestats

$ chronyc sources -v

Sur sig-outils, la sortie ressemble à ceci :

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 51.159.69.162                 2   8   377    95    -48us[  -61us] +/- 1203us
^+ 51.159.69.156                 2   8   377   221   +102us[  +89us] +/- 1410us
^+ ntp.obspm.fr                  2   9   377   310   -215us[ -228us] +/- 4890us
^- 1.ntp.ubuntu.com              2  10   377   587   +812us[ +799us] +/-   19ms
^- 2.ntp.ubuntu.com              2  10   377   601   +640us[ +627us] +/-   21ms
^? 203.0.113.44                  0   6     0     -     +0ns[   +0ns] +/-    0ns

Les colonnes, d'après chronyc(1) :

  • M : ^ pour un serveur, = pour un pair, # pour une horloge de référence locale.
  • S : l'état de sélection. * la source retenue ; + les sources combinées avec elle ; - une source valable mais non combinée ; x un falseticker, en désaccord avec la majorité ; ~ une source trop variable ; ? une source inutilisable (injoignable, non synchronisée, ou pas encore assez de mesures).
  • Stratum et Poll : la strate annoncée par la source, et l'intervalle d'interrogation en puissance de 2 (8 signifie 256 secondes).
  • Reach : le registre d'accessibilité, en octal, sur les 8 derniers envois. 377 (huit bits à 1) : les 8 dernières requêtes ont reçu une réponse. 0 : aucune. Une valeur qui alterne (373, 356) révèle des pertes de paquets.
  • LastRx : l'ancienneté de la dernière mesure valable.
  • Last sample : le décalage de la source par rapport à l'horloge locale (positif : l'horloge locale est en avance), corrigé des ajustements faits depuis, puis entre crochets la valeur réellement mesurée, et après +/- la marge d'erreur.

La dernière ligne (une seule des adresses tirées du pool Debian est montrée) est typique d'une source qui n'a jamais répondu : avec Reach 0, cherchez un filtrage du trafic sortant. Pour savoir pourquoi une source n'est pas retenue, chronyc selectdata détaille l'état de sélection de chacune.

sourcestats montre la qualité statistique des mesures :

$ chronyc sourcestats
Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev
==============================================================================
51.159.69.162              18  10   72m     +0.004      0.031    -52us    41us
51.159.69.156              14   8   55m     -0.011      0.057    +97us    63us
ntp.obspm.fr               12   7   97m     +0.019      0.088   -221us   190us

NP est le nombre de mesures conservées, Span l'intervalle qu'elles couvrent, Frequency et Freq Skew la dérive résiduelle estimée par rapport à la source et sa marge, Offset et Std Dev le décalage estimé et l'écart type. Une source dont l'écart type est bien plus grand que celui des autres est moins fiable : souvent un chemin réseau chargé.

Vérifier NTS et les clients servis

$ sudo chronyc authdata
$ sudo chronyc clients

authdata doit afficher NTS dans la colonne Mode pour ntp.obspm.fr et les serveurs d'Ubuntu, avec une colonne KeyID non nulle et une colonne Cook (cookies disponibles) supérieure à zéro. Un - signifie une source non authentifiée, ce qui est attendu pour les adresses de Scaleway. Ces commandes, comme clients, demandent les droits d'administration : elles passent par la socket locale de commande de chronyd.

clients, sur sig-outils, liste les machines qui l'interrogent avec le nombre de requêtes reçues. Vous devez y voir 172.16.8.11 et 172.16.8.12, et personne d'autre.

Corriger un écart important à la main

Sur sig-app-2, au moment de l'incident, l'horloge retardait de 150 secondes. Après l'installation de chrony, makestep 1 3 a fait sauter l'horloge dès la première mesure. Si l'écart apparaît plus tard (restauration d'un instantané, migration de l'instance), les trois premières mises à jour sont passées, et chrony corrige progressivement. La page chrony.conf(5) indique que le taux d'ajustement est plafonné par défaut à 83 333 ppm, soit un douzième : rattraper 150 secondes prendrait donc une demi-heure environ, pendant laquelle l'horloge est fausse mais continue.

Pour forcer un saut immédiat :

$ sudo chronyc makestep
$ chronyc waitsync 30 0.01

makestep sans argument annule la correction en cours et fait sauter l'horloge de la valeur restante. waitsync 30 0.01 attend (au plus 30 essais espacés de 10 secondes) que chrony soit synchronisé avec une correction restante inférieure à 10 ms : pratique dans un script de déploiement qui doit s'assurer de l'heure avant de démarrer un service. Pour mesurer l'écart sans rien toucher, sur une machine où chrony n'est pas encore lancé, sudo chronyd -Q 'server 172.16.8.20 iburst' interroge le serveur, affiche le décalage et s'arrête.

Sous le capot

L'interface du noyau. Le noyau ne sait rien de NTP. Il offre deux opérations sur CLOCK_REALTIME : la régler (clock_settime(), c'est le saut) et en modifier la vitesse (adjtimex() ou clock_adjtime(), c'est l'ajustement progressif). Dans ce second cas, le noyau applique une correction de fréquence à chaque tic, et chronyd ou systemd-timesyncd ne font que calculer la bonne valeur à partir de leurs mesures. Le même appel transmet au noyau son erreur maximale estimée, que le noyau augmente ensuite d'elle-même avec le temps si personne ne la rafraîchit : c'est cette valeur que timedatectl compare au seuil de 16 secondes pour afficher System clock synchronized.

Les choix de timesyncd. Le code de systemd-timesyncd (fichier timesyncd-manager.c de systemd 255) est court et instructif : si le décalage mesuré est inférieur à 0,4 seconde, il demande au noyau un ajustement progressif ; au-delà, il fait sauter l'horloge, à tout moment, pas seulement au démarrage. Il enregistre aussi l'heure dans la date de modification de /var/lib/systemd/timesync/clock, pour qu'une machine sans RTC fiable reparte au moins de la dernière heure connue au démarrage suivant. Chrony obtient un résultat comparable avec sa directive driftfile et ses fichiers de ntsdumpdir, qui conservent la dérive et les cookies NTS.

Ce que voient les autres services. Un saut n'est pas invisible : les minuteurs systemd exprimés en heure réelle (OnCalendar=) sont recalculés, car le noyau prévient les processus qui l'ont demandé (descripteur timerfd avec l'option TFD_TIMER_CANCEL_ON_SET). Les délais relatifs, fondés sur l'horloge monotone, ne bougent pas. C'est la même distinction que celle des deux horloges, appliquée par systemd à lui-même.

Attendre la synchronisation au démarrage. La cible time-sync.target marque le moment où l'heure est jugée fiable. Par défaut, elle est atteinte tôt, sans attendre de vraie synchronisation. Pour qu'un service ne démarre qu'avec une heure juste (un service qui vérifie des certificats dès son lancement, par exemple), il faut activer un service d'attente : systemd-time-wait-sync.service avec timesyncd, ou chrony-wait.service fourni par le paquet chrony, et ordonner son service avec After=time-sync.target et Wants=time-sync.target. Le prix est un démarrage plus lent, voire bloqué si aucune source n'est joignable.

La RTC. Avec rtcsync, chrony ne touche pas lui-même à l'horloge matérielle : il laisse le noyau la recopier depuis l'heure système toutes les 11 minutes (le « mode 11 minutes » qu'évoque hwclock(8)), tant que l'horloge est marquée synchronisée. La commande hwclock ne sert donc presque plus sur un serveur synchronisé ; sa page de manuel déconseille d'ailleurs hwclock --hctosys sur un système en marche, précisément parce que le saut perturberait les dates des fichiers.

La source de cadence. Le noyau compte le temps avec une clocksource :

$ cat /sys/devices/system/clocksource/clocksource0/current_clocksource
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource

Sur une instance KVM, vous verrez typiquement kvm-clock comme source courante, et tsc parmi les sources disponibles. Le noyau surveille la cohérence de ces sources et peut en changer s'il en juge une instable ; un message clocksource dans dmesg (lu à la leçon 3) mérite alors attention, car il précède souvent des dérives inexpliquées.

Les secondes intercalaires. UTC suit la rotation de la Terre, qui ralentit irrégulièrement. Pour qu'UTC ne s'en écarte pas de plus de 0,9 seconde, on y a inséré de temps en temps une seconde supplémentaire, 23:59:60, à la fin de juin ou de décembre ; la dernière date du 31 décembre 2016. Le temps Unix ignore ces secondes : chaque jour y a exactement 86 400 secondes. Le serveur NTP annonce la seconde à venir ; par défaut (leapsecmode system), le noyau fait reculer l'horloge d'une seconde à minuit UTC. Certains grands opérateurs préfèrent le lissage (leap smear) : étaler la seconde sur plusieurs heures en ralentissant leurs serveurs. La RFC 8633 est catégorique : ne jamais mélanger des serveurs qui lissent et des serveurs qui ne lissent pas, car pendant la période de lissage ils sont en désaccord d'une fraction de seconde. Le problème devrait disparaître : la Conférence générale des poids et mesures a décidé en 2022 (résolution 4) que l'écart toléré entre UT1 et UTC serait augmenté au plus tard en 2035, ce qui revient à cesser d'insérer des secondes intercalaires.

Pièges courants

System clock synchronized: no alors que le service tourne. Le démon n'a pas encore obtenu de mesure exploitable. Avec timesyncd, le journal dit pourquoi : Timed out waiting for reply from 51.159.69.162:123 (51.159.69.162). signifie que les requêtes partent sans réponse (pare-feu sortant, groupe de sécurité, instance sans accès à Internet) ; Server has too large root distance. Disconnecting. signifie que le serveur répond mais s'estime lui-même trop imprécis (au-delà de RootDistanceMaxSec=). Avec chrony, chronyc sources montre Reach 0 et l'état ?.

Can't synchronise: no majority. Chrony écrit ce message quand ses sources se contredisent sans majorité claire : typiquement avec deux sources seulement, l'une décalée. Il refuse alors de corriger l'horloge, ce qui est le bon comportement. La correction est d'ajouter des sources, pas d'en retirer une au hasard. Le message voisin Can't synchronise: not enough selectable sources apparaît quand le nombre de sources valables est inférieur à minsources.

TLS handshake with ntp.obspm.fr:4460 failed. Ce message de chrony, suivi du texte d'erreur de GnuTLS, signale l'échec de l'échange de clés NTS. Trois causes classiques : le port TCP 4460 sortant est filtré ; le magasin de certificats du système est absent ou périmé (paquet ca-certificates) ; l'horloge locale est si fausse que le certificat du serveur paraît expiré ou pas encore valide. C'est le paradoxe de NTS : il faut une heure à peu près juste pour obtenir une heure juste. D'où l'intérêt de garder des sources non authentifiées mais proches (Scaleway), ou, comme le fait Ubuntu depuis 25.10, un serveur d'amorçage (ntp-bootstrap.ubuntu.com) dont le certificat est signé par une autorité propre, configurée par ntstrustedcerts, et l'option nocerttimecheck qui autorise un nombre limité de synchronisations sans vérifier les dates du certificat.

Failed to set time: Automatic time synchronization is enabled. Réponse de timedatectl set-time quand un service de synchronisation est actif. Ne désactivez pas la synchronisation pour régler l'heure à la main : corrigez la source, ou forcez un saut avec chronyc makestep.

Failed to set time zone: Invalid or not installed time zone 'Europe/paris'. Les noms de fuseaux respectent la casse ; timedatectl list-timezones donne la liste exacte.

Les symptômes indirects. Une horloge en retard se manifeste souvent ailleurs que dans timedatectl. APT refuse une mise à jour : Release file for http://fr.archive.ubuntu.com/ubuntu/dists/noble-updates/InRelease is not valid yet (invalid for another 2min 31s). Updates for this repository will not be applied. Le fichier Release du dépôt porte une date de publication que votre machine croit future. curl vers une API refuse le certificat : SSL certificate problem: certificate is not yet valid. Des jetons sont rejetés par la bibliothèque JWT de l'application. Devant l'un de ces messages, le premier réflexe est timedatectl.

Deux démons à la fois. Les paquets Debian et Ubuntu empêchent d'installer ensemble chrony et systemd-timesyncd. Mais un ancien ntpsec ou openntpd installé à la main, ou un agent fourni par un éditeur, peut cohabiter et se battre avec chrony : l'horloge oscille, et chronyc tracking affiche des décalages qui ne se résorbent pas. ss -ulpn 'sport = :123' montre qui écoute sur le port NTP.

Un écart qui apparaît après coup. Après la restauration d'un instantané de sig-app-2, l'horloge est fausse de plusieurs minutes, et chrony la corrige lentement parce que makestep 1 3 ne joue que sur les trois premières mises à jour. Pour une machine virtuelle susceptible d'être suspendue ou restaurée, la FAQ de chrony propose makestep 1 -1 (sauter à chaque fois que l'écart dépasse 1 seconde). C'est un arbitrage : vous acceptez des sauts, éventuellement en arrière, pour retrouver vite une heure juste.

chrony dans un conteneur. L'unité chrony.service de Debian déclare ConditionCapability=CAP_SYS_TIME : dans un conteneur sans ce privilège, le service est simplement ignoré. C'est normal : l'horloge système appartient à l'hôte, et c'est l'hôte qu'il faut synchroniser. Il en va de même pour les nœuds d'un cluster Kubernetes.

Comparer des journaux en heures différentes. Un journal en heure de Paris, un autre en UTC, une base qui stocke des dates sans fuseau (timestamp au lieu de timestamptz) : l'écart d'une ou deux heures ressemble à une panne alors qu'il s'agit d'affichage. Fixez la règle (UTC partout dans les journaux) et utilisez journalctl --utc dans vos recherches.

Sécurité

L'heure est une cible. Un attaquant capable de déplacer l'horloge d'une machine peut lui faire accepter un certificat expiré ou révoqué depuis, rejouer un jeton ou un ticket Kerberos dont la durée de vie est passée, contourner un mot de passe à usage unique fondé sur le temps (TOTP), ou rendre ses traces inexploitables en les mêlant à des dates fausses. NTP sans authentification sur Internet est exposé aux usurpations et aux attaques de l'homme du milieu. Les parades :

  • NTS vers au moins une partie des sources externes, comme sur sig-outils ;
  • plusieurs sources indépendantes et minsources supérieur à 1, pour qu'une source compromise soit mise en minorité ;
  • limiter les sauts : makestep borné aux premières mises à jour, et éventuellement maxchange, qui fait ignorer puis refuser les corrections démesurées. La FAQ de chrony décrit cette approche : l'attaquant ne peut alors provoquer qu'un écart limité, et seulement dans une courte fenêtre après le démarrage.

Ne pas servir l'heure au monde. Les anciens serveurs ntpd répondaient à des requêtes de supervision (la commande monlist, dite « mode 7 ») par des réponses bien plus volumineuses que la question. Avec une adresse source usurpée, cela en faisait des amplificateurs d'attaques par déni de service, massivement exploités en 2014 (CVE-2013-5211). La RFC 8633 recommande de restreindre ces fonctions. Chrony ne sert rien par défaut ; avec allow, limitez-le au réseau privé, et laissez son port de commande (UDP 323) à son réglage par défaut, qui n'écoute que sur l'adresse locale. Le groupe de sécurité Scaleway et le pare-feu de l'hôte forment deux barrières de plus.

Le moindre privilège du démon. Sur Debian 13, chronyd démarre avec les droits de root pour ouvrir ses ports et régler l'horloge, puis bascule sous le compte _chrony. Son unité systemd applique un bac à sable étendu (ProtectSystem=strict, NoNewPrivileges=yes, liste restreinte de capacités), et le fichier /etc/default/chrony passe l'option -F 1, qui active un filtre seccomp des appels système. systemd-analyze security chrony le confirme. C'est un bon modèle de ce que la leçon 14 appliquera à l'unité de Signalements.

La preuve. Les journaux de Signalements contiennent des adresses IP et des identifiants d'agents : des données personnelles au sens du RGPD, conservées pour assurer la traçabilité. Leur valeur, devant la mairie, devant un juge ou dans un rapport d'incident, dépend de la fiabilité de leur horodatage. Documentez la configuration de l'heure (sources, seuils, surveillance) : c'est elle qui permet d'affirmer qu'un événement a eu lieu à telle heure, à une seconde près.

En production

Surveiller le décalage, pas seulement le service. Un service chrony actif ne dit pas que l'heure est juste. Collectez sur chaque machine le décalage, l'état de synchronisation et la strate. chronyc -c tracking produit la même information que tracking en format CSV, facile à analyser dans un script ou un agent de supervision ; l'exportateur Prometheus node_exporter publie de son côté l'état de l'horloge du noyau (collecteur timex). Les seuils se raisonnent à partir des besoins :

  • l'ANSSI demande une précision d'au moins la seconde pour la journalisation ;
  • les jetons et TLS tolèrent quelques secondes ;
  • une synchronisation saine dans un même centre de données reste à la milliseconde près.

Un seuil d'avertissement autour de 100 ms et un seuil critique à 1 seconde laissent le temps d'agir avant que les applications ne souffrent. Alertez aussi sur Leap status : Not synchronised qui dure plus de quelques minutes, sur une strate qui devient anormale, et sur un écart entre machines, pas seulement par rapport à la source : deux serveurs d'application en désaccord sont un problème, même s'ils sont chacun dans les limites.

La cohérence avant la précision. Les recommandations de l'ANSSI le disent : pour la journalisation, ce qui compte est que toutes les machines aient la même heure ; la précision absolue par rapport au temps universel ne se justifie que par des besoins métier. C'est ce que garantit l'architecture en étoile autour de sig-outils. À plus grande échelle, on dédie deux ou trois serveurs de temps internes, dans des zones différentes, et toutes les machines les interrogent tous.

La redondance du serveur interne. sig-outils est un point unique pour le temps, comme il l'est pour les journaux et les sauvegardes. Les serveurs de Scaleway configurés en secours sur sig-app-1 et sig-app-2 limitent le risque : même si sig-outils disparaît, les deux machines suivent les mêmes sources et restent cohérentes. Notez la dépendance dans la fiche de chaque serveur.

Les services managés. sig-db, la base PostgreSQL managée, a son horloge tenue par Scaleway : vous ne la réglez pas. Si l'application fait générer les dates par la base (now() dans une requête) et parfois par le serveur d'application (datetime.now(timezone.utc) en Python), deux horloges écrivent dans la même table. Choisissez une seule origine pour les dates qui doivent être ordonnées entre elles, et vérifiez de temps en temps l'écart entre SELECT now() et l'heure de sig-app-1.

Automatiser. Les fichiers de sources.d et conf.d, la liste des serveurs par zone, les règles de pare-feu : tout cela se décrit dans l'outil d'automatisation (cours Ansible : les fondamentaux), pour qu'une nouvelle instance soit à l'heure dès son premier démarrage, avant même que l'application ne s'y installe. Dans un cluster Kapsule, les nœuds sont gérés par Scaleway, y compris leur synchronisation ; vos conteneurs héritent de l'heure de l'hôte.

Les mises à jour de tzdata. Les gouvernements changent parfois leurs règles d'heure d'été avec un préavis court. Le paquet tzdata est mis à jour en conséquence dans les dépôts de sécurité ou de mises à jour, et les mises à jour automatiques le prennent en charge. Les environnements virtuels Python qui embarquent leur propre base (paquet tzdata de PyPI) ou les images de conteneurs figées ne bénéficient pas de ces mises à jour : c'est à l'équipe de les reconstruire.

Exercices

1. Lire un état (niveau 100). Sur une machine héritée, timedatectl status affiche Time zone: Europe/Paris (CEST, +0200), System clock synchronized: yes, NTP service: active et RTC in local TZ: yes, suivi d'un long avertissement. Que signifie chacune de ces lignes, laquelle pose problème, et que faites-vous ?

Solution

Le fuseau d'affichage est l'heure de Paris, en heure d'été (+2 h). L'horloge est disciplinée par un service de synchronisation actif (l'erreur maximale tenue par le noyau est sous 16 secondes). Le problème est RTC in local TZ: yes : l'horloge matérielle stocke l'heure locale, ce qui pose des difficultés à chaque changement d'heure et au démarrage, d'où l'avertissement de timedatectl. Correction : sudo timedatectl set-local-rtc 0. Sur un serveur, il faut en plus envisager de passer le fuseau en UTC (sudo timedatectl set-timezone Etc/UTC) après avoir recensé les tâches planifiées dont l'heure se décalera.

2. Mesurer une durée (niveau 100). Un script de purge des pièces jointes calcule sa durée d'exécution avec debut = time.time() puis duree = time.time() - debut. Une nuit, le journal indique une durée négative. Expliquez, et corrigez.

Solution

time.time() lit CLOCK_REALTIME, qui peut sauter. Pendant l'exécution, la synchronisation a fait reculer l'horloge (un saut de timesyncd au-delà de 0,4 seconde, un chronyc makestep, ou un makestep au redémarrage de chrony), et la seconde lecture est antérieure à la première. Une durée se mesure avec l'horloge monotone : time.monotonic() en Python, qui lit CLOCK_MONOTONIC et ne recule jamais. time.time() reste le bon choix pour dater le début de la purge dans le journal.

3. Une source muette (niveau 200). Sur sig-app-2, chronyc sources affiche ^? 172.16.8.20 0 6 0 - +0ns[ +0ns] +/- 0ns, et les deux serveurs de Scaleway avec ^* et ^+. Que se passe-t-il, quelles vérifications faites-vous dans l'ordre, et pourquoi l'heure de sig-app-2 reste-t-elle correcte pour l'instant ?

Solution

Reach 0 et l'état ? : aucune réponse de sig-outils sur les 8 dernières requêtes. Vérifications, de la plus proche à la plus lointaine :

  1. Sur sig-outils : systemctl status chrony (le service tourne-t-il ?) et sudo chronyc clients (voit-il arriver 172.16.8.12 ?).
  2. Sur sig-outils : la directive allow 172.16.8.0/22 est-elle présente (grep -r allow /etc/chrony/) et chrony a-t-il été redémarré après son ajout ? ss -ulpn 'sport = :123' doit montrer chronyd en écoute sur toutes les adresses ou sur 172.16.8.20.
  3. Le pare-feu de sig-outils laisse-t-il entrer UDP 123 depuis 172.16.8.0/22 ? (sudo nft list ruleset, leçon 8.)
  4. Le réseau : ping 172.16.8.20 depuis sig-app-2, et sudo chronyd -Q 'server 172.16.8.20 iburst' sur une machine où chrony est arrêté, pour isoler le problème.

L'heure reste correcte parce que sig-app-2 dispose de deux autres sources (les serveurs de Scaleway), qui sont en accord. C'est précisément le rôle des sources de secours. Mais la cohérence avec sig-app-1 n'est plus garantie par une source commune : à corriger rapidement.

4. Un parc à l'heure (niveau 200). Écrivez un script Bash, à lancer depuis sig-outils, qui interroge par SSH sig-app-1 et sig-app-2, récupère pour chacun le décalage du champ System time de chronyc -c tracking et l'état Leap status, et sort avec le code 2 si un décalage dépasse 0,1 seconde en valeur absolue ou si une machine n'est pas synchronisée. Le format CSV de chronyc -c tracking place le décalage système dans le cinquième champ et l'état de seconde intercalaire dans le dernier.

Solution
#!/usr/bin/env bash
set -euo pipefail
seuil=0.1
code=0
for h in sig-app-1 sig-app-2; do
  ligne=$(ssh -o BatchMode=yes "$h" chronyc -c tracking) || { echo "$h : injoignable"; code=2; continue; }
  decalage=$(cut -d, -f5 <<<"$ligne")
  leap=$(awk -F, '{print $NF}' <<<"$ligne")
  echo "$h : décalage ${decalage} s, état ${leap}"
  if [ "$leap" = "Not synchronised" ]; then code=2; fi
  if awk -v d="$decalage" -v s="$seuil" 'BEGIN { exit !((d < 0 ? -d : d) > s) }'; then code=2; fi
done
exit "$code"

-o BatchMode=yes empêche SSH de demander un mot de passe, ce qui bloquerait un script automatique. Le calcul de la valeur absolue et la comparaison de nombres décimaux passent par awk, que Bash ne sait pas faire seul. Avant de vous fier au script, vérifiez sur une machine la position des champs avec chronyc -c tracking : la page chronyc(1) de votre version fait foi. En production, ce rôle revient à l'agent de supervision ; mais lancé par un minuteur systemd (leçon 10) avec une notification en cas d'échec, ce script couvre déjà le risque principal.

5. Concevoir pour une collectivité (niveau 300). Un client public vous demande de documenter la synchronisation de l'heure de Signalements pour un audit qui s'appuie sur les recommandations de l'ANSSI. Rédigez en quelques lignes l'architecture, ses justifications et ses limites, en citant au moins deux recommandations.

Solution

Éléments attendus :

  • Architecture : un serveur de temps interne (sig-outils, chrony) synchronisé sur cinq sources externes diverses (deux serveurs NTP de Scaleway proches, le serveur de strate 2 de l'Observatoire de Paris, qui diffuse le temps légal, et deux serveurs d'Ubuntu, ces trois derniers authentifiés par NTS) ; les serveurs d'application suivent sig-outils en priorité et les serveurs de Scaleway en secours ; minsources 2 sur le serveur interne.
  • Justifications : R5 (sources internes cohérentes entre elles, raccordées à plusieurs sources externes fiables, même protocole et même logiciel sur tout le parc) ; R4 (paramètres d'horodatage homogènes : UTC sur toutes les machines, horodatage RFC 3339 dans les journaux, précision meilleure que la seconde) ; RFC 8633 (au moins quatre sources indépendantes) ; NTS contre l'usurpation.
  • Surveillance : décalage, état et strate collectés, alerte à 100 ms et à 1 s, alerte sur la perte de synchronisation.
  • Limites : le serveur interne est unique (atténué par les sources de secours) ; les serveurs de Scaleway ne sont pas authentifiés ; l'horloge de la base managée dépend du fournisseur ; NTS dépend d'une heure initiale raisonnable. Écarts documentés, et piste d'évolution : un second serveur de temps interne dans une autre zone.

Récapitulatif

  • L'heure fonde TLS, les jetons, Kerberos, la corrélation des journaux et l'exécution des tâches : une horloge fausse se manifeste souvent par des erreurs qui ne parlent pas d'heure.
  • La RTC survit à l'arrêt, l'horloge système est celle qu'on lit et qu'on synchronise. CLOCK_REALTIME date les événements et peut sauter ; CLOCK_MONOTONIC mesure les durées et ne recule jamais.
  • Les serveurs vivent en UTC, RTC comprise ; l'heure de Paris est une affaire d'affichage (TZ=, journalctl --utc, l'application).
  • NTP mesure décalage et délai à partir de quatre horodatages, choisit parmi plusieurs sources et écarte les menteuses. Les démons sautent rarement et ajustent progressivement le reste du temps.
  • Ubuntu 24.04 et Debian 13 utilisent par défaut systemd-timesyncd, un client SNTP à une source ; chrony (par défaut à partir d'Ubuntu 25.10 et sur RHEL) gère plusieurs sources, sert l'heure et prend en charge NTS.
  • Pour Signalements : sig-outils sert l'heure au réseau privé (allow 172.16.8.0/22) à partir de sources diverses, dont NTS ; sig-app-1 et sig-app-2 le suivent, avec Scaleway en secours.
  • timedatectl pour l'état général, chronyc tracking, sources -v, sourcestats et authdata pour le diagnostic ; Reach 0 signale une source injoignable.
  • On surveille le décalage et la cohérence entre machines, pas seulement le service ; on ne sert jamais NTP au monde entier.

Pour aller plus loin

  • La RFC 5905 pour l'algorithme complet de NTP, la RFC 8915 pour NTS et la RFC 8633 pour les bonnes pratiques d'exploitation.
  • La documentation de chrony, en particulier chrony.conf(5), chronyc(1) et la FAQ, qui traite de la sécurité de la synchronisation.
  • Les recommandations de l'ANSSI pour l'architecture d'un système de journalisation, sections 2.2 et 2.3, sur l'horodatage et la synchronisation des horloges.
  • La page de l'Observatoire de Paris sur la diffusion de l'heure par Internet, et le site heurelegalefrancaise.fr.
  • Le cours Performance et diagnostic, pour la précision de l'horodatage dans les mesures, et le cours Journaux centralisés avec Loki, où des horloges cohérentes sont indispensables.
  • La leçon suivante : Planifier des tâches : cron et minuteurs.
+20 XP Carte du ciel →Mon cosmonaute →

Sources