A GPS-backed time server is not required for an ordinary Windows network. Public NTP services are suitable for most environments. However, a local GPS source is a useful home-lab project and provides an independent internal reference that can continue operating without Internet access.

The most difficult part is often not installing Chrony. It is working out which Linux device appeared when the GPS receiver was connected, confirming that data is flowing from it and then making GPSD and Chrony use the same device.

What this build uses

  • An always-on Linux computer.
  • A USB GPS receiver.
  • GPSD to read and interpret the receiver.
  • Chrony to discipline the Linux clock and provide NTP to the network.
  • A web interface to make the state of the service easier to understand.
  • An internal DNS name such as time.example.com.

The Linux computer can be a small physical system, a Raspberry Pi or another always-on host. A physical system is usually simpler where the receiver provides PPS because USB pass-through and hardware timing add unnecessary complications to a virtual machine.

Choosing the GPS receiver

A basic USB GPS receiver can provide date and time through NMEA serial messages. A receiver with a usable pulse-per-second output can provide much more precise timing.

Before buying a receiver, check:

  • Linux compatibility.
  • Whether it appears as a standard USB serial device.
  • Whether the receiver exposes PPS to Linux.
  • Whether an external antenna is required for the intended location.
  • Whether the cable is long enough to place the antenna near a window.

Install the Linux system

This guide assumes a current Debian or Ubuntu Server installation with a normal user account that can run commands through sudo.

sudo apt update
sudo apt full-upgrade

Restart if the update installed a new kernel:

sudo reboot

Install Chrony, GPSD and diagnostic tools

sudo apt install chrony gpsd gpsd-clients pps-tools usbutils

The packages provide:

  • chrony – the NTP client and server.
  • gpsd – the service that reads the GPS receiver.
  • gpsd-clients – tools including cgps and gpsmon.
  • pps-tools – diagnostic tools for a PPS device.
  • usbutils – the lsusb command.

Do not configure Chrony yet. The first task is to identify the receiver.

Connect the GPS receiver

Before connecting the receiver, run:

sudo dmesg --follow

Leave that command running and connect the GPS receiver. Linux should report a new USB device and usually assign it a serial device name such as /dev/ttyUSB0 or /dev/ttyACM0.

Press Ctrl+C to leave the live display.

Confirm that Linux can see the USB device

lsusb
ls -l /dev/ttyUSB*
ls -l /dev/ttyACM*

One of the last two commands may report that no matching files exist. That is normal if the receiver uses the other device type.

A typical result is:

crw-rw---- 1 root dialout 188, 0 Aug  4 19:12 /dev/ttyUSB0

Use a persistent device name

Names such as /dev/ttyUSB0 can change if another USB serial device is connected.

ls -l /dev/serial/by-id/

A result may resemble:

usb-u-blox_AG_-_www.u-blox.com_u-blox_GNSS_receiver-if00 -> ../../ttyACM0

A path beneath /dev/serial/by-id/ is normally preferable in service configuration because it remains tied to the device rather than its current USB number.

Check whether raw GPS data is arriving

Stop GPSD temporarily so a diagnostic tool can open the serial device directly:

sudo systemctl stop gpsd.socket
sudo systemctl stop gpsd

Run gpsmon against the actual device path:

sudo gpsmon /dev/ttyUSB0

Replace the example path with the one found earlier. A working receiver should produce continuously changing data, often with NMEA sentences beginning with values such as:

$GPRMC
$GPGGA
$GPGSA
$GPGSV

Receivers supporting several satellite systems may use GN rather than GP.

If the screen remains empty, stop here. Chrony cannot use a receiver from which Linux is receiving no data.

If gpsmon shows no data

  • Confirm the correct serial device was used.
  • Confirm GPSD is not still holding the serial port.
  • Confirm the receiver appears in lsusb.
  • Confirm the required USB serial module loaded.
  • Confirm the receiver has power and a reasonable view of the sky.
sudo lsof /dev/ttyUSB0
sudo dmesg | tail -n 50
lsmod | grep -E 'usbserial|cdc_acm|pl2303|cp210x|ftdi_sio'

Do not load a module with copied vendor and product identifiers unless they match the receiver shown by lsusb.

Configure GPSD with the receiver

On Debian and Ubuntu, the package commonly stores startup settings in:

/etc/default/gpsd

Open the file:

sudo nano /etc/default/gpsd

Use the persistent path found earlier:

START_DAEMON="true"
USBAUTO="false"
DEVICES="/dev/serial/by-id/REPLACE-WITH-THE-ACTUAL-DEVICE"
GPSD_OPTIONS="-n"
OPTIONS=""

The -n option tells GPSD to begin reading the receiver without waiting for a client to connect.

Start GPSD

sudo systemctl enable gpsd
sudo systemctl restart gpsd
systemctl status gpsd --no-pager

If the distribution uses gpsd.socket, inspect both units:

systemctl status gpsd gpsd.socket --no-pager

Verify GPSD with cgps

cgps -s

Wait for a fix. Useful fields include status, UTC time, latitude and longitude, and the number of satellites used.

A position fix is useful evidence that the receiver works. The time-server build is concerned primarily with UTC time and, where available, PPS.

Check for a PPS device

ls -l /dev/pps*

If the receiver and driver expose PPS, a device such as /dev/pps0 may appear.

sudo ppstest /dev/pps0

A working PPS source should produce a new assertion or pulse once per second.

If no PPS device exists, the receiver may not expose PPS through USB, the driver may not support it, or additional hardware may be required. Message-based GPS timing can still be used, but it will not provide the same precision.

What must work before continuing

  • The receiver appears in lsusb.
  • Linux assigns a serial device.
  • A persistent /dev/serial/by-id/ path exists where possible.
  • gpsmon shows live data.
  • GPSD starts with the correct device.
  • cgps -s shows decoded UTC and a valid fix.
  • ppstest shows one pulse per second where PPS is supported.

Part two will connect the proven GPSD source to Chrony, configure the server for internal clients, install the web interface, verify Stratum 1 operation and configure Windows and network devices to use an internal DNS name.

Project documentation

Related information