Keeping time with Chrony

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