Configure Chrony NTP on VPS — Accurate Time Sync

September 2026 · 7 min read

Configure Chrony NTP Server on VPS for accurate time synchronization

One of the most overlooked steps when setting up a VPS is configuring time synchronization. Clock drift — where your server's clock gradually diverges from real time — causes a cascade of subtle problems: SSL/TLS certificates fail validation before their actual expiry, cron jobs run at the wrong times, log timestamps become unreliable, and authentication tokens get rejected because the server clock is out of sync with the issuing authority. Chrony is a modern NTP implementation designed to replace the older ntpd, providing faster sync, lower resource usage, and robust handling of intermittent network connectivity — making it ideal for cloud VPS environments.

Why Chrony Instead of systemd-timesyncd?

Ubuntu ships with systemd-timesyncd enabled by default, but it's only a simple SNTP client that syncs once at boot and applies drift corrections slowly. Chrony is a full NTP implementation that:

Featuresystemd-timesyncdChronyntpd (legacy)
ProtocolSNTPNTPv4NTPv4
Continuous adjustmentNoYesYes
NTP Server modeNoYesYes
NTS (encrypted)NoYes (v4.0+)No
Memory footprintVery lowLowMedium
VPS suitabilityAdequateRecommendedWorks

Install Chrony on Ubuntu/Debian

# Update package list
sudo apt update

# Install Chrony
sudo apt install -y chrony

# Verify installed version
chronyc --version
Note: Chrony is available in the default repositories on Ubuntu 22.04+ and Debian 11+ — no PPA or third-party repository required.

Disable systemd-timesyncd Before Using Chrony

Running both at the same time will cause conflicts over control of the system clock:

# Check if timesyncd is running
systemctl status systemd-timesyncd

# Stop and disable timesyncd
sudo systemctl stop systemd-timesyncd
sudo systemctl disable systemd-timesyncd

# Enable Chrony and start it now
sudo systemctl enable --now chrony

Configure /etc/chrony/chrony.conf

The main configuration file is at /etc/chrony/chrony.conf. The default Ubuntu config uses the Ubuntu NTP pool, which works well out of the box. Here's a recommended configuration for general-purpose VPS use:

sudo nano /etc/chrony/chrony.conf
# NTP servers — use pool.ntp.org or your datacenter's NTP servers
pool 0.pool.ntp.org iburst maxsources 4
pool 1.pool.ntp.org iburst maxsources 4
pool time.cloudflare.com iburst

# Drift file — records the clock drift rate
driftfile /var/lib/chrony/chrony.drift

# Log directory (remove if not needed)
logdir /var/log/chrony

# Allow NTP clients from this network (if acting as NTP server)
# allow 192.168.1.0/24

# Allow a large one-time step on first startup
makestep 1.0 3

# Sync the RTC (hardware clock) to system time
rtcsync

# Leap second handling
leapsectz right/UTC

Save the file and restart Chrony:

sudo systemctl restart chrony

Set the Correct Timezone

NTP always synchronizes to UTC, but you should also set the correct local timezone for your server:

# Show current timezone settings
timedatectl

# List available timezones
timedatectl list-timezones | grep Asia

# Set timezone (example: Bangkok)
sudo timedatectl set-timezone Asia/Bangkok

# Verify
date
Tip: Production servers often run on UTC to keep log timestamps consistent across regions. For personal VPS in Thailand, Asia/Bangkok is more convenient for reading logs directly.

Use Chrony as an NTP Server for Your LAN

If you have multiple VPS instances on the same private network, you can designate one as a local NTP server to reduce external NTP queries:

# In /etc/chrony/chrony.conf, add the network to allow:
allow 10.0.0.0/8

# Restart Chrony
sudo systemctl restart chrony

# On other VPS instances, point to this server's IP:
# pool 10.0.0.1 iburst

Verify Chrony Is Working Correctly

# Check Chrony service status
systemctl status chrony

# Show NTP sources with details
chronyc sources -v

# Show tracking statistics (offset, frequency, etc.)
chronyc tracking

# Show source activity counts
chronyc activity

# Show per-source statistics
chronyc sourcestats -v
Tip: In chronyc sources output, a * prefix means Chrony selected this source as the current sync reference. ^* means it's synchronized and actively using that source. If you see only ? or - prefixes, Chrony hasn't locked onto any source yet — wait a few minutes and check again.

Common Issues and Fixes

Error: "No sources online"

Chrony cannot reach any NTP servers. Check your firewall rules and DNS resolution:

# Test UDP connectivity to NTP server
nc -uzv pool.ntp.org 123

# Check firewall — UDP port 123 outbound must be allowed
sudo ufw status
sudo iptables -L OUTPUT -n | grep 123

# Test DNS resolution
dig pool.ntp.org

# Check Chrony logs for more details
sudo journalctl -u chrony -n 50

Error: "System clock wrong by more than 1000 seconds"

The server clock is too far off for Chrony's normal slew mechanism. Force an immediate step correction:

# Force an immediate time step
sudo chronyc makestep

# Alternative: stop Chrony, sync manually, then restart
sudo systemctl stop chrony
sudo ntpdate -s pool.ntp.org
sudo systemctl start chrony

Error: "chronyd: Could not open /var/run/chrony/chronyd.pid"

The runtime directory is missing or has incorrect permissions:

# Create the directory and fix ownership
sudo mkdir -p /var/run/chrony
sudo chown _chrony:_chrony /var/run/chrony

# Restart the service
sudo systemctl restart chrony

systemd-timesyncd Conflict — Clock Control Conflict

Another service is still managing the system clock alongside Chrony:

# Check which services are active
systemctl is-active systemd-timesyncd
systemctl is-active ntp

# Disable conflicting services
sudo systemctl disable --now systemd-timesyncd
sudo systemctl disable --now ntp   # if ntpd is also installed

sudo systemctl restart chrony
chronyc tracking

Clock Drifts Back After Reboot

Verify the drift file is writable and RTC sync is enabled in the config:

# Check drift file exists and has content
ls -la /var/lib/chrony/
cat /var/lib/chrony/chrony.drift

# Verify rtcsync is in config
grep rtcsync /etc/chrony/chrony.conf

# Manually sync hardware clock to system time
sudo hwclock --systohc

Frequently Asked Questions

What is the difference between Chrony and ntpd?

Chrony was designed specifically for systems that aren't always online and for virtualized environments like VPS. It converges to accurate time faster than ntpd and handles large initial offsets more gracefully. Modern Linux distributions — Fedora, RHEL 8+, Ubuntu 20.04+, and Debian 11+ — have all switched to Chrony as their default NTP daemon. Unless you have a specific reason to use ntpd (such as compatibility with very old clients), Chrony is the better choice.

Which firewall ports does Chrony need?

For NTP client mode (syncing time from the internet): you only need UDP port 123 outbound to be allowed. Most firewalls don't block outgoing UDP by default. If you're also running Chrony as an NTP server for other hosts, additionally open UDP port 123 inbound: sudo ufw allow 123/udp.

How do I enable NTS (encrypted NTP) with Chrony?

NTS requires Chrony 4.0 or later. Add NTS-capable servers to your config:

# In /etc/chrony/chrony.conf
server time.cloudflare.com iburst nts
server nts.ntp.se iburst nts

# Restart and verify NTS authentication
sudo systemctl restart chrony
chronyc -n authdata