Keeping Linux Clocks in Sync with chrony and NTP
Clock drift causes weird, expensive bugs that look like everything except a time problem. Here's how I keep Linux servers in sync with chrony.
- #linux
- #chrony
- #ntp
- #time-sync
- #troubleshooting
- #networking
Time synchronization is the most boring thing on a server until the moment it isn’t. Then it’s TLS handshakes failing because a cert “isn’t valid yet,” Kerberos tickets getting rejected, log timelines that don’t line up across hosts, distributed locks misbehaving, and database replication throwing errors that make no sense. Every one of those looks like a different problem. All of them can be a clock that drifted a few seconds. I’ve watched a team burn a day on a “networking issue” that was a VM whose clock had wandered 40 seconds off.
Modern Linux has settled on chrony for this, and it’s better at the job than the old ntpd ever was — especially on VMs and machines that sleep or have unreliable network. Here’s how I set it up and verify it’s actually working.
chrony vs systemd-timesyncd vs ntpd
Three things you’ll encounter:
ntpd— the classic, still around, fine but largely superseded.systemd-timesyncd— a lightweight SNTP client built into systemd. It’s good enough for a laptop or a leaf node that just needs roughly-correct time. It is not a full NTP implementation and can’t serve time to others.chrony— the right default for servers. It disciplines the clock faster after boot, handles intermittent connectivity, copes with virtualization clock jumps, and can act as a server for your other hosts.
For anything in a data center, use chrony.
Install and the basic config
sudo apt install chrony # or: sudo dnf install chrony
sudo systemctl enable --now chronyd
The config lives in /etc/chrony/chrony.conf (Debian) or /etc/chrony.conf (RHEL). A sane server config:
# Upstream sources. pool gives you several servers from one line.
pool 2.pool.ntp.org iburst
# Allow the clock to step (not just slew) if it's way off at start
makestep 1.0 3
# Record the drift so the clock is good right after a reboot
driftfile /var/lib/chrony/drift
# Sync the hardware (RTC) clock from the system clock
rtcsync
iburst makes the initial sync fast — a handful of quick packets instead of waiting minutes. makestep lets chrony jump the clock during the first few updates if it’s grossly wrong; after that it slews (speeds up or slows down the clock gradually) so time never runs backwards under a running application.
Run your own internal time server
In a fleet, you don’t want 500 hosts all hammering public pools — and you want them agreeing with each other more than with the outside world. Stand up two or three internal chrony servers that sync upstream, and point everything else at them:
# On the internal server, allow your subnet to query it
allow 10.0.0.0/8
# Serve local time even if upstream is unreachable (stratum 10)
local stratum 10
Then clients just use server timehost1.internal iburst lines. This keeps your fleet internally consistent, which is what actually matters for distributed systems.
Verify it’s working — the commands that matter
Installing chrony isn’t the job; confirming sync is.
# Are we synced, and how far off?
chronyc tracking
Look at System time (offset from true time) and Leap status — you want Normal and an offset measured in microseconds or low milliseconds.
# Which sources are we using, and which is selected?
chronyc sources -v
The * next to a source means it’s the currently selected sync peer. A ? or no selected source means you’re not actually syncing — investigate before you trust the clock.
# How much error and drift?
chronyc sourcestats
And the system-level view:
timedatectl status # 'System clock synchronized: yes' is what you want
The mistakes that bite people
- Two time daemons fighting. If
systemd-timesyncdandchronydare both running, they fight over the clock. Pick one:sudo systemctl disable --now systemd-timesyncdwhen you install chrony. - Firewall blocking UDP 123. NTP is UDP port 123. If your sources never select (
chronyc sourcesshows them but none get a*), check egress for UDP/123 before anything else. - Wrong timezone vs wrong time.
timedatectlshows both. A wrong timezone is a display issue fixed withtimedatectl set-timezone. A wrong time is a sync issue. Don’t confuse them. - VMs that pause. Snapshotted or migrated VMs can resume with a badly skewed clock. chrony’s
makestephandles the catch-up, which is one reason it beats ntpd on virtualized fleets.
Where AI fits
Time-sync debugging is mostly about interpreting the verification output, and that’s a clean fit for a model. I paste the full chronyc tracking and chronyc sources -v output and ask “is this host actually synced, and if not, what’s the most likely cause?” The model reads the offset, the stratum, and the source selection state and tells me where to look — far faster than recalling what sourcestats columns mean. Keep a couple of Linux troubleshooting prompts for parsing this output and you cut the guesswork.
The short version
Use chrony on servers. Configure a pool, enable makestep and rtcsync, and for a fleet run two or three internal servers everyone points at. Then verify with chronyc tracking and chronyc sources — installation without verification is how clocks silently drift for months. Get this boring layer right and a whole category of bizarre, time-shaped bugs simply never happens. For more foundational ops, see the AI for Linux Admins guides.
Time configuration affects authentication, certificates, and distributed systems. Verify synchronization with chronyc before relying on a host’s clock in production.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.