Grovestreet NTP
A public Stratum 1 GPS-synchronized NTP server providing precise time to our cul-de-sac and beyond!
Stats
Full statistics →This server
Pool scores →Live
History →Your sync stats
--Clock
--Traffic
--GPS
--How this works
The Open Time Project provides free, high-accuracy time synchronisation from a GPS-disciplined Stratum 1 server. Where a Stratum 2 server takes its time from other servers over the internet, this one derives it directly from GPS satellites, to nanoseconds.
The signal path
GPS satellites → u-blox NEO-M9N. The satellites carry atomic clocks and broadcast precise time. The receiver on the TimeHAT turns that broadcast into two separate outputs:
- NMEA sentences - serial data carrying time of day, position and satellite info
- PPS (pulse per second) - an electrical pulse on each UTC second boundary
PPS → SDP2 → PHC. The pulse runs over a direct PCB trace into SDP2, a pin on the Intel I226-LM NIC. The card's PHC (PTP Hardware Clock), backed by a TCXO (Temperature Compensated Crystal Oscillator), timestamps the exact instant the edge arrived.
ts2phc → PHC discipline. A pulse is defined to land on .000000000, so any other reading is error. ts2phc reads the timestamp, works out that error - "the PHC called it .000000247, so it is 247 ns fast" - and trims the PHC's frequency to match. That feedback loop is what holds the hardware clock to GPS within nanoseconds.
PHC → chrony → clients. chrony reads the disciplined PHC as its only selected source. The PHC counts in TAI (International Atomic Time, currently UTC + 37 s), so chrony applies that offset before answering in UTC.
What NMEA is actually for
NMEA does reach chrony, through gpsd's shared memory, but that refclock
is configured noselect: chrony measures it and shows it,
and never steers the clock with it. Serial framing leaves it about
45 ms behind the second it describes, against a pulse the NIC
timestamps to within tens of nanoseconds. It earns its place as a
cross-check on the receiver, not as a source of time.
The date is set once, at startup, from this server's own internet sources, and the PHC is seeded from it. After that the pulse alone keeps the clock true.
Holdover
If GPS is lost, the TCXO carries the clock unaided. At roughly 280 ppb stability that is about 1 ms of drift per hour, far longer than a reacquisition takes.
Hardware
Raspberry Pi 5, TimeHAT v6, TCXO-backed Intel I226-LM NIC with hardware timestamping, u-blox NEO-M9N GPS module.
Resources
Clock health
Disciplined by GPS pulse-per-second through the NIC hardware clock. Every reading below is shown against the envelope it is expected to hold.
Clock offset from GPS
-
Point your clock at this server
Windows GUI configuration
- Open Settings → Time & Language → Date & Time
- Click Additional clocks (or Related settings → Additional date, time & regional settings)
- Click Internet Time tab → Change settings
- Enter the server address and click Update now:
ntp.grovestreet.zip
Command line (Administrator)
Open Command Prompt as Administrator and run:
w32tm /config /manualpeerlist:"ntp.grovestreet.zip" /syncfromflags:manual /update
net stop w32time && net start w32time
w32tm /resync
Verify synchronization
w32tm /query /status
w32tm /stripchart /computer:ntp.grovestreet.zip /samples:5
macOS GUI configuration
- Open System Settings (or System Preferences on older macOS)
- Go to General → Date & Time
- Click Set date and time automatically and enter:
ntp.grovestreet.zip
Terminal: one-time sync
sudo sntp -sS ntp.grovestreet.zip
Terminal: permanent configuration
sudo systemsetup -setnetworktimeserver ntp.grovestreet.zip
sudo systemsetup -setusingnetworktime on
Ubuntu / Debian (systemd-timesyncd)
# Edit configuration
sudo nano /etc/systemd/timesyncd.conf
# Add under [Time]:
[Time]
NTP=ntp.grovestreet.zip
# Restart service
sudo systemctl restart systemd-timesyncd
timedatectl timesync-status
Using chrony (recommended)
# Install chrony
sudo apt install chrony
# Edit config
sudo nano /etc/chrony/chrony.conf
# Add at the top:
server ntp.grovestreet.zip iburst
# Restart
sudo systemctl restart chronyd
chronyc sources -v
RHEL / Fedora / Rocky
sudo dnf install chrony
sudo nano /etc/chrony.conf
# Add: server ntp.grovestreet.zip iburst
sudo systemctl enable --now chronyd
chronyc tracking
Arch Linux
sudo pacman -S chrony
echo "server ntp.grovestreet.zip iburst" | sudo tee -a /etc/chrony.conf
sudo systemctl enable --now chronyd
Active Directory Group Policy
Configure via Group Policy Management (gpmc.msc):
Computer Configuration
→ Administrative Templates
→ System
→ Windows Time Service
→ Time Providers
→ Configure Windows NTP Client
Settings:
NtpServer: ntp.grovestreet.zip,0x9
Type: NTP
CrossSiteSyncFlags: 2
ResolvePeerBackoffMinutes: 15
ResolvePeerBackoffMaxTimes: 7
SpecialPollInterval: 3600
EventLogFlags: 0
PowerShell (domain controllers)
# On PDC Emulator
w32tm /config /manualpeerlist:"ntp.grovestreet.zip" /syncfromflags:manual /reliable:yes /update
Restart-Service w32time
w32tm /resync /rediscover
Note: only configure the PDC Emulator to sync externally. Other DCs sync from it via the domain hierarchy.
DHCP Option 42 (NTP servers)
Configure your DHCP server to distribute the NTP server address automatically to all clients.
ISC DHCP Server
# /etc/dhcp/dhcpd.conf
option ntp-servers ntp.grovestreet.zip;
Windows DHCP Server
# PowerShell
Add-DhcpServerv4OptionDefinition -OptionId 42 -Name "NTP Servers" -Type IPv4Address -MultiValued
Set-DhcpServerv4OptionValue -OptionId 42 -Value "178.238.99.189"
# Or via GUI:
# DHCP Manager → Server Options → Configure Options
# → 042 NTP Servers → Add IP address
pfSense / OPNsense
Services → DHCP Server → [Interface]
→ Other Options → NTP Server 1: 178.238.99.189
Ubiquiti UniFi
Settings → Networks → [Network] → DHCP
→ DHCP NTP Server: 178.238.99.189
Option 42 takes a literal address on many DHCP implementations, which is why the IP appears here rather than the hostname.
Get server time via curl
This server responds to curl and other CLI tools with the current GPS-disciplined time directly. No NTP client required - just a terminal.
Quick start
curl ntp.grovestreet.zip
Returns an ISO 8601 UTC timestamp, e.g. 2026-02-08T14:23:45.123Z
Output formats
Use the ?format= parameter to choose how the time is displayed:
# ISO 8601 (default)
curl ntp.grovestreet.zip
# → 2026-02-08T14:23:45.123Z
# Unix timestamp (seconds since epoch)
curl "ntp.grovestreet.zip?format=unix"
# → 1738938225.123456
# Human-readable
curl "ntp.grovestreet.zip?format=human"
# → Sunday, February 08, 2026 14:23:45.123456 UTC
# Full server card with stats
curl "ntp.grovestreet.zip?format=all"
Timezone support
Add ?tz= with any
IANA timezone name
to get localized output. The default is UTC.
# Amsterdam (CET/CEST)
curl "ntp.grovestreet.zip?tz=Europe/Amsterdam"
# → 2026-02-08T15:23:45.123+0100
# New York (EST/EDT)
curl "ntp.grovestreet.zip?tz=America/New_York"
# → 2026-02-08T09:23:45.123-0500
# Tokyo (JST)
curl "ntp.grovestreet.zip?tz=Asia/Tokyo"
# → 2026-02-08T23:23:45.123+0900
# Combine format and timezone
curl "ntp.grovestreet.zip?format=human&tz=Europe/Amsterdam"
# → Sunday, February 08, 2026 15:23:45.123456 Europe/Amsterdam (UTC+01:00)
Discover timezones
Don't know your timezone identifier? Search for it:
# List all available timezones
curl "ntp.grovestreet.zip?format=tzlist"
# Search for a specific region
curl "ntp.grovestreet.zip?format=tzlist" | grep -i amsterdam
# → Europe/Amsterdam
curl "ntp.grovestreet.zip?format=tzlist" | grep -i "new_york"
# → America/New_York
Timezone names follow the IANA Time Zone Database (also known as the Olson database). Full reference: Wikipedia - List of tz database time zones.
Dedicated endpoint
The /time path works the same way but is always plain text -
useful for browser access or scripts that set a custom User-Agent:
# These are equivalent:
curl ntp.grovestreet.zip
curl ntp.grovestreet.zip/time
# Works in browsers too:
# https://ntp.grovestreet.zip/time?format=human&tz=Europe/Amsterdam
Response headers
Every response includes machine-readable headers for programmatic use:
# Inspect headers with -v or -I
curl -I "ntp.grovestreet.zip?tz=Europe/Amsterdam"
# X-Server-Timestamp: 1738938225.123456 (Unix time, always UTC)
# X-Stratum: 1 (NTP stratum level)
# X-Timezone: Europe/Amsterdam (Requested timezone)
Supported CLI tools
The server automatically detects these tools and responds with plain text
instead of the web dashboard: curl · wget · HTTPie · Python requests ·
PowerShell · Go http.Client · aiohttp · lwp-request · fetch. If your tool
isn't detected, use the /time endpoint directly.