Posted on Leave a comment

Build a Stratum 1 NTP Server for Under $20

Build a Stratum 1 NTP
Server for Under $20

Your home lab’s time is lying to you. Here’s how to fix that with
a $15 GPS dongle and a Raspberry Pi.


Every device on your network is syncing time from somewhere. Usually
it’s your router, which is syncing from some pool.ntp.org server, which
itself is three or four hops removed from an actual atomic clock. By the
time that timestamp reaches your endpoints, it’s carrying accumulated
drift, network jitter, and whatever latency the upstream pool is having
today.

For most home use, this is fine. For Raspberry Pi clusters, ham radio
digital modes, logging infrastructure, or anything where precise
timestamping matters, it’s noise.

A Stratum 1 NTP server solves this permanently: GPS satellites carry
atomic-clock-derived time. A GPS receiver with a pulse-per-second (PPS)
signal gives you sub-microsecond accuracy. Your entire network syncs
directly from that, with no upstream dependency, no internet
requirement, no pool latency.

Here’s how to build one for under $20.


What You Need

Hardware: – Raspberry Pi (any model — Pi Zero W, Pi
3, Pi 4 all work) – VK-162
USB GPS dongle
— ~$15 on Amazon – microSD card (8GB+ with Raspberry
Pi OS Lite) – Power supply

That’s it. No HAT, no additional hardware, no
soldering. The VK-162 connects over USB and presents as a standard
serial device. Most builds stop here.

Optional for higher accuracy: – GPIO PPS signal
(requires a GPS module with PPS output — the VK-162 doesn’t have an
exposed PPS pin, so this guide uses USB serial for ~1ms accuracy rather
than sub-microsecond. For precision timing applications, see note
below.)

Note: The VK-162 uses a u-blox chipset over USB, which gives you
good accuracy for a homelab NTP server (millisecond-range). If you need
sub-microsecond PPS accuracy for lab instrumentation or network timing,
you’ll want a GPIO-connected GPS module with a PPS output. For home
networks, logging, ham radio, and most homelab use cases, the VK-162
over USB is more than adequate.


Step 1: Flash and
Boot Raspberry Pi OS Lite

Use Raspberry Pi Imager to flash Raspberry Pi OS Lite (64-bit).
Enable SSH during the flash process. No desktop needed — this will run
headless.

Boot, SSH in, update:

sudo apt update && sudo apt upgrade -y

Step 2: Install gpsd

gpsd is the standard GPS daemon for Linux. It handles
talking to the GPS device and exposes a clean socket that other
applications (including chrony) can read.

sudo apt install -y gpsd gpsd-clients

Plug in your VK-162. It will appear as a serial device — usually
/dev/ttyACM0:

ls /dev/ttyACM*

Test that GPS data is coming through:

sudo gpsd /dev/ttyACM0 -F /var/run/gpsd.sock
cgps -s

You should see satellite count, position, and time data after GPS
acquires a fix (put the dongle near a window — it needs sky view). First
fix can take 1-2 minutes cold, faster with a clear view.

If cgps shows data, gpsd is working. Stop it for
now:

sudo killall gpsd

Step 3: Configure gpsd

Edit the default configuration:

sudo nano /etc/default/gpsd
START_DAEMON="true"
GPSD_OPTIONS="-n"
DEVICES="/dev/ttyACM0"
USBAUTO="true"
GPSD_SOCKET="/var/run/gpsd.sock"

Enable and start the service:

sudo systemctl enable gpsd
sudo systemctl start gpsd

Step 4: Install and
Configure Chrony

chrony is a modern NTP implementation that handles GPS
sources well. Replace whatever NTP daemon your system is running:

sudo apt install -y chrony

Edit the chrony configuration:

sudo nano /etc/chrony/chrony.conf

Add these lines (keep any existing pool lines as fallback, or remove
them if you want GPS-only):

# GPS via gpsd
refclock SHM 0 refid GPS precision 1e-1 offset 0.9999 delay 0.2
refclock SHM 2 refid PPS precision 1e-9

# Fallback pools (optional — remove if you want air-gapped operation)
pool 2.debian.pool.ntp.org iburst

# Allow your local network to sync from this server
allow 192.168.0.0/24

# Serve time even if not synced (useful during GPS acquisition)
local stratum 1

Restart chrony:

sudo systemctl restart chrony

Step 5: Verify It’s Working

Check chrony sources:

chronyc sources -v

You should see GPS listed as a source. It will show as ?
initially while acquiring. After GPS lock, it becomes *
(selected) or + (acceptable). This takes a few minutes.

MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* GPS                           0   4   377    11   -142ns[  +30ns] +/-  953us

That * means chrony is using your GPS as its primary
time source. Your NTP server is now Stratum 1.

Check what your server is now reporting to clients:

chronyc tracking

Look for Stratum : 1. That’s it — you’re done.


Step 6: Point Your Network At
It

On your router or other devices, set the NTP server to your Pi’s IP
address. For home networks, updating the router’s NTP setting pushes
accurate time to every device automatically.

For Linux hosts you want to point directly:

# /etc/chrony/chrony.conf or /etc/ntp.conf
server 192.168.1.x iburst

Accuracy Expectations

With the VK-162 over USB serial, you can expect accuracy in the 1-10
millisecond range — more than sufficient for:

  • Home lab infrastructure
  • Ham radio digital modes (FT8, WSJT-X, APRS)
  • Logging and telemetry timestamps
  • Network monitoring and analysis
  • General sysadmin time sync

For applications requiring microsecond or sub-microsecond accuracy
(telecom infrastructure, financial trading systems, scientific
instrumentation), you’ll want a GPS module with a hardware PPS output
connected to a GPIO pin. That’s a different, more complex build.


Why the VK-162

It’s not the cheapest USB GPS dongle. It’s the one that actually
works without fighting with drivers.

The VK-162 uses a u-blox chipset and presents as a standard CDC-ACM
serial device — no proprietary drivers, no vendor software required.
It’s plug-and-play on Raspberry Pi OS, Ubuntu, Fedora, FreeBSD, and most
Linux distributions. gpsd recognizes it immediately.

Cheap dongles with SiRF or MediaTek chipsets often require specific
baud rates, initialization strings, or kernel modules that cause
headaches. The u-blox chipset is the industry standard for a reason.

Get
the VK-162 on Amazon →


Troubleshooting

GPS not appearing as /dev/ttyACM0: Try
/dev/ttyUSB0. Check dmesg | grep -i usb after
plugging in.

cgps shows no fix: Put the antenna near a window.
The VK-162 can acquire indoors near glass but struggles in basements or
metal-enclosed spaces.

Chrony showing GPS as ? after 10+
minutes:
Check that gpsd is running
(systemctl status gpsd) and that the socket path matches
your chrony config.

Chrony ignoring GPS source: The SHM offset value
(0.9999) may need tuning for your hardware. Start with a
larger allowed offset in chrony.conf: maxdistance 1.0.


What You’ve Built

A GPS-disciplined NTP server that: – Syncs directly from satellite
time signals – Needs no internet connection to operate – Serves your
entire local network as Stratum 1 – Costs less than one month of most
cloud monitoring services – Runs on hardware you probably already
have

Time is infrastructure. It should be reliable, local, and yours.


VK-162
USB GPS Dongle on Amazon →

Leave a Reply

Your email address will not be published. Required fields are marked *