nts-sources.yml: Format, Schema, and Purpose Explained

The nts-sources.yml file is a YAML database that serves as the single source of truth for all Network Time Security (NTS) servers tracked by the repository, defining server metadata and enabling automated configuration generation for NTP daemons.

The jauderho/nts-servers repository maintains a curated list of public NTS servers for secure time synchronization. At the heart of this project lies nts-sources.yml, a structured YAML file that catalogs every server with essential metadata including hostname, stratum, and geographical location. This central file drives the entire automated pipeline that generates configuration files for Chrony and ntpd-rs while keeping documentation synchronized.

Understanding the nts-sources.yml Format

The nts-sources.yml file uses a straightforward schema designed for both human readability and machine parsing. According to the source code in jauderho/nts-servers, the file organizes data under a top-level servers key containing an ordered list of server descriptors.

YAML Schema and Required Fields

Each server entry in nts-sources.yml is a mapping with the following fields (as defined in lines 1-14 of the file):

  • hostname: String representing the DNS name. Supports plain text or Markdown link syntax (e.g., "[time.cloudflare.com](https://time.cloudflare.com)").
  • stratum: Integer indicating the NTP stratum level (lower values indicate higher accuracy).
  • location: String describing the geographical location (country or city).
  • owner: String identifying the organization or individual responsible for the server.
  • notes: Optional string for additional remarks such as "Anycast" or "IPv4 and IPv6".
  • vm: Boolean flag set to true if the server runs in a virtualized environment.

A minimal valid entry appears as:

- hostname: time.cloudflare.com
  stratum: 3
  location: All
  owner: Cloudflare
  notes: Anycast
  vm: false

File Organization Requirements

The file enforces alphabetical grouping by country to ensure predictable editing and automated processing. As specified in AGENTS.md (lines 3-6), new entries must be inserted into the appropriate alphabetical section, making the raw YAML structure scannable and version-control friendly.

Core Purpose and Automation Pipeline

The nts-sources.yml file functions as the canonical definition for trusted NTS servers. Rather than maintaining separate lists for documentation and configuration, all downstream artifacts derive from this single source.

Configuration File Generation

The scripts/ntpServerConverter.py script consumes nts-sources.yml to produce three critical outputs:

  • chrony.conf: Chrony NTP daemon configuration generated by generate_chrony_conf (lines 59-77).
  • ntp.toml: ntpd-rs configuration generated by generate_ntp_toml (lines 86-106).
  • README tables: Markdown documentation generated by generate_markdown (lines 21-44).

Stratum Verification and Updates

To maintain accuracy, scripts/ntsUpdateServers.py reads the YAML file and queries each server using ntpdate or ntpq. The update_stratum_values function (lines 40-87) compares reported stratum values against the stored data and rewrites the file when discrepancies are detected.

Agent-Driven Automation

The repository's automated agent workflow (defined in AGENTS.md) inserts new servers directly into nts-sources.yml after validating NTS/NTP reachability. This ensures the central database remains current without requiring manual YAML editing for every new server.

Practical Usage Examples

Working with nts-sources.yml involves parsing Markdown-formatted hostnames, generating configurations, and updating metadata programmatically.

When processing the hostname field, scripts must handle both plain text and Markdown link formats. The scripts/ntsUpdateServers.py implementation (lines 28-44) uses regex extraction:

import re

def extract_hostname(hostname_field):
    """
    Accepts plain text or Markdown links like 
    '[time.cloudflare.com](https://time.cloudflare.com)'
    Returns the raw hostname.
    """
    markdown_match = re.match(r'\[([^\]]+)\]', hostname_field)
    if markdown_match:
        return markdown_match.group(1)
    return hostname_field.strip()

Adding a New Server Entry

To manually append a server, insert into the appropriate alphabetical section following the established schema:

- hostname: "[time.example.de](https://time.example.de)"
  stratum: 2
  location: Germany
  owner: Example Corp
  notes: IPv4 and IPv6
  vm: false

This format mirrors entries found in lines 71-78 of the source file.

Generating Configuration Files

Convert the YAML into usable NTP daemon configurations with:

python3 scripts/ntpServerConverter.py nts-sources.yml

This command writes chrony.conf, ntp.toml, and updates README.md using the conversion logic in generate_chrony_conf.

Updating Stratum Values Automatically

Verify and refresh stratum data without manual editing:

python3 scripts/ntsUpdateServers.py --dry-run   # Preview changes

python3 scripts/ntsUpdateServers.py            # Apply updates

The script loads the YAML via load_yaml_file, queries each host through get_stratum, and persists changes via save_yaml_file (see the main() function, lines 90-124).

Summary

  • nts-sources.yml serves as the single source of truth for NTS server metadata in the jauderho/nts-servers repository.
  • The YAML schema requires hostname, stratum, location, owner, and vm fields, with optional notes.
  • Alphabetical grouping by country is mandatory per AGENTS.md requirements.
  • scripts/ntpServerConverter.py transforms this file into chrony.conf, ntp.toml, and README documentation.
  • scripts/ntsUpdateServers.py automates stratum verification and updates against live server data.
  • Hostname fields support Markdown link syntax, requiring regex parsing in downstream tools.

Frequently Asked Questions

What is the exact structure of the nts-sources.yml file?

The file contains a top-level servers key mapped to an ordered list of server entries. Each entry is a YAML mapping with six fields: hostname (string, supports Markdown), stratum (integer), location (string), owner (string), notes (optional string), and vm (boolean). The entire list is organized alphabetically by country to facilitate automated agent workflows.

How does the repository use nts-sources.yml to generate configs?

The Python script scripts/ntpServerConverter.py parses the YAML and invokes specialized generators: generate_chrony_conf produces Chrony daemon configurations, generate_ntp_toml creates ntpd-rs settings, and generate_markdown renders the server table for documentation. All outputs derive from this single YAML source to ensure consistency across the repository.

Can hostnames in nts-sources.yml contain formatting or URLs?

Yes. The hostname field accepts either plain text (e.g., time.cloudflare.com) or Markdown hyperlink syntax (e.g., [time.cloudflare.com](https://time.cloudflare.com)). Downstream tools like scripts/ntsUpdateServers.py extract the raw hostname using regex patterns to handle both formats correctly during stratum verification.

How are stratum values in nts-sources.yml kept accurate?

The scripts/ntsUpdateServers.py utility automates this process. It loads the YAML, queries each server using standard NTP tools (ntpdate/ntpq), and updates the stratum field if the live value differs from the stored value. Run with --dry-run to preview changes before applying them to the canonical file.

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 →