Keeping time with Chrony
Table of Contents
I’m on a Debian 11 machine. systemd-timesyncd
is installed by default. chrony
will remove it during the installation:
apt install chrony -y
Check the status with systemctl status chrony
and chronyc actvity
:
root@debian:~# chronyc activity
200 OK
5 sources online
0 sources offline
0 sources doing burst (return to online)
0 sources doing burst (return to offline)
3 sources with unknown address
Verify if your System Clock has been synchronized and the NTP service are active with timedatectl
and chronyc tracking
:
root@debian:~# timedatectl
Local time: Thu 2021-10-14 11:05:17 +04
Universal time: Thu 2021-10-14 07:05:17 UTC
RTC time: Thu 2021-10-14 07:05:18
Time zone: Indian/Mauritius (+04, +0400)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
root@debian:~#
root@debian:~# chronyc tracking | egrep -i "utc|leap"
Ref time (UTC) : Thu Oct 14 09:21:33 2021
Leap status : Normal
Sometimes the Ref time from chronyc tracking
will still point to the Unix Epoch time. This can happen when the sources are not resolving or stopped responding. Chrony will replace them automatically with new addresses only if the sources are marked as unreacheable. You can replace them immediately with chronyc refresh
.
Chrony as an NTP client #
Upon installation, there’s not much to change. The configuration is either /etc/chrony/chrony.conf
This is where you will set your sources: server or pool. By default I have the debian vendor zone:
root@debian:~# cat /etc/chrony/chrony.conf | egrep "^pool|^server"
pool 2.debian.pool.ntp.org iburst
A pool is list of servers. You list them with chronyc sources
:
root@debian:~# chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^? time.cloudflare.com 0 8 0 - +0ns[ +0ns] +/- 0ns
^? 197.224.66.40 2 6 377 59 -11ms[ -11ms] +/- 171ms
^* time.cloudflare.com 3 6 377 59 -6886us[-3451us] +/- 104ms
^? time.cloudflare.com 0 8 0 - +0ns[ +0ns] +/- 0ns
^+ time.cloudflare.com 3 6 377 59 -7340us[-3905us] +/- 104ms
To understand what the above symbols associated with servers represent, run chronyc sources -v
.
Use NTS #
Network Time Security or NTS is basically NTP with TLS. You can more about it here. To enable it, you should specify where the NTS-KE cookies should be stored. Debian has done all the heavy lifting for you:
root@debian:~# cat /etc/chrony/chrony.conf | grep -B 1 ntsdumpdir
# Save NTS keys and cookies.
ntsdumpdir /var/lib/chrony
The above line tells chronyc
to avoid making an NTS-KE request when chronyd is started again.
Note: I intended to write this post for Rocky Linux. But its repo has the 3.5 version. NTS was added in 4.0. I tried the rpm provided by centos 8 upstream. It contains a lot of bugs.
I’m gonna add two new server directive in chrony.conf
with the nts
option:
root@debian:~# cat /etc/chrony/chrony.conf | egrep "^pool|^server"
pool 2.debian.pool.ntp.org iburst
server nts.sth1.ntp.se iburst nts
server nts.sth2.ntp.se iburst nts
NTP Pool does not currently support NTS.
Restart chronyd
, and all sources should be online:
root@debian:~# chronyc activity | grep online
7 sources online
0 sources doing burst (return to online)
Run chronyc -N authdata
to verify if the new servers are using NTS:
root@debian:~# chronyc -N authdata
Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen
=========================================================================
2.debian.pool.ntp.org - 0 0 0 - 0 0 0 0
2.debian.pool.ntp.org - 0 0 0 - 0 0 0 0
2.debian.pool.ntp.org - 0 0 0 - 0 0 0 0
2.debian.pool.ntp.org - 0 0 0 - 0 0 0 0
2.debian.pool.ntp.org - 0 0 0 - 0 0 0 0
nts.sth1.ntp.se NTS 1 15 256 22m 0 0 8 100
nts.sth2.ntp.se NTS 1 15 256 22m 0 0 8 100
Chrony as a server on a LAN #
I guess one of the reasons to keep a local ntp server is to put less of a load on public time servers. A basic server is very easy to setup. Just add the allow
directive followed by the network from which clients are allowed to connect and restart chrony
:
allow 192.168.100.0/24
It’s recommended to add a local stratum, but it’s up to you. For this particular configuration, it will work fine.
Allow UDP Port 123:
ufw allow ntp
Configure a client #
Add your server in the client’s chrony.conf
file and restart the service:
server 192.168.100.121 iburst prefer
Verify the sources:
alpine:~# chronyc sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^- 197.224.66.40 2 6 377 90 -19ms[-2599us] +/- 160ms
^- time.cloudflare.com 3 6 377 25 -16ms[ -472us] +/- 103ms
^- time.cloudflare.com 3 6 377 26 -15ms[+1121us] +/- 104ms
^* 192.168.100.121 4 6 7 18 -4190ns[ +16ms] +/- 104ms
alpine:~# chronyc tracking
Reference ID : C0A86479 (192.168.100.121)
Stratum : 5
Ref time (UTC) : Thu Oct 14 09:07:51 2021
System time : 0.002209067 seconds slow of NTP time
Last offset : -0.002241889 seconds
RMS offset : 0.005034517 seconds
Frequency : 30.028 ppm fast
Residual freq : +25.609 ppm
Skew : 0.609 ppm
Root delay : 0.203035384 seconds
Root dispersion : 0.006499020 seconds
Update interval : 65.2 seconds
Leap status : Normal
On your server, run chronyc clients
to view your list of clients:
root@debian:~# chronyc clients
Hostname NTP Drop Int IntL Last Cmd Drop Int Last
===============================================================================
192.168.100.120 2 0 6 - 52 0 0 - -
“You've gotta dance like there's nobody watching, Love like you'll never be hurt, Sing like there's nobody listening, And live like it's heaven on earth.”
― William W. Purkey