A client of your own server
iburst makes the first four polls back to back, so the sync takes
seconds instead of minutes. Only node2 stays as a source if you
comment out the pool lines in chrony.conf and restart the service.
An NTP client and server: keeps the system clock in step with time servers and can serve time to your machines.
chronyc tracking
is the clock in sync, and how close
chronyc sources
time servers and their state
chronyc sourcestats
offset and spread per server
sudo chronyc reload sources
reread /etc/chrony/sources.d
sudo chronyc burst 4/4
poll the servers now
sudo chronyc makestep
correct the clock in one step
chronyc waitsync 10 0.5
wait for sync (for scripts)
sudo systemctl restart chrony
reread chrony.conf and conf.d
chrony is two programs. The chronyd service keeps the system clock: it
polls time servers over NTP (UDP port 123) and brings the clock to their
time. chronyc queries the service and gives it commands over a local
socket. By default the Ubuntu clock is kept by systemd-timesyncd — a
client only, whose state timedatectl shows. chrony keeps the clock
more precisely, shows in detail where the time comes from, and can serve
it to other machines.
chrony is not installed on the lab machine; the package is in
/opt/debs:
The install takes about 10 seconds and removes systemd-timesyncd: two
NTP clients on one machine would get in each other's way. The chrony
service is enabled and running right away.
node1 gets its time from node2:
| Field | What it means |
|---|---|
Reference ID |
where the time comes from now: the address in hex and the name |
Stratum |
the level in the NTP hierarchy: the source is one level lower |
System time |
how far the system clock is now behind (slow) or ahead (fast) |
Last offset |
the offset at the last measurement |
Leap status |
Normal — the clock is in sync, Not synchronised — it is not |
The gap between the clock and the source is the System time line: 4
microseconds here. Without sources Reference ID is 00000000 (),
Stratum is 0, Ref time is in 1970, and Leap status is
Not synchronised.
The last line is a single line in the output; it is wrapped here.
| Column | What it means |
|---|---|
M |
^ — server, = — peer, # — the machine's own clock |
S |
* — selected for adjusting, + — combined with it, - — not combined, ? — unusable, x — may be wrong, ~ — too variable |
Stratum |
the server's level |
Poll |
the polling interval as a power of two: 6 is 64 seconds |
Reach |
the last eight polls in octal: 377 — all answered, 17 — four polls so far, each answered, 0 — no answers at all |
LastRx |
how many seconds ago the last answer came |
Last sample |
the offset after adjustment, the measured one in brackets, the error after +/- |
Reach reads from right to left: the lowest bit is the latest poll.
After UDP 123 was closed on node2, 17 turned into 170: the last
three polls got no answer. chronyc sources -v prints the same legend
above the table.
Usually chronyd adjusts the clock smoothly: it makes the clock run a
little faster or slower, and the time does not jump: no faster than
83 milliseconds per second (maxslewrate defaults to 83333 ppm), so 2
hours would take at least a day. A large gap it fixes with a step. The line makestep 1 3 in the Ubuntu config allows a
step when the gap is over 1 second — but only during the first three
updates after start.
The node1 clock is 2 hours fast, the node2 source is added with
reload sources — 4 seconds later the journal shows:
If you set the clock by hand (date -s) on a running machine, chronyd
notices the jump and drops the sync until a new measurement, then steps
the time back:
A new measurement comes on the polling schedule (64 seconds and more)
or right after sudo chronyc burst 4/4.
The main file is /etc/chrony/chrony.conf. In Ubuntu 24.04, without
comments, it is:
Your own settings go into two directories:
| Directory | Files | How to apply |
|---|---|---|
/etc/chrony/conf.d/ |
*.conf — any directives |
sudo systemctl restart chrony |
/etc/chrony/sources.d/ |
*.sources — only server, pool, peer |
sudo chronyc reload sources |
reload sources rereads only sources.d: a server line in conf.d
does not appear after it, a restart is needed. The lab machine has no
network to the outside, the pool names do not resolve, and
chronyc activity prints 16 sources with unknown address — these
lines do no harm.
Directives are in the table below; the full list is man chrony.conf.
| Directive | What it does | Example |
|---|---|---|
server sources.d, conf.d |
A time server by name or address; iburst makes the first four polls back to back. | server node2 iburst |
pool chrony.conf, sources.d |
A name behind which there are many servers; maxsources sets how many to use. | pool ntp.ubuntu.com iburst maxsources 4 |
allow conf.d |
Which addresses to answer as an NTP server; without allow chronyd is only a client. | allow 10.0.0.0/8 |
local conf.d |
Serve the time of the machine's own clock even when the server has no source. | local stratum 10 |
makestep chrony.conf |
Step the clock if the gap is over N seconds, but only during the first M updates after start. | makestep 1 3 |
confdir chrony.conf |
A directory of *.conf files read when the service starts. | confdir /etc/chrony/conf.d |
sourcedir chrony.conf |
A directory of *.sources files; chronyc reload sources rereads them without a restart. | sourcedir /etc/chrony/sources.d |
driftfile chrony.conf |
The file where chronyd remembers how fast or slow the machine's clock runs, across restarts. | driftfile /var/lib/chrony/chrony.drift |
rtcsync chrony.conf |
Copy the system time to the hardware clock (RTC) every 11 minutes. | rtcsync |
maxupdateskew chrony.conf |
Ignore measurements while the estimated frequency error is above this many ppm. | maxupdateskew 100.0 |
logdir chrony.conf |
The chrony log directory; the log directive sets what to write. | logdir /var/log/chrony |
Nothing found. Try a shorter query.
iburst makes the first four polls back to back, so the sync takes
seconds instead of minutes. Only node2 stays as a source if you
comment out the pool lines in chrony.conf and restart the service.
On node2:
allow sets which addresses to answer: without it chronyd works only
as a client. The lab machines get their own network in each session —
ip -br a shows it. local stratum 10 allows serving the time of its
own clock even when the server itself has no source: without this line
such a server is no use to clients. The clients of node2 get level
11.
waitsync <tries> <offset> waits until the clock is in sync and the
correction is below the given one (0.5 s here), polling every 10
seconds. Code 0 means it got there, 1 means the tries ran out. The
offset as a number is the fourth field:
makestep without a fresh measurement changes nothing: right after
date -s it answers 200 OK, and the clock stays as it was.
sudo systemctl restart chrony also corrects the clock: after start the
first three updates of makestep 1 3 apply again.
chronyd is not running: systemctl status chrony. If chrony is not
installed, there is no chronyc command at all.
Commands that change the service state — makestep, burst,
reload sources — are for root: sudo chronyc …. tracking,
sources and sourcestats work as a regular user.
The server name does not resolve: chronyd added a source without an
address and waits. The journal has Added source ID#0000000017
(ntp.lab.invalid) with no IP, and chronyc activity counts it among
sources with unknown address. Check the name: getent hosts <name>.
The server has never answered (Reach 0): a wrong address, no chrony on
it, no allow for your network, or UDP 123 closed by a firewall —
firewall. If Reach was non-zero and dropped, the answers stopped
coming recently.
There is no usable source: see chronyc sources. Right after a manual
date -s it is the same — chronyd waits for a new measurement.
chronyd brings the time back to the source with a step, as in
chrony. To shift the time for an experiment, turn the
sync off: sudo timedatectl set-ntp false stops chrony, set-ntp true
starts it again.
timesync-status asks systemd-timesyncd, and the chrony install
removed it. With chrony use chronyc tracking. Right after the install
timedatectl may print NTP service: n/a; the reliable check is
Leap status in chronyc tracking.
A step back repeats time that has already passed: journal lines go out
of order, cron jobs and timers may fire twice or be skipped, TLS
certificates look "not yet valid". On a live server let chrony adjust
the clock smoothly, and keep makestep and date -s for a machine you
have just brought up.
systemd-timesyncd.journalctl -u chrony.Found an inaccuracy? Report an error in the article