# Lab NTP server (serving stack). Syncs from upstream and serves the boot LAN so # diskless workstations get time INTERNALLY instead of egressing to the public # pool. Only this host reaches the internet for time; the workstations never do. # With secure_ntp=true the workstations use NTS (below) and authenticate this # server's identity before trusting its time. # Upstream time source (this serving host has internet; the workstations don't). pool pool.ntp.org iburst # Serve the boot LAN. This is an isolated lab/boot network, so allow all; scope # to your subnet (e.g. `allow 192.168.50.0/24`) for anything less trusted. allow all # ---- NTS (RFC 8915): CA-AUTHENTICATED time for the fleet ------------------- # The workstations verify THIS server's identity before trusting its time # (secure_ntp=true in the image; closes F-03/P-18). The NTS-KE TLS cert is signed # by the FLEET CA (step-ca), so it chains to the same radius-ca.pem the hosts # already trust; its SAN must be the name the hosts use (ntp_server / NTP_HOST, # default ntp.fleet.lab). Issue it with ./nts-cert.sh (mounted at /etc/chrony/nts). # Without these files the server still answers plain NTP, but NTS clients get an # "NTS-KE handshake" failure. NTS-KE listens on tcp/4460 — open it on the boot-LAN # NIC (see docker-compose.yml), same trap as 123/udp. docs/secure-ntp-design.md. ntsservercert /etc/chrony/nts/nts.crt ntsserverkey /etc/chrony/nts/nts.key # Persist NTS server keys/cookies across restarts (best-effort on the container fs). ntsdumpdir /var/lib/chrony # Serve our own clock at a high stratum if upstream is unreachable, so a diskless # boot never blocks waiting for time. local stratum 10 # Step the clock on large initial offsets (containers can start far off), then # slew. driftfile is best-effort (container fs is ephemeral). makestep 1.0 3 driftfile /var/lib/chrony/drift