Accurate time synchronization is the foundation of distributed systems, certificate validation, log correlation, and financial transactions. Running your own NTP (Network Time Protocol) server reduces dependency on external services, improves accuracy within your network, and eliminates a potential attack vector. This guide compares three self-hosted NTP server implementations: Chrony, NTPsec, and OpenNTPD.

Why Run Your Own NTP Server?

Self-hosted NTP provides:

  • Reduced latency — local server responds faster than public pools
  • Offline timekeeping — maintains accuracy during internet outages
  • Security — no exposure to NTP amplification attacks from external servers
  • Compliance — meet regulatory requirements for accurate timestamps
  • Internal stratum — serve as a stratum 2 or 3 server for your network

Chrony

Chrony is the default NTP implementation on most modern Linux distributions (RHEL, Fedora, Ubuntu, Debian). It was designed to perform well under a wide variety of conditions including intermittent network connections, heavily loaded networks, and temperature fluctuations.

Key Features

  • Faster synchronization than traditional NTP — typically within milliseconds on first sync
  • Better response to frequency changes — ideal for virtual machines
  • Works without polling the NTP server continuously — reduces network load
  • Supports NTP server, client, peer, and reference clock modes
  • Hardware timestamping support for sub-microsecond accuracy
  • PTP (Precision Time Protocol) support

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
version: "3.8"
services:
  chrony:
    image: networkstatic/chrony:latest
    container_name: chrony
    ports:
      - "123:123/udp"
    volumes:
      - ./chrony.conf:/etc/chrony/chrony.conf:ro
    cap_add:
      - SYS_TIME
    restart: unless-stopped

Configuration (chrony.conf):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Upstream NTP servers
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst

# Allow clients on local network
allow 192.168.0.0/16
allow 10.0.0.0/8

# Serve time even when not synchronized
local stratum 10

# Record the rate at which the system clock gains/loses time
driftfile /var/lib/chrony/drift

# Log directory
logdir /var/log/chrony
log measurements statistics tracking

# Key file for NTP authentication
keyfile /etc/chrony/chrony.keys

Monitoring Chrony

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Check synchronization status
chronyc tracking

# View time sources
chronyc sources -v

# View source statistics
chronyc sourcestats -v

# Real-time monitoring
chronyc activity

NTPsec

NTPsec is a hardened fork of the traditional NTP reference implementation, focused on security, correctness, and maintainability. It removes legacy code and adds modern security features.

Key Features

  • Security-hardened codebase — audited and simplified
  • Python-based monitoring tools (ntpmon, ntpviz)
  • Built-in statistics visualization
  • Drop-in replacement for classic NTP
  • Reduced attack surface compared to ntpd
  • NTS (Network Time Security) client support

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
version: "3.8"
services:
  ntpsec:
    image: ntpsec/ntpsec:latest
    container_name: ntpsec
    ports:
      - "123:123/udp"
    volumes:
      - ./ntp.conf:/etc/ntpsec/ntp.conf:ro
      - ./ntpsec-keys:/etc/ntpsec/ntp.keys:ro
    cap_add:
      - SYS_TIME
    restart: unless-stopped

Configuration (ntp.conf):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# Upstream servers with NTS
pool 0.pool.ntp.org iburst maxpoll 10
pool 1.pool.ntp.org iburst maxpoll 10
pool 2.pool.ntp.org iburst maxpoll 10

# Restrict access
restrict default nomodify nopeer noquery
restrict 127.0.0.1
restrict ::1
restrict 192.168.0.0 mask 255.255.0.0 nomodify noquery

# Drift file
driftfile /var/lib/ntpsec/ntp.drift

# Statistics
statsdir /var/log/ntpsec/
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable

Monitoring NTPsec

1
2
3
4
5
6
7
8
# Visual monitoring (ncurses interface)
ntpmon

# Generate statistics graphs
ntpviz -d /var/log/ntpsec/ -g local-offset

# Check peer status
ntpq -p

OpenNTPD

OpenNTPD is part of the OpenBSD project, designed for simplicity and security. The portable version runs on Linux and other Unix-like systems. It prioritizes correct behavior over configurability.

Key Features

  • Minimal configuration — works out of the box
  • Privilege separation — runs as non-root after startup
  • Automatic server selection — picks the best time source
  • Small codebase — easier to audit
  • DNS-based server discovery — resolves pool names periodically
  • No complex ACL system — simple allow/deny rules

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
version: "3.8"
services:
  openntpd:
    image: openntpd/openntpd:latest
    container_name: openntpd
    ports:
      - "123:123/udp"
    volumes:
      - ./ntpd.conf:/etc/openntpd/ntpd.conf:ro
    cap_add:
      - SYS_TIME
    restart: unless-stopped

Configuration (ntpd.conf):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Listen on all interfaces
listen on *

# Upstream servers
servers pool.ntp.org

# Allow all clients (restrict with firewall instead)
# sensor *

# Correction threshold
# Constraint from a reliable HTTPS server
constraint from "https://time.cloudflare.com"

Monitoring OpenNTPD

1
2
3
4
5
6
7
8
# Check synchronization status
ntpd -s

# View daemon status (OpenBSD)
rcctl check ntpd

# Check if the daemon is running
pgrep -a ntpd

Comparison Table

FeatureChronyNTPsecOpenNTPD
Default onRHEL, Fedora, UbuntuAlpine, some BSDsOpenBSD
Sync speed⚡ Fastest (ms on first sync)ModerateModerate
VM optimization✅ Excellent⚠️ Basic❌ None
Hardware timestamping✅ Yes⚠️ Limited❌ No
PTP support✅ Yes❌ No❌ No
NTS support⚠️ Server only✅ Client + Server❌ No
Monitoring toolschronyc (CLI)ntpmon, ntpvizMinimal
Configuration complexityModerateModerateMinimal
Privilege separation✅ Yes✅ Yes✅ Yes
Codebase size~50K lines~100K lines~10K lines
NTPv4✅ Full✅ Full✅ Basic
SNTP✅ Yes✅ Yes✅ Yes

Which NTP Server Should You Choose?

Choose Chrony if you run Linux servers, especially in virtualized environments. It is the modern standard for NTP on Linux, with superior synchronization speed and VM-aware clock discipline.

Choose NTPsec if security is your primary concern and you need comprehensive monitoring tools. The hardened codebase and built-in visualization make it ideal for security-sensitive deployments.

Choose OpenNTPD if you value simplicity and minimalism. It works out of the box with almost no configuration, making it perfect for small deployments where “just works” is the top priority.

Why Self-Host Your NTP Infrastructure?

Running your own NTP server eliminates external dependencies for time synchronization. During internet outages, your internal server continues serving cached time. For organizations with strict compliance requirements (PCI-DSS, SOC 2, HIPAA), a self-hosted NTP server provides an auditable time source. For related infrastructure hardening, see our TLS termination proxy guide and certificate monitoring guide.

FAQ

What stratum level should my self-hosted NTP server use?

If you sync from public NTP pools, your server should be stratum 2 or 3. The local stratum directive in Chrony sets the stratum level when no upstream servers are available — typically 10 or higher to indicate “fallback” mode.

How accurate is a self-hosted NTP server?

With public pool servers, you can typically achieve 1-10ms accuracy on a well-connected server. Using hardware timestamping and GPS clocks, sub-microsecond accuracy is possible. Chrony generally achieves the best accuracy among the three implementations.

Can I run an NTP server in a Docker container?

Yes. All three servers can run in Docker containers. You need to map UDP port 123 and add the SYS_TIME capability so the daemon can adjust the system clock. Note that container clocks may drift more than bare-metal servers.

How do I prevent NTP amplification attacks on my server?

All three servers have built-in rate limiting. Chrony uses ratelimit directives, NTPsec uses restrict rules, and OpenNTPD has minimal exposure by default. Additionally, configure your firewall to only allow NTP from trusted networks.

What is NTS (Network Time Security)?

NTS is a protocol (RFC 8915) that provides cryptographic security for NTP, protecting against packet injection and replay attacks. NTPsec supports both NTS client and server modes. Chrony supports NTS server mode. OpenNTPD does not support NTS.

How often should NTP clients poll the server?

The default poll interval is 64 seconds (2^6), ranging from 64 to 1024 seconds. Chrony adapts dynamically based on network conditions. For most use cases, the default polling is sufficient. Increase minpoll/maxpoll values only if you need faster synchronization.