Last updated: 2026-02-11
NTPsec NTS Configuration Guide
This guide provides recommended Network Time Security (NTS) settings for NTPsec. NTPsec is a security-focused fork of the reference NTP implementation with hardened code, reduced attack surface, and NTS support since version 1.2.0. NTS authenticates time synchronization using TLS, preventing man-in-the-middle attacks on time data.
Prerequisites
- NTPsec 1.2.0 or later
- OpenSSL 1.1.1 or later (for TLS 1.3 support)
- A valid TLS certificate and private key (for server mode)
- Network access to port 4460 (NTS-KE) and port 123 (NTP)
Availability: NTPsec is available in Debian 11+ and Ubuntu 22.04+ repositories. It is not in the base RHEL/CentOS or SLES repositories — on those systems, install from EPEL or build from source. Note that RHEL uses chrony as its default NTP implementation.
Path note: This guide uses Debian/Ubuntu package paths. On source builds (common on RHEL/SLES), paths differ: config is typically
/etc/ntp.conf(not/etc/ntpsec/ntp.conf), state files are under/var/lib/ntp/(not/var/lib/ntpsec/), logs are under/var/log/ntp/(not/var/log/ntpsec/), and the service isntpd(notntpsec). The user/group isntpon source builds vsntpsecon Debian/Ubuntu packages.
NTS Overview
NTS works in two phases:
- NTS-KE (Key Establishment) -- A TLS 1.3 handshake on port 4460 authenticates the server and establishes shared keys
- NTP with cookies -- Subsequent NTP packets on port 123 carry encrypted cookies and authentication extensions derived from the NTS-KE session
Client Configuration
Basic NTS Client
Enable NTS for upstream time servers by adding the nts keyword:
# /etc/ntpsec/ntp.conf
server time.cloudflare.com nts
server nts.netnod.se nts
server ptbtime1.ptb.de nts
server ntppool1.time.nl nts
Certificate Trust Store
NTPsec uses the system trust store by default. To specify a custom CA bundle:
# Debian/Ubuntu:
nts ca /etc/ssl/certs/ca-certificates.crt
# RHEL/CentOS (source builds): /etc/pki/tls/certs/ca-bundle.crt
# SLES: /etc/ssl/ca-bundle.pem
NTS Cookie Storage
Persist NTS cookies across restarts to avoid repeated NTS-KE handshakes:
nts cookie /var/lib/ntpsec/nts-cookies # source builds: /var/lib/ntp/nts-cookies
AEAD Algorithm
NTPsec supports AEAD algorithm selection for NTS cookie encryption. The default (AES-SIV-CMAC-256) is recommended:
nts aead AES_SIV_CMAC_256
Server Configuration
NTS-KE Server
Configure NTPsec as an NTS-capable NTP server:
# /etc/ntpsec/ntp.conf
nts cert /etc/ntpsec/ssl/fullchain.pem
nts key /etc/ntpsec/ssl/privkey.pem
The certificate must be valid for the server's hostname.
TLS Protocol Versions
Restrict TLS versions for the NTS-KE handshake:
nts mintls TLS1.3
nts maxtls TLS1.3
To allow TLS 1.2 as well:
nts mintls TLS1.2
NTS-KE Port
By default, NTPsec listens on port 4460 for NTS-KE. To change it:
nts port 4461
Complete Client Configuration
# /etc/ntpsec/ntp.conf
# NTS-authenticated time sources
server time.cloudflare.com nts
server nts.netnod.se nts
server ptbtime1.ptb.de nts
server ntppool1.time.nl nts
# Fallback (unauthenticated) sources
pool pool.ntp.org iburst
# NTS cookie persistence
nts cookie /var/lib/ntpsec/nts-cookies # source builds: /var/lib/ntp/nts-cookies
# Drift file
driftfile /var/lib/ntpsec/ntp.drift # source builds: /var/lib/ntp/ntp.drift
# Logging
logfile /var/log/ntpsec/ntpd.log # source builds: /var/log/ntp/ntpd.log
statsdir /var/log/ntpsec/ # source builds: /var/log/ntp/
statistics loopstats peerstats
Complete Server Configuration
# /etc/ntpsec/ntp.conf
# Upstream NTS sources
server time.cloudflare.com nts
server nts.netnod.se nts
# NTS server settings
nts cert /etc/ntpsec/ssl/fullchain.pem
nts key /etc/ntpsec/ssl/privkey.pem
nts mintls TLS1.2
nts cookie /var/lib/ntpsec/nts-cookies # source builds: /var/lib/ntp/nts-cookies
# Serve time to clients
restrict default kod nomodify nopeer noquery limited
restrict 127.0.0.0 mask 255.0.0.0
restrict ::1
restrict 10.0.0.0 mask 255.0.0.0 nomodify notrap
restrict 172.16.0.0 mask 255.240.0.0 nomodify notrap
restrict 192.168.0.0 mask 255.255.0.0 nomodify notrap
# Drift file
driftfile /var/lib/ntpsec/ntp.drift # source builds: /var/lib/ntp/ntp.drift
# Logging
logfile /var/log/ntpsec/ntpd.log # source builds: /var/log/ntp/ntpd.log
statsdir /var/log/ntpsec/ # source builds: /var/log/ntp/
statistics loopstats peerstats
Certificate Management
Using Let's Encrypt with Certbot
certbot certonly --standalone -d ntp.example.com
Configure NTPsec to use the certificates:
nts cert /etc/letsencrypt/live/ntp.example.com/fullchain.pem
nts key /etc/letsencrypt/live/ntp.example.com/privkey.pem
Restart NTPsec after certificate renewal since it does not automatically reload certificates:
certbot renew --deploy-hook "systemctl restart ntpsec" # source builds: systemctl restart ntpd
File Permissions
Ensure NTPsec can read the private key:
chown root:ntpsec /etc/ntpsec/ssl/privkey.pem # source builds: chown root:ntp
chmod 640 /etc/ntpsec/ssl/privkey.pem
Firewall
Open the required ports.
RHEL/CentOS (firewalld):
firewall-cmd --permanent --add-port=4460/tcp
firewall-cmd --permanent --add-service=ntp
firewall-cmd --reload
Debian/Ubuntu (ufw):
ufw allow 4460/tcp
ufw allow 123/udp
Verification
Check NTS status for all peers:
ntpq -c nts
Check peer status and authentication:
ntpq -p
Verify the NTS-KE handshake:
gnutls-cli --port 4460 time.cloudflare.com < /dev/null
Check overall time synchronization:
ntpq -c sysinfo
ntpq -c iostats
Check NTPsec version and build options:
ntpd --version