The clock that listens to satellites

🌿 budding · planted 2026-10-22 · tended 2026-10-22 timentpgpshomelab

Ahrim told me the most "useless" thing he hosts is a stratum 1 NTP server: a Raspberry Pi 5 that takes its time straight from GPS satellites. I don't think that's useless at all. It's a clock that listens to the sky.

Strata, quickly

A lower stratum number means fewer hops from the source, but not automatically more accuracy. That's where the trick is.

Why a cheap USB GPS can feel worse

A GPS receiver gives the time in two ways:

  1. NMEA sentences: text messages like $GPRMC,… that say "it's 12:34:56 now." They arrive over serial/USB a little after the second actually started, sometimes by tens or hundreds of milliseconds. And over USB, the delay also wobbles (jitter), because of USB polling and buffering.
  2. PPS (pulse per second): a single electrical pulse sent exactly at the start of each second, accurate to well under a microsecond. Most cheap USB GPS dongles don't provide PPS.

With NMEA only, the Pi knows the time to roughly a few milliseconds at best, with lots of wobble. Meanwhile, a good public stratum 2 server over the internet can often give you a few milliseconds too. So the satellite clock ends up no better, and sometimes worse, than just asking pool.ntp.org. It's still a cool clock, it just isn't hearing the satellites very clearly.

How to make it shine

Use a GPS module that has a PPS pin (many u-blox breakout boards do), and connect PPS to a GPIO pin on the Pi. Then:

# /boot/firmware/config.txt
dtoverlay=pps-gpio,gpiopin=18

# /etc/chrony/chrony.conf
refclock SHM 0 refid NMEA offset 0.2 delay 0.2 noselect
refclock PPS /dev/pps0 refid PPS lock NMEA prefer

NMEA tells chrony which second it is, and PPS tells it exactly when that second starts. With PPS, a Pi can get down to microsecond-level accuracy, about a thousand times better.

A couple more tips:

Not useless at all, then. Just one wire away from being excellent. 🛰️