Time Server (Chrony)
Chrony provides NTP time synchronization for all infrastructure nodes. It runs as a native systemd service on a dedicated VM in each environment, synchronizing from upstream NTP servers and serving time to the local network.
Deployment order
NTP deploys after Networking and Step-CA, and before monitoring and applications.
Architecture
graph TD
Upstream["Upstream NTP Servers\n(NIST, Cloudflare, etc.)"]
Chrony["Chrony Server\n(.123)"]
VM1[Infrastructure VMs]
VM2[Application VMs]
Upstream -->|sync| Chrony
Chrony -->|serve time| VM1
Chrony -->|serve time| VM2
The Chrony server synchronizes with multiple upstream NTP sources and acts as a stratum 10 local clock for the network. All VMs in the environment point to the local Chrony server instead of querying public NTP servers directly.
File Locations
| File | Purpose |
|---|---|
playbooks/infrastructure/ntp/deploy.yml |
Main playbook |
playbooks/infrastructure/ntp/tasks/chrony.yml |
Installation and configuration task |
playbooks/infrastructure/ntp/templates/servers.conf.j2 |
Upstream NTP server list |
playbooks/infrastructure/ntp/templates/allow.conf.j2 |
Client access allow list |
playbooks/infrastructure/ntp/templates/server.conf.j2 |
Server mode settings |
playbooks/infrastructure/ntp/handlers/main.yml |
Service restart handler |
environments/<env>/group_vars/infra_ntp/chrony.yml |
Per-environment NTP variables |
Hosts
| Environment | IP | FQDN |
|---|---|---|
| WIL | 10.2.20.123 |
time.wil.5am.cloud |
| LDN | 10.3.20.123 |
time.ldn.5am.cloud |
Deployment
The task file:
- Installs
chronyvia apt - Deploys upstream server configuration to
/etc/chrony/conf.d/servers.conf - Deploys client allow list to
/etc/chrony/conf.d/allow.conf - Deploys server mode config to
/etc/chrony/conf.d/server.conf - Enables and starts the
chronyservice - Verifies synchronization with
chronyc tracking - Displays status output
Server Mode Configuration
The server.conf.j2 template configures Chrony to operate as a local time source:
local stratum 10— acts as a time source even if upstream servers are unreachablertcsync— synchronizes the system clock with the hardware clockhwtimestamp *— enables hardware timestamping on all interfaces for precision
Sources: ansible/playbooks/infrastructure/ntp/tasks/chrony.yml · ansible/playbooks/infrastructure/ntp/templates/server.conf.j2
Configuration Reference
All variables are set in ansible/environments/<env>/group_vars/infra_ntp/chrony.yml.
| Parameter | Type | Description | Default |
|---|---|---|---|
chrony_ntp_servers |
list[string] |
Upstream NTP servers (uses geographically local servers per-env) | (per-env) |
chrony_allow |
list[string] |
Networks allowed to query this NTP server | (per-env) |
Sources: ansible/environments/wil/group_vars/infra_ntp/chrony.yml · ansible/playbooks/infrastructure/ntp/templates/servers.conf.j2 · ansible/playbooks/infrastructure/ntp/templates/allow.conf.j2
Common Tasks
Verify time synchronization
SSH to the NTP server and check the tracking status:
Key fields to check:
- Reference ID — upstream server currently in use
- Stratum — should be 2-3 (one hop from the upstream stratum 1 server)
- System time — offset from NTP time (should be sub-millisecond)
Check connected clients
Add a new upstream NTP server
-
Edit
ansible/environments/<env>/group_vars/infra_ntp/chrony.yml: -
Deploy:
Allow a new network
-
Add the network CIDR to
chrony_allow: -
Deploy: