Fix the NTP "unsynchronized" state on chrony, ntpd and w32tm
In the NTP protocol, the stratum field is an 8-bit integer identifying the distance from the reference atomic clock. Values 1–15 are valid operating strata. Stratum 16 is a sentinel value meaning "unsynchronized" — the daemon has no trusted time source. It is both:
The difference matters for diagnosis. Freshly-booted stratum 16 with a visible iburst countdown is normal. Stratum 16 after 30 minutes of uptime is a fault.
Run these three commands in order. Each one points to the most likely next cause.
$ chronyc tracking # overall sync status
$ chronyc sources -v # per-source reachability and selection
$ chronyc sourcestats -v # offset/jitter stability per source
$ ntpq -p # per-source table
$ ntpq -c rv # read variables: stratum, offset, jitter, dispersion
$ ntpq -c 'rv 0 stratum,offset,frequency,sys_jitter'
Read the output against the three common root causes below.
Signature in chronyc sources: every source shows ? or ~ in the selection column, and reach is 0. Signature in ntpq -p: all peers show .INIT. as their refid.
Fix sequence:
# 1. Test UDP 123 reachability
$ nc -u -vz ntp.rdem-systems.com 123
# or, if nc is not UDP-capable
$ ntpdate -q ntp.rdem-systems.com
# 2. Check firewall state
$ sudo iptables -L -n | grep 123
$ sudo firewall-cmd --list-all | grep ntp
$ sudo ufw status | grep 123
# 3. If blocked, open it
$ sudo ufw allow 123/udp # ufw
$ sudo firewall-cmd --add-service=ntp --permanent && sudo firewall-cmd --reload
Deep dive: the firewall guide covers iptables, firewalld, ufw and Windows Firewall.
Signature: sources are reachable (reach > 0), but the daemon refuses to step the clock. Logs mention "panic sanity" (ntpd) or "clock jump too large" (chrony).
Default thresholds:
| Daemon | Threshold | Directive |
|---|---|---|
| ntpd | 1000 s | tinker panic 0 (disable) or launch with -g |
| chrony | Configurable (no hard panic) | makestep 1.0 3 in chrony.conf |
| w32time | Varies (MaxPosPhaseCorrection / MaxNegPhaseCorrection) | Registry under HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config |
# One-shot step (manual)
$ sudo chronyc makestep
# Persist: allow step for first 3 clock updates if offset > 1s
# in /etc/chrony/chrony.conf
makestep 1.0 3
# One-shot step at start-up (past panic threshold)
$ sudo systemctl stop ntp
$ sudo ntpd -gq # query once with -g allowed
$ sudo systemctl start ntp
Signature: sources are reachable, offsets are small, but the selection column shows x (false ticker) or - (outlyer) on every peer. The daemon has no majority to agree with, so it stays at stratum 16.
Usually means you have an even number of sources and they split 50/50, OR one source is wildly wrong and drags the median. Fixes:
chronyc sourcestats -v — look for one source with offset > 3× the others — and treat it as a false ticker.On Windows, stratum 16 manifests as the unsynchronized state of w32time or TimeState::StateNoSync.
:: Query status
> w32tm /query /status
:: Force resync from authoritative peer
> w32tm /resync /force
:: Reconfigure manual peer list
> w32tm /config /manualpeerlist:"ntp.rdem-systems.com time.cloudflare.com" /syncfromflags:manual /update
> net stop w32time && net start w32time
> w32tm /resync /force
If the resync fails, check Windows Firewall allows outbound UDP 123.
Virtualisation adds a second time authority competing with NTP. Turn it OFF inside guests that run chronyd/ntpd:
vmtoolsd which can sync the guest to the host. Disable in /etc/open-vm-tools/tools.conf with time.synchronize.tools.startup = false and related flags.<clock offset="host"> with periodic sync. Use <clock offset="utc"/> and let chronyd handle it.After disabling host-guest sync, restart chronyd and wait 1–3 poll intervals (64–256 s default) for sync to lock.
Related diagnostic pages:
After the fix — related sites: