How to Configure Chrony as a Time Server on RHEL 7
Accurate system time is foundational to almost every enterprise workload. Kerberos authentication, TLS certificate validation, log correlation, and database replication all depend on clocks that stay in sync. While ntpd has served Linux administrators for decades, Red Hat Enterprise Linux 7 ships Chrony as the default NTP implementation. Chrony converges faster after network interruptions, handles virtual machine clock drift more gracefully, and consumes fewer resources. This tutorial walks you through promoting a RHEL 7 host into a dedicated Chrony time server that synchronises from upstream NTP pools and then serves accurate time to the rest of your internal network.
Prerequisites
- A RHEL 7 server with a static IP address (e.g.,
192.168.10.5) that all clients can reach. - Root or
sudoaccess on the server and at least one test client. yumaccess to a configured repository (RHEL subscription, local mirror, or CentOS 7 equivalent).- Firewalld running (the default on RHEL 7) or iptables configured.
- Basic familiarity with editing files using
viornano.
Step 1: Install Chrony
Chrony is included in the base RHEL 7 repositories. Install both the daemon and the command-line tool in one step:
sudo yum install -y chrony
Verify the installed version:
chronyc --version
You should see output similar to chronyc (chrony) version 3.4. The main binary is chronyd (the daemon) and the control utility is chronyc.
Step 2: Configure /etc/chrony.conf for Server Role
The default configuration file already points to the RHEL/CentOS NTP pool. You need to add two critical directives: allow (to permit clients to query this server) and local (to serve time even when upstream sources are unreachable). Open the file:
sudo vi /etc/chrony.conf
A complete production-ready configuration looks like this:
# Upstream NTP pool servers
server 0.rhel.pool.ntp.org iburst
server 1.rhel.pool.ntp.org iburst
server 2.rhel.pool.ntp.org iburst
server 3.rhel.pool.ntp.org iburst
# Record drift in this file so chronyd can compensate on restart
driftfile /var/lib/chrony/drift
# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second
makestep 1.0 3
# Enable kernel synchronisation of the real-time clock (RTC)
rtcsync
# Allow NTP client access from the local network
allow 192.168.10.0/24
# Serve time even when not synchronised to an upstream source
# stratum 10 signals "I am locally authoritative but not ideal"
local stratum 10
# Log tracking, measurements, and statistics
logdir /var/log/chrony
log tracking measurements statistics
The allow directive accepts a subnet in CIDR notation. Replace 192.168.10.0/24 with your actual internal network. The local stratum 10 directive is crucial for isolated networks: it causes Chrony to advertise itself as a valid (if lower-quality) time source even if the upstream pool is unreachable, preventing clients from falling back to their CMOS clock independently.
Step 3: Open the Firewall for NTP Traffic
NTP uses UDP port 123. Add a permanent firewall rule and reload:
sudo firewall-cmd --permanent --add-service=ntp
sudo firewall-cmd --reload
sudo firewall-cmd --list-services
The ntp service definition in firewalld already maps to UDP/123, so you do not need to specify the port manually. If you prefer explicit port syntax:
sudo firewall-cmd --permanent --add-port=123/udp
sudo firewall-cmd --reload
Step 4: Start and Enable chronyd
sudo systemctl enable chronyd
sudo systemctl start chronyd
sudo systemctl status chronyd
The status output should show active (running). Look for the line beginning with Selected source in the journal to confirm upstream synchronisation:
sudo journalctl -u chronyd -n 30
Step 5: Verify Server Synchronisation with chronyc
The chronyc tracking command shows the current reference source, stratum, and offset:
chronyc tracking
Expected output:
Reference ID : A9FEA97B (time.example.com)
Stratum : 2
Ref time (UTC) : Sun May 17 10:22:14 2026
System time : 0.000012345 seconds fast of NTP time
Last offset : +0.000012340 seconds
RMS offset : 0.000008123 seconds
Frequency : -15.234 ppm fast
Residual freq : -0.001 ppm
Skew : 0.023 ppm
Root delay : 0.024156 seconds
Root dispersion : 0.001284 seconds
Update interval : 64.2 seconds
Leap status : Normal
To see all current time sources and their reachability:
chronyc sources -v
The * symbol next to a source means it is the currently selected reference. An x means the source is considered a falseticker and is excluded.
Step 6: Configure Clients to Point at Your Server
On each RHEL 7 client, edit /etc/chrony.conf and replace the pool lines with your server’s IP:
# Remove or comment out the pool lines, then add:
server 192.168.10.5 iburst prefer
Restart chronyd on the client:
sudo systemctl restart chronyd
chronyc tracking
The Stratum field on the client should now read 3 (one higher than the server’s stratum of 2).
Step 7: List Connected Clients with chronyc
Once clients are configured, the server can report which clients are actively polling it:
chronyc clients
Sample output:
Hostname NTP Drop Int IntL Last Cmd Drop Int Last
===============================================================================
192.168.10.20 47 0 6 - 23 0 0 - -
192.168.10.21 52 0 6 - 18 0 0 - -
For per-source statistics including estimated error and frequency offset per client, use:
chronyc sourcestats -v
Step 8: CMOS Fallback and stratum Levels Explained
Without the local stratum 10 directive, if all upstream servers become unreachable, chronyd stops advertising as a time source and clients degrade to their hardware clock (CMOS). The local directive prevents this. Stratum values range from 1 (directly connected to a reference clock like GPS) to 15 (reachable but many hops away). Stratum 16 means “unsynchronised.” Your server will be stratum 2 when synced from the pool (pool servers are typically stratum 1–2), and will fall back to stratum 10 only when isolated.
Step 9: Compare Chrony with ntpd
You may encounter documentation that still references ntpd. Red Hat deprecated ntpd in RHEL 7 in favour of Chrony. The key differences are:
- Convergence speed: Chrony adjusts the clock faster after a step change, which is critical in VMs that can lose time during live migration.
- Intermittent connectivity: Chrony handles network links that come and go (laptops, VPN clients) better than
ntpd. - Resource use:
chronydis a smaller binary and uses less CPU than the equivalentntpdprocess. - Compatibility: Both use the same NTP wire protocol; clients do not know or care which daemon is running on the server.
If you must run ntpd for compatibility (e.g., legacy hardware appliances that require broadcast NTP), install the ntp package and use ntpstat and ntpq -p for monitoring. However, for all modern RHEL 7 deployments, Chrony is the recommended choice.
Conclusion
You now have a fully operational Chrony time server on RHEL 7. It synchronises from the public NTP pool, serves accurate time to your entire subnet via the allow directive, and falls back to local stratum 10 if upstream connectivity is lost. You have opened the firewall for UDP/123, verified synchronisation with chronyc tracking, inspected source quality with chronyc sources, and confirmed that clients are polling your server with chronyc clients. A centralised, well-configured time server dramatically simplifies troubleshooting across your infrastructure: when every host agrees on the time, log correlation becomes straightforward and authentication failures caused by clock skew disappear.