Can You Mix NTS and Non-NTS Servers in Your Time Synchronization Setup?

No, you cannot mix NTS and non-NTS servers in the same configuration when using the nts-servers repository, as the NTS protocol's TLS authentication layer causes clients to ignore or reject plain NTP responses.

The jauderho/nts-servers repository provides a curated list of NTS-enabled NTP servers designed for secure time synchronization. When configuring time sync clients using the generated files from this repository, you must include only NTS servers to ensure proper authentication and avoid synchronization failures.

Why Mixing NTS and Non-NTS Servers Fails

The Network Time Security (NTS) protocol adds a TLS-based authentication layer on top of standard NTP. When you configure a client to use NTS, it expects encrypted, authenticated time responses. If you attempt to mix NTS and non-NTS servers in the same configuration, one of two outcomes occurs:

  • The client ignores or rejects plain NTP responses from non-NTS servers, treating them as untrusted
  • The client falls back to insecure NTP, defeating the security purpose of deploying NTS

According to the jauderho/nts-servers source code, the repository enforces an NTS-only policy to prevent these security gaps. The README explicitly states: "It is not possible to mix and match NTP and NTS at this time. Only NTS servers should be specified as the NTP entries will not be used" [README.md L25].

Source Code Evidence

The generated configuration files demonstrate this restriction clearly. In chrony.conf, every server entry includes the nts keyword, which instructs chronyd to require NTS authentication for that peer:

server time.cloudflare.com nts iburst
server 1.ntp.ubuntu.com nts iburst

[chrony.conf L5-L7]

Similarly, the ntp.toml file for ntpd-rs uses NTS-specific configuration parameters, ensuring the client refuses unauthenticated time data. These files are generated from the canonical nts-sources.yml by scripts/ntpServerConverter.py, which applies the NTS flag uniformly to all entries.

Configuration Examples

Correct NTS-Only Configuration

When using the nts-servers repository, your chrony.conf should contain only servers with the nts flag:


# /etc/chrony.conf (generated by scripts/ntpServerConverter.py)

server time.cloudflare.com nts iburst
server 1.ntp.ubuntu.com nts iburst
server time.example.com nts iburst

This configuration ensures all time sources use encrypted NTS handshakes before transmitting time data.

Incorrect Mixed Configuration

The following configuration will not work as intended because the plain NTP server will be ignored or rejected:


# This configuration is unsupported

server time.cloudflare.com nts iburst    # NTS server (OK)

server pool.ntp.org iburst               # Plain NTP (will be ignored)

The chronyd daemon will discard responses from pool.ntp.org because they lack the required NTS authentication cookies.

Verifying NTS Server Connectivity

Before deploying, verify individual servers support NTS using the provided validation script:

./scripts/ntsCheck.sh time.cloudflare.com

This script executes a one-shot NTS query via chronyd to confirm the server responds with proper TLS authentication [ntsCheck.sh]. If a server fails this check, it should not be included in your nts-sources.yml or final configuration.

Managing Separate Time Sync Configurations

If your infrastructure requires both NTS-secured time and legacy NTP sources, maintain separate configuration files:

  1. Use chrony.conf from the nts-servers repository for NTS-only clients
  2. Create a distinct chrony-legacy.conf for systems requiring plain NTP
  3. Run separate chronyd instances or use different client machines

Never combine both server types in the same configuration file when using the nts keyword, as the authentication requirements are mutually exclusive.

Summary

  • Mixing is unsupported: The jauderho/nts-servers repository explicitly forbids combining NTS and plain NTP servers in the same configuration
  • Protocol incompatibility: NTS clients reject unauthenticated NTP responses, making mixed configurations ineffective
  • Uniform NTS flag: Generated files like chrony.conf and ntp.toml apply the nts keyword to every server entry via scripts/ntpServerConverter.py
  • Validation required: Use scripts/ntsCheck.sh to verify NTS capability before adding servers to nts-sources.yml
  • Separate deployments: Maintain distinct configurations if you must support both protocols in your infrastructure

Frequently Asked Questions

What happens if I accidentally mix NTS and non-NTS servers in chrony.conf?

The chronyd daemon will ignore or reject responses from plain NTP servers because they cannot provide the TLS-authenticated NTS handshake required by the nts flag. Your client will synchronize only with the NTS-enabled servers, or potentially fail to sync entirely if no valid NTS servers are reachable.

How do I convert the nts-servers list into a working chrony configuration?

Run the scripts/ntpServerConverter.py script against the nts-sources.yml file. This Python script generates both chrony.conf and ntp.toml with the correct nts keyword applied to every server entry, ensuring compliance with the repository's NTS-only policy.

Can I run both NTS and plain NTP on the same machine?

Yes, but you must use separate configuration files and potentially separate client instances. Do not combine both server types in a single chrony.conf file that uses the nts keyword, as this creates conflicting authentication requirements.

How do I verify that a server truly supports NTS before adding it?

Execute ./scripts/ntsCheck.sh <hostname> to perform a real-time NTS handshake test. The script uses chronyd to attempt authentication and will confirm whether the server provides valid NTS cookies and TLS encryption.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →