Clock Drift
My Arch desktop had drifted about a minute ahead of the two clocks I don’t usually think to question: my radio-controlled Casio GW-B5600 and my phone. The watch corrects itself from longwave radio and the phone has network time, so when both of them agree against the desktop, it’s a safe bet the desktop is the one in the wrong.
timedatectl was the first stop:
$ timedatectl status
Local time: Sat 2025-01-04 08:11:01 PST
Universal time: Sat 2025-01-04 16:11:01 UTC
RTC time: Sat 2025-01-04 16:11:01
Time zone: America/Los_Angeles (PST, -0800)
System clock synchronized: no
NTP service: inactive
RTC in local TZ: no
Two lines matter here:
System clock synchronized: no
NTP service: inactive
Nothing was disciplining the clock. At boot, Linux reads the RTC, then advances time from hardware timers. Without NTP, nothing compares that against an external reference and nudges it back.
So the desktop was just another quartz clock. Manufacturing tolerance sets the baseline, and temperature and power state keep shifting the rate around.
The good news was RTC in local TZ: no. The hardware clock was UTC, which is
what I want on Linux. Only the system clock was off.
The fix was to enable time synchronization:
sudo timedatectl set-ntp true
sudo systemctl enable --now systemd-timesyncd.service
After a few packets, timedatectl looked much healthier:
$ timedatectl status
Local time: Sat 2025-01-04 08:18:42 PST
Universal time: Sat 2025-01-04 16:18:42 UTC
RTC time: Sat 2025-01-04 16:18:42
Time zone: America/Los_Angeles (PST, -0800)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
The more interesting output comes from timedatectl timesync-status:
$ timedatectl timesync-status
Server: 141.11.228.173 (0.arch.pool.ntp.org)
Poll interval: 34min 8s (min: 32s; max 34min 8s)
Leap: normal
Version: 4
Stratum: 2
Reference: 11FD0225
Precision: 1us (-26)
Root distance: 1.052ms (max: 5s)
Offset: +4.917ms
Delay: 81.811ms
Jitter: 3.721ms
Packet count: 8
Frequency: +4.873ppm
Serveris the active NTP peer drawn from the pool, so the exact IP doesn’t matter much.Poll intervalis how often the client asks for time, stretching out as the local clock looks more stable.Leapis leap-second state, andnormalmeans none is pending.Versionis the NTP protocol version, and4is what you should see.Stratumis the hop distance from a primary reference like GPS or a radio clock, with stratum 2 (synced from a stratum 1) being normal for a desktop on the public internet.Referenceis the server’s upstream identifier, mainly useful when debugging the server side.Precisionis what the server advertises for its own clock, which feeds into the error estimate but says nothing about my desktop on its own.Root distanceis the estimated maximum gap from true reference time after delay and accumulated error, around a millisecond here and well under the five second max.Offsetis the current difference between my local clock and the server’s, and a few milliseconds over the public internet is fine.Delayis the round-trip to the server, around 82ms here, which is unsurprising for public NTP.Jitteris the variation between samples, where lower is better and a few milliseconds is fine.Packet countis how many samples have gone into the current estimate, and the kernel needs a handful before it trusts it.
That leaves Frequency, the field that explains the original symptom. It’s
the rate correction the kernel has learned for the local oscillator, in parts
per million. At +4.873ppm, the desktop was running roughly 4.873 microseconds
per second too fast:
4.873 ppm * 86,400 seconds/day = 0.421 seconds/day
Tiny per second, but it accumulates. Half a second per day is a few seconds per week. Add RTC drift while the machine is powered off, and the gap against a radio-controlled watch becomes hard to miss.
Once the system clock is correct, write it back to the RTC:
sudo hwclock --systohc --utc
That way the next boot starts close. NTP still corrects after the network comes up, but starting closer beats starting far off.
No mystery. The desktop had been keeping time on its own while the watch and phone were checking in with the outside world. Once NTP was back on, the desktop joined them, and the drift fell into the usual millisecond-scale noise of internet time sync.