Deployment guide

ntpd-rs

Overview

ntpd-rs is a modern, memory-safe implementation of the Network Time Protocol, written in Rust by the Pendulum project. It is a full NTP client and server in one. It keeps this machine's own clock disciplined against the public NTP pool, and it serves accurate time to the other machines on your network, so you can run your own time source instead of relying on external servers for every device.

This guide covers the deployment and configuration of ntpd-rs on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images.

What you get:

  • ntpd-rs 1.9.0 installed from the official pinned, checksum-verified release, run under systemd as ntpd-rs.service
  • A client that disciplines this machine's clock from four distinct public NTP pool sources
  • A server that answers time requests from your machines on 0.0.0.0:123 (udp)
  • A local Unix observation socket (/var/run/ntpd-rs/observe) that ntp-ctl uses and that is never reachable from the network
  • The Prometheus metrics exporter, present but disabled by default (no management TCP port)
  • This instance's reachable server address, recorded to /root/ntpd-rs-credentials.txt (root only) on first boot

The image installs ntpd-rs 1.9.0 from the official pinned, checksum-verified package. The ntpd-rs.service daemon runs as an unprivileged ntpd-rs system user with only the capabilities it needs to read network time and set the system clock. It replaces the base image's default time synchronization. You administer it with the ntp-ctl command-line tool over a local Unix observation socket, so the management interface is never exposed to the network. The only network-facing surfaces the image opens are the NTP service on udp/123 and SSH.

Secure by default, with no known credentials. Serving network time requires no login and no password, so this image ships with none. The management and observation interface is bound to a local Unix socket, so it can never be reached from the network. The Prometheus metrics exporter is left disabled. On the first boot of every VM, a one-shot service records this instance's reachable address in a root-only file, so you know where to point your clients. ntpd-rs supports Network Time Security (NTS) for authenticated time. NTS is off by default because it needs a certificate your clients can trust, and this guide shows how to enable it with your own certificate.

Prerequisites

  • An active Azure subscription, an SSH public key, and a VNet and subnet in the target region
  • A subscription to the ntpd-rs listing on Azure Marketplace
  • Network Security Group rules that allow TCP 22 (administration) and UDP 123 (the NTP service) from the machines that will use this server for time

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a time server for a small to medium network. ntpd-rs is a lightweight daemon, so you need a larger size only for very large client populations.

1

Deploy from the Azure Portal

Search for ntpd-rs in the Marketplace, select the SecureAnyCloud publisher, and select Create. Configure the Network Security Group to allow UDP 123 from the machines that will use this server for time, and TCP 22 for administration.

2

Deploy from the Azure CLI

RG="time-prod"; LOCATION="eastus"; VM_NAME="ntp1" IMAGE_URN="sac1647283583153:ntpd-rs-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:ntpd-rs-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 123 --priority 1001

The NTP service uses UDP. Make sure the NSG rule you add for port 123 uses the UDP protocol so that clients can reach the server.

3

First boot: find your server address

On first boot, the image records this instance's reachable address so you know where to point your clients, and it starts ntpd-rs. This completes within seconds. SSH in as azureuser and read the record:

sudo cat /root/ntpd-rs-credentials.txt

The file records this server's NTP_SERVER_IP (the address your clients point at), the NTP_SERVER_PORT (123), and the local OBSERVE_SOCKET path used for management. There are no passwords in this file, because serving network time needs none. If your VM sits behind a Standard SKU public IP that the platform metadata does not expose, the recorded address may be the VM's private address. In that case, use your VM's public IP when you configure clients outside the VNet.

4

Confirm the server is running

Check that ntpd-rs.service is active and that ntp-daemon --version reports 1.9.0. The ntp-ctl status command shows the upstream pool sources this server disciplines its own clock from, which is the client role. When the daemon first starts, it reports Stratum 16 (not yet synchronized). Within a few minutes it selects sources and settles to a low stratum, typically 2 or 3.

ntp-daemon --version systemctl is-active ntpd-rs.service
sudo ntp-ctl status
5

Confirm it is serving time

Serving time is the purpose of this appliance. The server answers time requests from your machines. The daemon binds the NTP service on 0.0.0.0:123 (udp), and a real NTP client query returns a valid mode-4 (server) response that carries the current time. The offset shown is the difference from the querying client's clock, in seconds.

sudo ss -ulnp sport = :123 python3 /opt/ntpd-rs/ntp-query.py 127.0.0.1 123
6

Secure by default

The only network-facing surface besides SSH is the NTP service on udp/123. The management and observation interface that ntp-ctl uses is a local Unix socket, not a TCP port, so it can never be reached from the network. The Prometheus metrics exporter, which would open a TCP port, is left disabled.

sudo ss -tlnH ls -l /var/run/ntpd-rs/observe systemctl is-enabled ntpd-rs-metrics.service || true

The only non-loopback TCP listener is SSH on port 22. The 127.0.0.53/127.0.0.54 port 53 entries are the local DNS stub resolver and are not reachable from the network. The observe interface is a srw Unix socket, and the metrics service reports disabled.

7

Point a client at this server

To use this server for time, point your machines at its NTP_SERVER_IP (from Step 3). To confirm that the server answers on its own reachable address, run this on the VM itself:

SERVER_IP="$(hostname -I | awk '{print $1}')" echo "This server: ${SERVER_IP}" python3 /opt/ntpd-rs/ntp-query.py "${SERVER_IP}" 123

On a Linux client that uses systemd-timesyncd, set this server as the time source in /etc/systemd/timesyncd.conf. This is a configuration snippet for the client machine, not a command to run on the server:

[Time] NTP=<NTP_SERVER_IP>

Then apply it on the client with sudo systemctl restart systemd-timesyncd and confirm it with timedatectl show-timesync --property=ServerName. On Windows clients, set the NTP server with w32tm /config /manualpeerlist:<NTP_SERVER_IP> /syncfromflags:manual /update. Any standard NTP client works, because the server speaks standard NTPv4.

8

Serve additional networks and tune sources

The server configuration lives in /etc/ntpd-rs/ntp.toml. It ships serving on all interfaces (0.0.0.0:123) and disciplining its clock from the ntpd-rs.pool.ntp.org pool. To use your own upstream servers instead of the public pool, or to add a specific upstream, edit the [[source]] blocks. This is a configuration snippet:

# Discipline this server's clock from your own upstream NTP servers. [[source]] mode = "server" address = "upstream1.example.com" [[source]] mode = "server" address = "upstream2.example.com"

After editing the configuration, apply it with sudo systemctl restart ntpd-rs and re-check with sudo ntp-ctl status. Keep at least three upstream sources so that the algorithm can reject a single misbehaving source.

9

Enable Network Time Security (NTS)

ntpd-rs supports Network Time Security (RFC 8915), which authenticates NTP and protects it against tampering. NTS is off by default because an NTS-KE (key exchange) server needs a TLS certificate your clients can trust. To enable it, obtain a certificate for a hostname your clients resolve, for example with Let's Encrypt. Then add an NTS-KE server block to /etc/ntpd-rs/ntp.toml that references your certificate and key. This is a configuration snippet:

[[nts-ke-server]] listen = "0.0.0.0:4460" certificate-chain-path = "/etc/ntpd-rs/tls/fullchain.pem" private-key-path = "/etc/ntpd-rs/tls/privkey.pem"

Keep the private key at 0600 root:root. It is generated on your own instance and never leaves it. Open TCP 4460 in the NSG for NTS-KE, apply the change with sudo systemctl restart ntpd-rs, and point NTS-capable clients at your hostname. Because the certificate and key are yours and are created on your own VM, no secret is baked into the image.

Troubleshooting

A client cannot reach the server. Confirm that the NSG allows UDP 123 (not TCP) from the client, and that the client points at this server's reachable address from Step 3. From the server, python3 /opt/ntpd-rs/ntp-query.py 127.0.0.1 123 proves that the daemon is serving locally.

The server shows Stratum 16. This is normal immediately after start. ntpd-rs is conservative and takes a few minutes of polling to declare synchronization. sudo ntp-ctl status shows the sources and their offsets converging. If the server never leaves Stratum 16, confirm that the VM has outbound UDP 123 to the internet so that it can reach the pool.

Check server health. sudo ntp-ctl status shows the synchronization state and every source. sudo systemctl status ntpd-rs and sudo journalctl -u ntpd-rs show service logs.

Support

SecureAnyCloud provides 24/7 technical support for this ntpd-rs image. Our engineers can help with designing your time hierarchy, pointing clients at this server, tuning upstream sources, enabling Network Time Security with your own certificate, turning on loopback Prometheus metrics for monitoring, firewall and NSG rules, and ntpd-rs version upgrades. Critical issues receive a one hour average response time. Contact sales@secureanycloud.com.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch ntpd-rs 1.9.0 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure