Fixing Clock Skew and Certificate Errors

Fixing Clock Skew and Certificate Errors

What You'll Learn

  • Why make's "Clock skew detected" warning and TLS's "certificate is not yet valid" share one root cause
  • How to tell whether a wrong clock is the culprit using date / openssl
  • How to fix the clock and restore both builds and certificate verification

Conclusion (triage pattern)

  • However varied the symptoms, the root is one thing: the system clock has drifted from real time
  • First confirm the drift is real with timedatectl and date -u
  • If it is, fix the clock with NTP, then re-touch any files with a future mtime

Assumptions (target environment)

  • OS: Ubuntu / Debian / RHEL family (systemd with chrony or systemd-timesyncd)
  • Mainly environments where the clock drifts easily: VMs, containers, Raspberry Pi

What is clock skew, and why does it break certificates and builds?

Conclusion: Clock skew is the system clock drifting from real time. Builds see file mtimes in the future, certificates see a validity window (notBefore) in the future, so both get rejected as "from the future."

Clock skew means a machine's system clock is off from the correct time. The direction of the drift changes the symptom.

  • Clock is behind (in the past) → a freshly issued certificate is judged "not yet valid"
  • Clock is ahead (in the future) → generated files get a future mtime, and build tools warn

The essence of this problem is that a seemingly unrelated build error and certificate error both come from the same time mismatch. A certificate has a time window — notBefore (valid from) and notAfter (valid until) — and make compares file freshness by mtime. Both rely on "the current time," so when that baseline itself is wrong, things break in a chain.

Common sources

  • VM suspend/resume or snapshot restore rewinds the clock
  • The host clock is already wrong when a container starts
  • A dead RTC (hardware clock) battery resets the time on every reboot
  • An NFS server and client disagree on the time (file mtimes look like the future)

How do I check whether the clock is wrong?

Conclusion: Check sync status with timedatectl and the current UTC with date -u, then compare against a trusted external time. A gap of tens of seconds or more points to clock skew.

Start by checking sync status and the current time.

$ timedatectl
               Local time: Sat 2026-06-06 12:00:00 UTC
           Universal time: Sat 2026-06-06 12:00:00 UTC
                 RTC time: Sat 2026-06-06 12:00:00
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: no
              NTP service: active

System clock synchronized: no is the tell. Next, compare against a trusted external time. An HTTP response Date header is a convenient reference.

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

If the two times differ by tens of seconds to minutes or more, clock skew is the cause. To avoid confusing this with a time-zone difference, always compare in UTC with date -u.

A wrong time zone (Time zone) is not clock skew. If the UTC value from date -u is correct, a difference in displayed local time is a time-zone issue and does not affect certificates or builds.

How do I fix the "Clock skew detected" build warning?

Conclusion: After fixing the clock, list files with a future mtime via find . -newermt now and reset them with touch. Rebuilding with make clean is the most reliable fix.

A typical warning during make:

make: Warning: File 'main.o' has modification time 9876 s in the future
make: warning:  Clock skew detected.  Your build may be incomplete.

This happens because a source or object file's mtime is in the future relative to the current system clock. Since make decides what to rebuild by comparing mtimes, future-dated files break dependency resolution and the build may end up incomplete.

The order is "1) fix the clock, then 2) fix the future mtimes." If you don't fix the clock first, touch just stamps the still-wrong current time again.

# 1. Fix the clock (details in #fix-clock below)
$ sudo timedatectl set-ntp true

# 2. Find files with a future mtime
$ find . -newermt now -type f

# 3. Reset them to the current time
$ find . -newermt now -type f -exec touch {} +

The most reliable approach is to discard intermediates and rebuild.

$ make clean && make

If this happens with sources on NFS, sync the clock on both the NFS server and client. Fixing only one side leaves future mtimes stamped by the other, and it recurs.

How do I fix "not yet valid / expired" certificates?

Conclusion: Check notBefore/notAfter with openssl x509 -noout -dates. If the current time is outside the window, suspect the clock. Fixing the clock usually resolves it without reissuing the certificate.

When the clock is wrong, verification fails even for a valid certificate. Typical messages by tool:

# curl
curl: (60) SSL certificate problem: certificate is not yet valid

# git clone (https)
fatal: unable to access '...': server certificate verification failed

# Go-based tools
x509: certificate has expired or is not yet valid

# apt update
E: Release file for ... is not valid yet (invalid for another 5h 30min ...)

The apt "is not valid yet" message is clear evidence of clock skew. Check the certificate's validity window with openssl.

# A local certificate file
$ openssl x509 -in cert.pem -noout -dates

# A remote server's certificate
$ echo | openssl s_client -connect example.com:443 2>/dev/null \
    | openssl x509 -noout -dates
notBefore=Jun  5 00:00:00 2026 GMT
notAfter=Sep  3 23:59:59 2026 GMT

If the current UTC (date -u) is before notBefore, you get "not yet valid"; if after notAfter, "expired." In both cases the certificate itself is fine, and fixing the clock resolves it.

Before reissuing a certificate or disabling verification with --insecure, always check the clock. If the cause is clock skew, swapping the certificate is pointless, and disabling verification only weakens security. If a CA bundle or incomplete chain is the cause, see Fixing "certificate verify failed".

How do I correct the clock properly?

Conclusion: Enable NTP with timedatectl set-ntp true and correct immediately with chronyc makestep. Write the time back to the RTC with hwclock --systohc so it survives reboots.

Enabling NTP sync is the baseline.

$ sudo timedatectl set-ntp true
$ timedatectl   # confirm: System clock synchronized: yes

When the drift is large, chrony corrects gradually for safety. To jump immediately, use makestep.

$ sudo chronyc makestep
$ chronyc tracking   # confirm the offset converges near 0

If the time keeps resetting after a reboot (e.g. a dead RTC battery), write the corrected system clock back to the hardware clock.

$ sudo hwclock --systohc

For how NTP sync works and when to choose systemd-timesyncd vs chrony, see Fixing Server Time Skew (NTP sync).

VM / container notes

  • A container shares the host kernel's clock. You can't run NTP inside the container, so fix the clock on the host
  • A VM can jump in time on resume or snapshot restore. Enable the hypervisor's guest time sync, or run NTP inside the guest

A checklist to prevent recurrence

Conclusion: Make NTP persistent, write the RTC back, and sync time across VMs and NFS pairs, and clock-skew build and certificate errors are largely preventable.

Measure Command / setting Effect
Keep NTP sync always on timedatectl set-ntp true Auto-corrects clock drift
Save correct time to the RTC hwclock --systohc Prevents reset after reboot
Detect early with monitoring Watch chronyc tracking offset Catches drift before an incident
Sync both NFS server and client Enable NTP on both hosts Prevents future-mtime recurrence

Copy-paste: clock skew diagnosis one-liner

# Check sync status, local UTC, and external time at once
timedatectl; echo "--- local UTC ---"; date -u; \
  echo "--- remote ---"; curl -sI https://www.google.com | grep -i '^date:'

Next Reading