Skip to content

Configuring and Troubleshooting Linux Time Synchronization with chrony

On Linux servers, accurate system time is important for log chronology, authentication, certificate validity periods, and comparing events across multiple systems.

On RHEL 8, chrony can be used for time synchronization. The chronyd daemon can be managed with systemctl, and synchronization status can be checked with chronyc.

In this article, we install chrony, configure an NTP server persistently, and then use waitsync, sources, and tracking to determine whether a problem lies in the configuration, reachability, time source selection, or system clock synchronization.

Values that need to be changed for each environment are represented by the following variable.

Variable nameExample settingDescription
<<NTP_SERVER>>time.cloudflare.comHostname of the NTP server used as the synchronization target

This configuration example uses Cloudflare’s public NTP service. Cloudflare identifies time.cloudflare.com as the endpoint for its NTP service.

If your organization specifies a particular NTP server, replace <<NTP_SERVER>> with its hostname.

Install the chrony package.

Terminal window
sudo dnf install -y chrony

Next, start chronyd and configure it to start automatically when the operating system boots.

Terminal window
sudo systemctl enable --now chronyd

Verify that the service is running and automatic startup is enabled.

Terminal window
sudo systemctl status chronyd --no-pager
sudo systemctl is-enabled chronyd

If systemctl status shows active (running) and systemctl is-enabled shows enabled, the chrony service is running and automatic startup is enabled.

Step 2: Configure the NTP server persistently

Section titled “Step 2: Configure the NTP server persistently”

The chrony server directive lets you specify an NTP server. The iburst option sends the initial queries to the time source at short intervals so that initial measurements can be collected more quickly.

For details, refer to the official chrony configuration file manual.

Here, the existing /etc/chrony.conf is backed up once, and the specified NTP server is added only if it is not already configured.

Terminal window
if [ ! -e /etc/chrony.conf.before-ntp ]; then
sudo cp -a /etc/chrony.conf /etc/chrony.conf.before-ntp
fi
if ! sudo grep -Fqx 'server <<NTP_SERVER>> iburst' /etc/chrony.conf; then
printf '%s\n' 'server <<NTP_SERVER>> iburst' | sudo tee -a /etc/chrony.conf >/dev/null
fi
sudo grep -F 'server <<NTP_SERVER>> iburst' /etc/chrony.conf

This procedure does not automatically remove existing server or pool settings. If time sources must be restricted in the actual environment, organize the existing configuration according to your organization’s NTP design.

Restart chronyd to apply the configuration. Then verify that the service is running, the specified configuration remains in the file, and chronyd recognizes the specified time source.

Terminal window
sudo systemctl restart chronyd
sudo systemctl is-active chronyd
sudo grep -F 'server <<NTP_SERVER>> iburst' /etc/chrony.conf
sudo chronyc -N sources | grep -F '<<NTP_SERVER>>'

If is-active shows active and both the configuration line and <<NTP_SERVER>> can be confirmed, the time source configuration has been saved to the file and is still loaded after restarting chronyd.

Step 3: Wait for synchronization with waitsync

Section titled “Step 3: Wait for synchronization with waitsync”

Even after configuring the NTP server and restarting chronyd, the system is not necessarily synchronized immediately. chronyd performs measurements against the time source and determines whether it can be used for synchronization.

chronyc waitsync waits until chronyd is synchronized. The official chrony 4.4 manual defines the following syntax:

waitsync [max-tries [max-correction [max-skew [interval]]]]

The first argument is the maximum number of attempts, the second is the allowed remaining time correction, the third is the allowed skew, and the fourth is the check interval. If the second or third argument is set to 0, no limit is applied for that value.

Here, synchronization is awaited for up to 60 attempts at 2-second intervals.

Terminal window
sudo chronyc waitsync 60 0 0 2

If the command exits successfully, chronyd is synchronized with an available time source. If synchronization cannot be established within the maximum number of attempts, the command exits with a nonzero status. In that case, use sources and tracking to investigate the cause.

Step 4: Check time source status and reachability with sources

Section titled “Step 4: Check time source status and reachability with sources”

chronyc sources lets you check the selection status, reachability, and measurement status of each time source referenced by chronyd. Adding -v displays explanations of the columns, while -N displays the original name instead of the address after name resolution.

Display detailed information about the specified time source and verify that responses are being received.

Terminal window
sudo chronyc -N sources -v
sudo chronyc -N sources | awk -v host='<<NTP_SERVER>>' '
$2 == host {
found = 1
reach = $5 + 0
if (reach > 0) {
reachable = 1
}
}
END {
exit !(found && reachable)
}
'

In sources, check the following items in particular:

  • ^ in the M column indicates an NTP server.
  • * in the S column indicates the currently selected time source.
  • + in the S column indicates a time source being used together with the selected source.
  • ? in the S column indicates that no measurements suitable for selection are available.
  • Reach shows the response history for recent NTP requests as an 8-bit octal value.
  • LastRx shows the time elapsed since the last valid measurement was received.

The verification command above exits successfully only when <<NTP_SERVER>> exists in sources and Reach is greater than 0. This confirms that chronyd recognizes the configured time source and has received at least one NTP response.

If <<NTP_SERVER>> is displayed but Reach remains 0, the configuration itself may be recognized even though NTP communication is not succeeding. Check DNS resolution, the network path for UDP/123, network-side filtering, and whether the NTP server is responding.

Step 5: Check system clock synchronization status with tracking

Section titled “Step 5: Check system clock synchronization status with tracking”

While sources shows the state of individual time sources, tracking lets you check the overall synchronization state of the system clock managed by chronyd.

Display synchronization information and check the reference, stratum, time difference, and synchronization status.

Terminal window
tracking="$(sudo chronyc tracking)"
printf '%s\n' "$tracking"
printf '%s\n' "$tracking" | grep -F 'Reference ID'
printf '%s\n' "$tracking" | grep -F 'System time'
printf '%s\n' "$tracking" | grep -F 'Leap status' | grep -F 'Normal'
printf '%s\n' "$tracking" | awk -F: '
/^[[:space:]]*Stratum[[:space:]]*:/ {
value = $2 + 0
found = 1
if (value > 0) {
ok = 1
}
}
END {
exit !(found && ok)
}
'

Check the following fields in particular:

  • Reference ID: currently referenced time source
  • Stratum: NTP stratum of the local system
  • System time: remaining difference between the system clock and NTP time
  • Last offset: offset estimated during the last clock update
  • RMS offset: RMS value of the offsets
  • Skew: error range of the frequency estimate
  • Root delay: cumulative delay to the reference time source
  • Root dispersion: estimated error relative to the reference time
  • Leap status: leap-second and synchronization status

This check verifies that Stratum is greater than 0 and that Leap status is Normal. Because System time is also displayed, you can check not only synchronization status but also the currently remaining time difference.

Step 6: Combine sources and tracking to isolate the problem

Section titled “Step 6: Combine sources and tracking to isolate the problem”

Finally, combine sources and tracking.

Receiving responses from the specified NTP server in sources and having the local system in a synchronized state in tracking are separate checks. Checking both together lets you distinguish between time source reachability and system clock synchronization.

Terminal window
sources="$(sudo chronyc -N sources)"
tracking="$(sudo chronyc tracking)"
printf '%s\n' "$sources"
printf '%s\n' "$tracking"
printf '%s\n' "$sources" | awk -v host='<<NTP_SERVER>>' '
$2 == host {
found = 1
reach = $5 + 0
if (reach > 0) {
reachable = 1
}
}
END {
exit !(found && reachable)
}
'
printf '%s\n' "$tracking" | grep -F 'Leap status' | grep -F 'Normal'

If this check exits successfully, both of the following conditions are true:

  1. NTP responses are being received from <<NTP_SERVER>>.
  2. The local system clock is synchronized.

The results can be interpreted as follows:

sourcestrackingMain areas to check
Target server is not displayedNot synchronizedContents of /etc/chrony.conf, whether the configuration was applied, hostname specification
Target server is displayed but Reach is 0Not synchronizedDNS, UDP/123, network path, NTP server response
Reach is greater than 0 but the source is not selectedNot synchronized or synchronized to another time sourceState of the S column, measurement status, comparison with other time sources
Reach is greater than 0Leap status: NormalNTP reachability and system clock synchronization are established

With chrony time synchronization, it is not sufficient to determine that everything is working solely because chronyd is running.

First, configure the time source persistently in /etc/chrony.conf and verify that chronyd still recognizes the setting after a restart. Then use waitsync to wait for synchronization, use sources to check the time source selection state, Reach, and measurement status, and use tracking to check the reference, stratum, system time difference, and synchronization status.

When investigating time drift, checking the configuration, time source reachability, time source selection, and system clock synchronization separately makes it easier to identify the stage at which the problem is occurring.

Category: Linux