Install and configure chrony NTP server.

Inspect chrony package.

$ apt info chrony
Package: chrony
Version: 4.0-8
Priority: optional
Section: net
Maintainer: Vincent Blut
Installed-Size: 644 kB
Provides: time-daemon
Pre-Depends: init-system-helpers (>= 1.54~)
Depends: adduser, iproute2, tzdata, ucf, libc6 (>= 2.29), libcap2 (>= 1:2.10), libedit2 (>= 2.11-20080614-0), libgnutls30 (>= 3.7.0), libnettle8, libseccomp2 (>= 2.4.3-1~)
Suggests: dnsutils, networkd-dispatcher
Conflicts: time-daemon
Breaks: network-manager (<< 1.20.0-1~)
Replaces: time-daemon
Homepage: https://chrony.tuxfamily.org
Tag: implemented-in::c, interface::commandline, interface::daemon,
 interface::text-mode, network::server, network::service, role::program,
 uitoolkit::ncurses, use::configuring, use::monitor, use::timekeeping
Download-Size: 286 kB
APT-Sources: http://ftp.task.gda.pl/debian bullseye/main amd64 Packages
Description: Versatile implementation of the Network Time Protocol
 It consists of a pair of programs:
 .
 chronyd:  This is a daemon which runs in background on the system.
 It obtains measurements (e.g. via the network) of the system's offset
 relative to other systems and adjusts the system time accordingly. For
 isolated systems, the user can periodically enter the correct time by
 hand (using 'chronyc'). In either case 'chronyd' determines the rate
 at which the computer gains or loses time, and compensates for this.
 Chronyd implements the NTP protocol and can act as either a client or
 a server.
 .
 chronyc: This is a command-line driven control and monitoring program.
 An administrator can use this to fine-tune various parameters within
 the daemon, add or delete servers etc whilst the daemon is running.

Install chrony package.

$ sudo apt install chrony

Inspect default configuration.

$ cat /etc/chrony/chrony.conf 
# Welcome to the chrony configuration file. See chrony.conf(5) for more
# information about usable directives.

# Include configuration files found in /etc/chrony/conf.d.
confdir /etc/chrony/conf.d

# Use Debian vendor zone.
pool 2.debian.pool.ntp.org iburst

# Use time sources from DHCP.
sourcedir /run/chrony-dhcp

# Use NTP sources found in /etc/chrony/sources.d.
sourcedir /etc/chrony/sources.d

# This directive specify the location of the file containing ID/key pairs for
# NTP authentication.
keyfile /etc/chrony/chrony.keys

# This directive specify the file into which chronyd will store the rate
# information.
driftfile /var/lib/chrony/chrony.drift

# Save NTS keys and cookies.
ntsdumpdir /var/lib/chrony

# Uncomment the following line to turn logging on.
#log tracking measurements statistics

# Log files location.
logdir /var/log/chrony

# Stop bad estimates upsetting machine clock.
maxupdateskew 100.0

# This directive enables kernel synchronisation (every 11 minutes) of the
# real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
rtcsync

# Step the system clock instead of slewing it if the adjustment is larger than
# one second, but only in the first three clock updates.
makestep 1 3

# Get TAI-UTC offset and leap seconds from the system tz database.
# This directive must be commented out when using time sources serving
# leap-smeared time.
leapsectz right/UTC

Delete default pool.

$ sudo sed -i -e "/\# Use Debian vendor zone./,+2d" /etc/chrony/chrony.con

Define Debian NTP pool as a source.

$ cat << EOF | sudo tee /etc/chrony/sources.d/debian-pool.sources
pool 0.debian.pool.ntp.org iburst
pool 1.debian.pool.ntp.org iburst
pool 2.debian.pool.ntp.org iburst
pool 3.debian.pool.ntp.org iburst
EOF

Bind server to a specific interface or IP address and allow access from a particular subnet.

$ cat << EOF | sudo tee /etc/chrony/conf.d/server.conf
binddevice eth0
#bindaddress 10.10.0.1
allow 10.10.0.1/16
EOF

Use Unix domain command socket for command and monitoring access.

$ cat << EOF | sudo tee /etc/chrony/conf.d/cmd.conf
bindcmdaddress /var/run/chrony/chronyd.sock
cmdport 0
EOF

Restart chrony service.

$ sudo systemctl restart chrony

Inspect service status.

$ systemctl status chrony
● chrony.service - chrony, an NTP client/server
     Loaded: loaded (/lib/systemd/system/chrony.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-09-30 10:02:57 CEST; 3min 53s ago
       Docs: man:chronyd(8)
             man:chronyc(1)
             man:chrony.conf(5)
    Process: 1149 ExecStart=/usr/sbin/chronyd $DAEMON_OPTS (code=exited, status=0/SUCCESS)
   Main PID: 1151 (chronyd)
      Tasks: 2 (limit: 1105)
     Memory: 1.3M
        CPU: 44ms
     CGroup: /system.slice/chrony.service
             ├─1151 /usr/sbin/chronyd -F 1
             └─1152 /usr/sbin/chronyd -F 1

Display tracking information.

$ sudo chronyc tracking
Reference ID    : C21D82FC (ntp.coi.pw.edu.pl)
Stratum         : 2
Ref time (UTC)  : Thu Sep 30 08:10:42 2021
System time     : 0.000006597 seconds fast of NTP time
Last offset     : -0.000517745 seconds
RMS offset      : 0.003449982 seconds
Frequency       : 6.271 ppm fast
Residual freq   : +0.046 ppm
Skew            : 2.133 ppm
Root delay      : 0.014363421 seconds
Root dispersion : 0.001481146 seconds
Update interval : 64.7 seconds
Leap status     : Normal

Display NTP sources.

$ sudo chronyc sources -v
.-- 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               
===============================================================================
^- ntp11.kashra-server.com       2   6   377   102   -468us[ -468us] +/-   42ms
^* ntp.coi.pw.edu.pl             1   6   377   167  -3151us[-3310us] +/- 7850us
^- s.complex.net.pl              2   7   377    42   +611us[ +611us] +/-   57ms
^- ntp.tktelekom.pl              2   7   377    39  +1877us[+1877us] +/-   35ms
^x ciskacz.of.pl                 2   6   377    38   +112ms[ +112ms] +/-   88ms
^+ 94-172-186-238.dynamic.c>     2   6   377    39  -2733us[-2733us] +/-   22ms
^+ time.cloudflare.com           3   6   377   105   +366us[ +366us] +/-   21ms
^- 46.175.224.7.maxnet.net.>     3   6   377    39   +806us[ +806us] +/-   61ms
^- ntp.ifj.edu.pl                1   6   377    36  +7466us[+7466us] +/-   23ms
^- main.jakspzoo.pl              2   6   377    26  +1099us[+1099us] +/-   38ms
^+ time.cloudflare.com           3   6   377   168   +996us[ +837us] +/-   20ms
^- ntp.wide-net.pl               2   7   377    40  +1234us[+1234us] +/-   44ms
^- ntp2.pl                       2   6   377    40  -4286us[-4286us] +/-   50ms
^- time.taken.pl                 2   6   377     9   +905us[ +905us] +/-   58ms
^+ ntp.oa.uj.edu.pl              1   6   377    13  +7166us[+7166us] +/-   22ms
^- ntp2.tktelekom.pl             2   6   377    13  +1453us[+1453us] +/-   40ms
^- 96-7.cpe.smnt.pl              2   7   377    39  +3695us[+3695us] +/-   43ms
^- ntp1.pl                       2   6   377    12  -4972us[-4972us] +/-   43ms
^+ host-168-137.prnet.pl         1   6   377    37    +47ms[  +47ms] +/-   63ms
^- 160.ip-54-37-233.eu           2   6   377    42  -3679us[-3679us] +/-   94ms

Display drift rate and offset estimation for each NTP source.

$ sudo chronyc sourcestats -v
.- Number of sample points in measurement set.
                            /    .- Number of residual runs with same sign.
                           |    /    .- Length of measurement set (time).
                           |   |    /      .- Est. clock freq error (ppm).
                           |   |   |      /           .- Est. error in freq.
                           |   |   |     |           /         .- Est. offset.
                           |   |   |     |          |          |   On the -.
                           |   |   |     |          |          |   samples. \
                           |   |   |     |          |          |             |
Name/IP Address            NP  NR  Span  Frequency  Freq Skew  Offset  Std Dev
==============================================================================
ntp11.kashra-server.com    19  13  1046     +0.541      4.492  -3555us  1635us
ntp.coi.pw.edu.pl          17  10  1045     +0.047      0.159  -3833us    53us
s.complex.net.pl           19  13   979     -0.135      2.795   -118us   980us
ntp.tktelekom.pl           19  13   979     +0.104      3.404   +226us  1154us
ciskacz.of.pl               6   3   324   +318.852    810.065   +144ms    28ms
94-172-186-238.dynamic.c>  18  11  1046     +0.303      2.307  -3499us   841us
time.cloudflare.com        17  11  1044     +0.049      0.122   +310us    47us
46.175.224.7.maxnet.net.>  16   9   971     -0.454      2.881  +1962us   878us
ntp.ifj.edu.pl             12   5   713     +1.220      3.789  +7045us   627us
main.jakspzoo.pl           19  11   975     +1.826      2.811   +477us  1029us
time.cloudflare.com        14   6   851     -0.136      0.174   +334us    44us
ntp.wide-net.pl            19  11   980     +1.483      2.882   +463us   968us
ntp2.pl                    17  11   850     -0.282      1.626  -3957us   446us
time.taken.pl              13   6   591     -1.035      5.236  -5058us   770us
ntp.oa.uj.edu.pl           13  10   588     -0.313      4.574  +6037us   824us
ntp2.tktelekom.pl          13   8   587     -0.380      6.781   +445us  1177us
96-7.cpe.smnt.pl           19  12   981     +0.910      2.586  +2463us   938us
ntp1.pl                    13   6   587     -1.910      3.397  -4260us   460us
host-168-137.prnet.pl      20  12  1047     -1.658     26.042  +1591us  9982us
160.ip-54-37-233.eu        11   7   840     +0.868      0.537  -4204us   106us

Display the number of online and offline sources.

$ sudo chronyc activity
200 OK
20 sources online
0 sources offline
0 sources doing burst (return to online)
0 sources doing burst (return to offline)
0 sources with unknown address

Display the server statistics.

$ sudo chronyc serverstats
NTP packets received       : 5
NTP packets dropped        : 0
Command packets received   : 426
Command packets dropped    : 0
Client log records dropped : 0
NTS-KE connections accepted: 0
NTS-KE connections dropped : 0
Authenticated NTP packets  : 0

Display clients that have accessed the server

$ sudo chronyc clients
Hostname                      NTP   Drop Int IntL Last     Cmd   Drop Int  Last
===============================================================================
10.10.10.100                    7      0   6   -    11       0      0   -     -
10.10.10.254                    5      0   8   -   303       0      0   -     -

Read How to update system time using systemd to configure NTP on clients.

Client NTP status.

$ timedatectl timesync-status
Server: 10.10.1.16 (10.10.1.16)
Poll interval: 17min 4s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C21D82FC
    Precision: 1us (-21)
Root distance: 8.032ms (max: 5s)
       Offset: +1.118ms
        Delay: 677us
       Jitter: 653us
 Packet count: 5
    Frequency: +4,768ppm
ko-fi