The NTP Pool (pool.ntp.org) is the time-synchronisation infrastructure that, without them knowing it, underpins most of the consumer Internet: home routers, smartphones, IoT devices, and a large portion of Linux distributions by default. This network of over 4,000 servers is 100% volunteer-based, coordinated since 2003 by Ask Bjørn Hansen and a handful of contributors.
Our Why Contribute to the NTP Pool page covers the reasons to join the project. This one is the practical follow-up: how to run a pool server in 2026, pitfalls encountered, and what to size for load. RDEM Systems has operated pool-registered servers for several years — a significant share under its own AS206014, others on third-party transits.
Before any registration, the server must tick four boxes:
2.pool.ntp.org and 3.pool.ntp.org zones are statistically AAAA-richer:
contributing over IPv6 there has disproportionate impact. See also our
NTP IPv6 test guide.Registration is free and takes five minutes:
europe and global.Several geographically distributed monitors (Europe, Americas, Asia, Oceania) query each registered server every 10–20 minutes. Each query produces a score increment based on the response:
| Result | Score impact | Typical cause |
|---|---|---|
| OK, offset < 75 ms | +1 (progressive toward +20) | Normal operation |
| OK, offset 75–400 ms | Slight penalty | Server under load or degraded WAN |
| Offset > 400 ms | −4 | Broken local sync, mishandled leap second |
| Timeout / no response | −5 | Firewall, server down, net speed exceeded |
| Stratum 16 announced | −5 | Unsynchronised daemon at the operator |
Global score ranges from −100 (banned) to +20 (excellent).
A server with score above +10 is included in pool DNS responses proportionally
to its net speed. Score is public at ntppool.org/scores/<IP> and helpful for
diagnosing regressions.
The pool tolerates temporary dips (maintenance, reboot) without immediate exclusion. But a score drop below +10 removes the server from DNS responses until recovery.
The declared net speed drives the volume of requests the pool directs to the server proportionally. Five levels:
| Net speed | Typical req/s | Average outbound bandwidth | Operator profile |
|---|---|---|---|
| 1 Mbit/s | < 50 | < 4 kbit/s | Individual, residential connection |
| 10 Mbit/s | 50–200 | 4–16 kbit/s | Small hosted VPS |
| 100 Mbit/s | 500–2,000 | 40–160 kbit/s | Pro infrastructure, comfortable VPS |
| 500 Mbit/s | 2,500–10,000 | 200 kbit/s–1 Mbit/s | Datacentre, dedicated bandwidth |
| 1,000 Mbit/s | 5,000–20,000 | 500 kbit/s–2 Mbit/s | Operator with dedicated link + serious CPU |
An NTP packet is 90 bytes at UDP level (48-byte payload + 8 UDP + 20 IPv4 + optional headers). In practice, CPU load remains negligible even at 20,000 req/s on one modern core. The real sizing is bandwidth and link quality: a network with stable latency helps the pool more than a beefy server behind a jittery connection.
The choice between chrony and ntpd for a public server is structural — see which daemon to pick for a public server on check-ntp.net for the detailed decision. Minimum recommended configuration on chrony 4.x:
# /etc/chrony/chrony.conf — public NTP pool server
# === Upstream sources (at least 4, diversified) ===
server time.cloudflare.com iburst nts
server nts.netnod.se iburst nts
server ntp1.ptb.de iburst
pool 2.pool.ntp.org iburst maxsources 4
# === Accept public traffic ===
# Accept NTP requests from the whole Internet
allow 0.0.0.0/0
allow ::/0
# === Rate limiting to protect the service ===
# KoD (Kiss-o'-Death) above ~4 req/s from one IP
ratelimit interval 1 burst 16 leak 2
# === Security ===
# Never serve our internal variables
noclientlog
# Disable control commands externally (chronyc stays local)
bindcmdaddress 127.0.0.1
bindcmdaddress ::1
# === Stability ===
makestep 1.0 3
rtcsync
leapsecmode system
# === NTS server-side (optional but recommended) ===
ntsserverkey /etc/chrony/nts.key
ntsservercert /etc/chrony/nts.crt
The ratelimit directive is critical: a client looping on one request per second
(symptom of a broken IoT device) can represent kbit/s by itself and hurt the score for everyone
else. KoD signals it to slow down; compliant implementations obey, bad ones keep going but on
a pace chrony ignores.
# /etc/ntp.conf — ntpd/ntpsec public server
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server time.cloudflare.com iburst nts
server ntp1.ptb.de iburst
# Restrict world actions
restrict default kod limited nomodify notrap nopeer noquery
restrict -6 default kod limited nomodify notrap nopeer noquery
# Localhost has all rights
restrict 127.0.0.1
restrict ::1
# Leap second history
leapfile /usr/share/zoneinfo/leap-seconds.list
# NO monlist (DDoS amplification vector)
# ntpsec disables mode 6/7 by default; on classic ntpd:
# disable monitor
The limited flag enables native rate-limiting; kod sends Kiss-o'-Death
to abusers; nomodify notrap nopeer noquery blocks any remote reconfiguration attempt.
Do not disable any of these defaults.
Joining the pool, the server becomes a target for three parasite behaviours:
Consumer device manufacturers (routers, IP cameras, smart TVs) have historically hardcoded a specific NTP server IP in their firmware — sometimes theirs, sometimes a third-party operator picked at random. Millions of devices then query that IP forever. Documented cases: Netgear WNDR router to University of Wisconsin (2003), D-Link NAS to poul-henning.kamp.dk (2005). There is no clean solution: filter source IP in iptables, or accept the load and send KoD.
In 2014, ntpd < 4.2.7 exposed a monlist command (mode 7) returning the list of the
last 600 clients. Used in reflected attack, a 234-byte request could produce a ~49 KB response
— a 200× amplification factor. The February 2014 attacks (CloudFlare, Hearthstone) consumed
hundreds of Gbit/s. Mitigations: disable mode 6 and 7 server-side (default on chrony 4.x and
ntpsec), or migrate to these modern implementations.
Kiss-o'-Death is an NTP packet with stratum 0 and a refid code (RATE, DENY…)
that tells the client to slow down or change source. RFC-compliant clients obey. Bad ones ignore
and keep going. For those:
# Temporarily ban an abusive IP (iptables)
iptables -I INPUT -s 203.0.113.42 -p udp --dport 123 -j DROP
# Or dynamically via ipset + fail2ban
# jail chrony_kod in /etc/fail2ban/jail.d/chrony.conf
Three axes to watch continuously on a pool server:
https://www.ntppool.org/scores/<IP>/log?monitor=*. Alert on score < +10.chronyc tracking to Prometheus
with the chrony_exporter or equivalent.
Alert on offset > 50 ms or stratum > 3.nftables or
conntrack. A curve that suddenly spikes signals a vendor lock or active attack.Abrupt removal produces monitor timeouts, which impact the score of other servers listed alongside. Clean procedure: