Ahosting Logo
Knowledge Base

Why a Server Clock Matters and How to Keep It Right

What a wrong clock breaks, and why nothing mentions timeAll of these have one cause and none of them say soTwo-factor codesgenerated from the current time;drift makes them all wrongCertificatesa valid certificate reads as notyet valid, or expiredSigned API requestsrejected as replayed or staleLog correlationevents in the wrong order acrossmachinesScheduled jobsrunning at the wrong time, ortwiceThe fixtime synchronisation enabled,which is one commandA set of unrelated authentication failures appearing at once is worth one clock check before anything else.

A wrong clock produces a collection of faults that appear unrelated, none of which mentions the time. It is one of the cheapest things to check and one of the last things anyone checks.

What breaks

Two-factor authentication. Codes are generated from the current time. A clock several minutes out rejects every correct code, and the user is certain they typed it right, because they did.

Certificate validation. A certificate is valid between two moments. A clock set in the past reports a perfectly good certificate as not yet valid, and connections fail with an error that appears to be about the certificate.

Scheduled jobs. They run on the machine's clock and time zone, which may not be the one you are thinking in. A backup scheduled for 02:00 running at 21:00 local is not a cron fault.

Log correlation. Comparing a web server log with an application log across two machines is impossible if their clocks disagree, and this is exactly the situation where you most need to.

Signed API requests. Many services reject requests whose timestamp is outside a tolerance, usually a few minutes. The error is typically about authentication.

Checking

timedatectl

The line to read is System clock synchronized. If it says no, the clock is drifting and will keep drifting.

Compare against something external:

date -u
curl -sI https://google.com | grep -i '^date'

A few seconds of difference is normal. Minutes is a problem.

Fixing it

On most current systems the service is already installed and simply needs enabling:

timedatectl set-ntp true
systemctl status systemd-timesyncd

Where chrony is used instead:

systemctl enable --now chronyd
chronyc tracking
chronyc sources

chronyc tracking reports the current offset, which is the number that tells you whether it is working.

Set the machine to UTC

timedatectl set-timezone UTC

This is worth doing deliberately on servers.

UTC has no daylight saving, so there is no hour that occurs twice a year and no hour that does not exist; both of which cause scheduled jobs to run twice or not at all. Comparing logs from two servers becomes reading, not arithmetic.

Display in local time in the application, where a person is reading it. Store and log in UTC.

If you change the time zone, restart services that cached it. A web server and a database will keep reporting the old zone until they do, which produces a confusing period where different components disagree.

Why containers and virtual machines drift

A container usually shares the host's clock, so fixing it inside the container does nothing. The host is where to correct it.

A virtual machine can drift after being paused, migrated or restored from a snapshot. It resumes believing the time it was suspended at. If a machine that was fine yesterday is now minutes out, this is usually why, and it will recur unless synchronisation is running.

Do not correct it by hand

date -s "2026-08-20 14:30:00"

Tempting and wrong. It fixes the moment and not the drift, so the clock is wrong again within weeks, and a large manual jump can confuse running services more than the drift did.

Enable synchronisation instead. It corrects gradually, keeps correcting, and needs no attention.

Where it should be on the checklist

Add it to provisioning, so every server has synchronisation enabled and UTC set before anything is installed. For the same stage, see setting up automatic security updates.

And add it to the list of things to check when something inexplicable happens. Two-factor codes failing, a certificate rejected on one machine and accepted everywhere else, jobs running at odd hours. The common cause is worth ruling out in the ten seconds it takes.

Common VPS issues and how to troubleshoot them goes into the rest of that list.

Measure the offset rather than guessing

"The clock looks right" is not a measurement. The number that matters is the offset from a reference, in milliseconds.

chronyc tracking | grep -E 'System time|Last offset'
timedatectl timesync-status 2>/dev/null | head
ntpdate -q pool.ntp.org 2>/dev/null | tail -1

A few milliseconds is normal. Anything approaching a minute is a problem, and the threshold that matters depends on what the machine does: two-factor codes tolerate roughly thirty seconds, signed API requests frequently less.

Record the figure when the machine is healthy, so a later reading has something to be compared against. Benchmarking a server meaningfully explains the same principle for the other baselines.

When synchronisation is running and not working

The service being active is not the same as the clock being correct, and this is the state that produces the most confusion.

chronyc sources -v
systemctl status chronyd --no-pager | tail -5

Look at whether any source is actually selected. A machine with sources listed but none chosen is not synchronising, and the usual cause is outbound UDP on port 123 being blocked by a firewall, which is easy to do accidentally when tightening rules.

That is worth checking specifically after any firewall change, because the symptom appears days later as drift rather than immediately as an error. Configuring a firewall without locking yourself out walks through the rules.

Two machines that disagree

The practical failure is rarely one machine being wrong in isolation; it is two machines disagreeing, which breaks anything spanning both.

A web server and a database with different clocks produce records timestamped inconsistently. A load balancer and its backends produce logs that cannot be correlated. A backup server and its source disagree about which file is newer, which can cause the wrong version to be kept.

for h in web1 db1 cache1; do printf '%-10s %s\n' "$h" "$(ssh $h date -u +%T.%N)"; done

Run that occasionally across a set of machines. They should agree to within a fraction of a second, and a divergence is worth investigating before it produces a fault nobody can explain.

The application has its own idea of time

Fixing the system clock does not necessarily fix what the application records, because several layers keep their own timezone setting.

php -i | grep '^date.timezone'
mysql -e "SELECT @@global.time_zone, @@session.time_zone, NOW(), UTC_TIMESTAMP();"

A database in one zone and PHP in another produces records whose timestamps are internally inconsistent, and the discrepancy is a fixed number of hours, which is the signature to look for.

Set both explicitly rather than relying on defaults, and prefer UTC in storage with conversion at display time. That removes the whole class of problem rather than managing it. Where server logs live deals with why correlating logs depends on it.