← Back to list

NTP Setup Between Two Linux Servers Using Chrony — Production-Ready Guide

In any system, time is not just a background detail — it’s a core dependency. Every log entry, authentication request, scheduled job, and…

Manohar Shetty · 2026-04-16 16:40 · 0 claps · 3.3 min read paywalled
#ntp-server #ntp #linux #redhat-linux #linux-tutorial
Open on Medium ↗
Wiki topics: 🔓 · Open Source

NTP Setup Between Two Linux Servers Using Chrony — Production-Ready Guide

In any system, time is not just a background detail — it’s a core dependency. Every log entry, authentication request, scheduled job, and distributed operation relies on the assumption that all machines share a consistent clock. The moment that assumption breaks, systems don’t fail loudly — they fail silently and unpredictably.

Imagine debugging an issue where events appear out of order, authentication tokens randomly fail, or scheduled tasks behave inconsistently. In many cases, the root cause isn’t complex architecture or bad code — it’s simply that the servers involved don’t agree on what time it is.

This is where Network Time Protocol (NTP) becomes essential. NTP ensures that all systems in a network stay synchronized to a common time source, maintaining consistency across infrastructure. Instead of each server drifting independently, they operate on a unified timeline, making systems reliable, traceable, and predictable.

In this guide, we’ll set up a simple and effective NTP architecture using Rocky Linux, where one server acts as the time source and another synchronizes against it.

Architecture

  • NTP Master (Server): 192.168.0.110ntp-master
  • NTP Client: 192.168.0.111ntp-client

One machine serves time. The other consumes it. No ambiguity.

Why Chrony (Not ntpd)

Rocky Linux uses chrony by default for a reason:

  • Faster sync on boot
  • Better handling of unstable networks
  • Lower drift over time
  • Works cleanly in VMs and cloud

If you’re still thinking about ntpd, you’re behind.

Step 1 — Configure NTP Master (192.168.0.110)

Set hostname

hostnamectl set-hostname ntp-master

Install chrony

dnf install -y chrony

Edit config

vi /etc/chrony.conf

Minimal, Correct Config

# Upstream time sources (optional but recommended)
pool 2.rocky.pool.ntp.org iburst

# Allow clients from your subnet
allow 192.168.0.0/24
# Act as time source even if upstream is unavailable
local stratum 10
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony

Start service

systemctl enable chronyd
systemctl restart chronyd

Open firewall (if enabled)

firewall-cmd --add-service=ntp --permanent
firewall-cmd --reload

Verify

chronyc sources -v
chronyc tracking

If this server isn’t synced, your entire setup is garbage. Fix this first.

Step 2 — Configure NTP Client (192.168.0.111)

Set hostname

hostnamectl set-hostname ntp-client

Install chrony

dnf install -y chrony

Edit config

vi /etc/chrony.conf

Critical Fix (Most People Fail Here)

REMOVE:

pool 2.rocky.pool.ntp.org iburst

ADD:

server 192.168.0.110 iburst

Final Clean Config

server 192.168.0.110 iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony

Start service

systemctl enable chronyd
systemctl restart chronyd

Step 3 — Verification (Don’t Skip This)

On Client

[root@ntp-client ~]# chronyc sources -v

  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current best, '+' = combined, '-' = not combined,
| /             'x' = may be in error, '~' = too variable, '?' = unusable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability register (octal) -.           |  xxxx = adjusted offset,
||      Log2(Polling interval) --.      |          |  yyyy = measured offset,
||                                \     |          |  zzzz = estimated error.
||                                 |    |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* ntp-master                   10   6   377    12  +8419ns[  +12us] +/-  269us

Expected:

  • You should see 192.168.0.110
  • Marked with ^* (selected source)
[root@ntp-client ~]# chronyc tracking
Reference ID    : C0A8006E (ntp-master)
Stratum         : 11
Ref time (UTC)  : Thu Apr 16 16:35:30 2026
System time     : 0.000002946 seconds fast of NTP time
Last offset     : +0.000003721 seconds
RMS offset      : 0.000014631 seconds
Frequency       : 4.336 ppm slow
Residual freq   : +0.001 ppm
Skew            : 0.238 ppm
Root delay      : 0.000537779 seconds
Root dispersion : 0.000058532 seconds
Update interval : 64.0 seconds
Leap status     : Normal

Check:

  • Reference ID → should point to master
  • Stratum → higher than master (e.g., 11 if master is 10)

Common Failures (You Will Hit These If You’re Careless)

1. Still using public NTP on client

If you see external servers → you didn’t remove the pool line. Fix it. No excuses.

2. ^? or unreachable source

Means:

  • Firewall blocking UDP 123
  • Master not running
  • Network issue

Check:

ping 192.168.0.110
ss -ulpn | grep 123

3. Master not allowing clients

If you skipped:

allow 192.168.0.0/24

Client will never sync. Period.

4. Time not syncing immediately

Chrony doesn’t blindly jump time unless needed.

Force sync:

chronyc makestep

What “Good” Looks Like

On client:

^* 192.168.0.110

On master:

  • Synced to upstream OR acting as local stratum

Hard Truth

If you don’t verify:

  • source selection (^*)
  • stratum consistency
  • tracking output

Then you didn’t configure NTP — you guessed and hoped.

This setup is simple. If it’s not working, you missed something basic. Go back and check instead of layering more confusion on top.

Conclusion

You now have:

  • A controlled internal time source
  • No dependency on external NTP for clients
  • Predictable, stable synchronization

That’s how you run this in real environments — clean, minimal, and verified.


메타데이터
post_id
d6ee758d6d33
slug
ntp-setup-between-two-rocky-linux-servers-chrony-production-ready-guide-d6ee758d6d33
url
https://medium.com/@tradingcontentdrive/ntp-setup-between-two-rocky-linux-servers-chrony-production-ready-guide-d6ee758d6d33
canonical_url
https://medium.com/@tradingcontentdrive/ntp-setup-between-two-rocky-linux-servers-chrony-production-ready-guide-d6ee758d6d33
author_url
https://medium.com/@tradingcontentdrive
status
ok
fetched_at
2026-06-12 22:02:08