Accurate timekeeping is critical in enterprise Linux environments. Kerberos authentication, TLS certificate validation, log correlation, and distributed system coordination all depend on clocks being tightly synchronised across hosts. On RHEL 9, Chrony is the default NTP implementation, replacing the older ntpd daemon. This tutorial walks through configuring a dedicated Chrony NTP server on RHEL 9 and pointing client machines at it.

Prerequisites

  • RHEL 9 server with a static IP address (e.g., 192.168.1.10) on the local network
  • Root or sudo access on the server and client machines
  • Network connectivity between the server and clients
  • Firewall access to UDP port 123 (NTP)

Step 1 — Install Chrony

Chrony is usually installed by default on RHEL 9, but install it explicitly to be certain.

dnf install -y chrony
systemctl enable --now chronyd
systemctl status chronyd

Confirm the version in use:

chronyc --version

Step 2 — Configure the NTP Server

Edit /etc/chrony.conf on the machine that will act as the NTP server for your local network. The default file references upstream public pools; you will add directives to allow local clients to query this server.

# /etc/chrony.conf — NTP server configuration

# Use the RHEL NTP pool as upstream sources
pool 2.rhel.pool.ntp.org iburst

# Record the rate at which the system clock gains/loses time
driftfile /var/lib/chrony/drift

# Allow the system clock to be stepped (corrected instantly) in the first three
# updates if it is off by more than 1 second, rather than slewing slowly
makestep 1.0 3

# Enable kernel synchronisation of the real-time clock (RTC)
rtcsync

# Allow clients on this subnet to query this server
allow 192.168.1.0/24

# Serve time even when not synchronised to upstream (stratum 10 = local fallback)
local stratum 10

# Logging
logdir /var/log/chrony

Restart Chronyd to apply the changes:

systemctl restart chronyd

Step 3 — Open the Firewall

NTP uses UDP port 123. Allow it through the firewall and reload the rules:

firewall-cmd --permanent --add-service=ntp
firewall-cmd --reload
firewall-cmd --list-services

Step 4 — Verify Synchronisation on the Server

Use the chronyc command-line client to inspect the synchronisation state. These three commands give different levels of detail.

# High-level synchronisation summary
chronyc tracking

# List time sources with verbose column headers
chronyc sources -v

# Source statistics (frequency offset, jitter)
chronyc sourcestats

# Confirm the server is reachable and clients are connecting
chronyc clients

The tracking output shows the reference source, system time offset, RMS offset, frequency error, and stratum. A stratum value of 2 means this server is one hop away from a stratum-1 reference clock. The * symbol next to a source in sources output indicates the currently selected source.

Step 5 — Configure Client Machines

On each client machine (also running RHEL 9), edit /etc/chrony.conf to point at the server you just configured instead of the public pool:

# /etc/chrony.conf — NTP client configuration

# Use the internal NTP server
server 192.168.1.10 iburst prefer

# Keep the drift file
driftfile /var/lib/chrony/drift

# Step the clock quickly if offset exceeds 1 second (first 3 updates)
makestep 1.0 3

# Sync the hardware clock
rtcsync

Restart Chronyd on each client and confirm it is using your server:

systemctl restart chronyd
chronyc sources -v

You should see 192.168.1.10 listed as the selected source with a * marker.

Step 6 — Hardware Clock and Manual Operations

After the system clock is synchronised, write the time to the hardware (BIOS/UEFI) clock so it persists across reboots:

# Sync system clock to hardware clock
hwclock --systohc

# Read the hardware clock
hwclock --show

# Manually add or remove an NTP source at runtime (no restart required)
chronyc add server 192.168.1.20 iburst
chronyc delete 192.168.1.20

# Force an immediate time check and slew
chronyc makestep

The makestep command is particularly useful after a VM live migration or a long suspend where the clock may have drifted significantly. Note that a sudden step (as opposed to a gradual slew) can confuse applications that rely on monotonically increasing timestamps, so use it deliberately in production.

For Kerberos environments, clocks must be within five minutes of the KDC. With Chrony correctly configured, this tolerance is easily maintained. For TLS, certificate validity windows are enforced against the system clock, making NTP an indirect security dependency.

Conclusion

You have installed and configured Chrony as a local NTP server on RHEL 9, allowed client machines on your subnet to synchronise against it, verified synchronisation using chronyc tracking and source commands, and written the synchronised time to the hardware clock. Your infrastructure now has a reliable internal time source that reduces dependence on external internet connectivity for time accuracy.

Next steps: How to Configure Kerberos Authentication on RHEL 9, How to Set Up a PXE Boot Server on RHEL 9, and How to Configure LDAP Client Authentication with SSSD on RHEL 9.