linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Processes & resources/chrony-and-ntp

kb/processes ── Processes & resources ── intermediate

chrony and NTP: clock synchronization

NTP is the clock synchronization protocol (about millisecond accuracy over the internet). On modern Linux the implementation is `chronyd` (default) or `systemd-timesyncd` (lightweight).

view as markdownaka: chronyd, chronyc, ntpd, systemd-timesyncd, ntp-pool

Why accurate time matters

A clock that is off by seconds breaks several things:

  • TLS handshake. Certificates are validated against the wall clock. Drift by ±5 minutes from reality and curl returns certificate has expired.
  • Kerberos. The tolerance is ±5 minutes, beyond that you get KRB_AP_ERR_SKEW.
  • Logs and tracing. ELK/Loki/Jaeger correlate events by timestamp.
  • Databases and replication. Postgres physical replication, MongoDB causal consistency.
  • The filesystem. make decides what to rebuild from mtime, cron waits for a specific time, and systemd-timers drift.

NTP, the protocol

NTP (Network Time Protocol) runs over UDP/123. Servers form a hierarchy of strata:

Stratum 0  atomic clocks / GPS / radio signal (they do not answer NTP themselves)
     ↓
Stratum 1  servers attached directly to stratum 0 (a handful worldwide)
     ↓
Stratum 2  public servers synchronized with stratum 1
     ↓
Stratum 3  usually your own local NTP server, if you run one
     ↓
Stratum 4+ clients on your network

The higher the number, the further from the original source. Stratum 16 means "not synchronized".

Sources for a home or office host:

  • pool.ntp.org. A global pool of thousands of servers; DNS returns a random set.
  • Distribution pools: 0.fedora.pool.ntp.org, 0.debian.pool.ntp.org, 0.ubuntu.pool.ntp.org.
  • Your own internal server for a large network. It lowers load on the public pool and works in an air-gapped environment.

Three NTP implementations on Linux

ImplementationDefault onNotes
chronyd (chrony)Fedora, RHEL, ArchFull-featured, handles an intermittent network, can act as a server
systemd-timesyncdUbuntu desktop, minimal imagesClient only (SNTP), one server, lightweight
ntpd (reference)rare on new systemsOlder implementation, slower to react, deprecated

Run only one. If chrony is installed, run systemctl disable --now systemd-timesyncd.

Check which daemon synchronizes the clock:

bash
timedatectl
# System clock synchronized: yes
# NTP service: active

When NTP service: active, some daemon is running. To find out which one, use systemctl is-active chronyd systemd-timesyncd.

The chrony config: /etc/chrony.conf (or /etc/chrony/chrony.conf)

A minimal client config:

pool 2.fedora.pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync

What the key directives mean:

DirectivePurpose
pool <host> iburstThe DNS name returns several servers; iburst gives a fast initial sync
server <host> iburstOne specific server
server X.X.X.X preferPrefer this source while it works
driftfile <path>Persist the crystal's drift estimate across reboots
makestep 1.0 3If the offset is > 1 sec, apply the first 3 updates as a step, then slew
rtcsyncSync the RTC (hardware clock) to the system clock every 11 minutes
allow 192.168.0.0/24Serve NTP to clients in this subnet (chrony as a server)
local stratum 10Announce yourself at stratum 10 when the internet is unreachable (for air-gap)

The iburst option is essential. At startup it sends 4 packets back to back at a 2-second interval, so synchronization takes seconds instead of minutes.

The systemd-timesyncd config

/etc/systemd/timesyncd.conf is simple:

ini
[Time]
NTP=time.cloudflare.com 0.pool.ntp.org
FallbackNTP=ntp.ubuntu.com
RootDistanceMaxSec=5

After an edit, run systemctl restart systemd-timesyncd. To check:

bash
timedatectl timesync-status

Debugging with chronyc

bash
chronyc tracking
# Reference ID    : C0A80034 (yorktown.both.org)
# Stratum         : 3
# System time     : 0.000004870 seconds slow of NTP time   ← key line
# Last offset     : -0.000007259 seconds
# Frequency       : 18715.217 ppm fast                     ← crystal drift
# Skew            : 0.087 ppm
# Leap status     : Normal

The main indicators:

  • System time. How far the clock is behind or ahead. < 1 ms is fine. Seconds is bad.
  • Stratum. Your own stratum. A 16 means not synchronized.
  • Leap status. Normal, or Insert/Delete in the days before a leap second.

The list of servers:

bash
chronyc sources -v
# MS Name/IP address       Stratum Poll Reach LastRx Last sample
# ^* time.cloudflare.com         3   8   377   55     +418us[+430us] +/-   18ms

Reading the MS column (Mode/State):

  • ^ is a regular server, = is a peer.
  • * was chosen as best, + is combined into the estimate, - was rejected, x may be wrong, ? has not answered yet.

Force a sync right now:

bash
sudo chronyc makestep
# 200 OK

Use this after editing the config or when a host wakes up from a long sleep.

The RTC, the hardware clock

The hardware clock (RTC) runs off a battery on the board and keeps ticking while the system is off. At boot the system clock (kernel) reads the RTC, and NTP then trims it.

bash
hwclock --show              # time in the RTC
sudo hwclock --systohc      # write system → RTC
sudo hwclock --hctosys      # read RTC → system

In chrony, rtcsync runs --systohc automatically every 11 minutes. Without it, the clock jumps back to the RTC value after a reboot.

A gotcha with Windows/Linux dual boot: Windows stores local time in the RTC, Linux stores UTC. If you dual boot and the clock jumps by the timezone offset:

bash
sudo timedatectl set-local-rtc 1     # tell Linux the RTC holds local time

Running your own NTP server

With dozens of hosts in an office or at home, one local server beats pointing them all at pool.ntp.org. In /etc/chrony.conf on the server:

pool 2.fedora.pool.ntp.org iburst
allow 192.168.0.0/24                  # who to serve
rtcsync
driftfile /var/lib/chrony/drift

Then open UDP/123 in the firewall. On the clients:

server 192.168.0.10 iburst prefer

The clients' stratum will be one above the server's.

Debugging: why the clock will not sync

bash
systemctl status chronyd                        # is it even running
journalctl -u chronyd --since "10 min ago"      # recent messages
chronyc activity                                # how many sources are online/offline
chronyc sources -v                              # do we see anything
# network check
sudo nmap -sU -p 123 0.pool.ntp.org             # is the port open?
sudo ss -ulnp 'sport = :123'                    # are we listening ourselves?

Common problems:

  • Every source shows ? (no answer). UDP/123 is blocked by the ISP's firewall.
  • Reference ID: 00000000 (). Not synchronized, the initial sync is in progress, wait a minute with iburst.
  • chronyd does not start. It conflicts with systemd-timesyncd. Disable timesyncd.

§ команды

bash
timedatectl

The main overview: system time, RTC, timezone, NTP sync status

bash
chronyc tracking

Precise chrony sync statistics: offset, drift, stratum, leap

bash
chronyc sources -v

All NTP sources with their status and the time of the last answer

bash
sudo chronyc makestep

Force a sync by stepping the clock, after a config edit or a wake-up

bash
sudo timedatectl set-timezone Europe/Moscow

Change the timezone, updates the /etc/localtime symlink

§ см. также

  • systemdsystemd: the init system and service managersystemd is the Linux init system: PID 1 that starts everything else, tracks dependencies, restarts what crashes, and collects the logs.
  • systemd-resolvedsystemd-resolved: the local DNS stubsystemd-resolved is a DNS stub resolver. It listens on `127.0.0.53:53` and proxies queries to upstream DNS, aggregating data from NetworkManager, DHCP, and VPN. You drive it with `resolvectl`.
  • cmd-systemctlsystemctl: managing systemd services`systemctl` is the main CLI for managing systemd units: services, timers, mounts, and sockets. It replaces SysV init and `service` on modern distros.
  • cmd-journalctljournalctl: systemd journal`journalctl` reads the binary journal written by systemd-journald. It is the central log for the system: kernel, systemd services, syslog, all through one interface.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies