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 includingcgpsandgpsmon.pps-tools– diagnostic tools for a PPS device.usbutils– thelsusbcommand.
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. gpsmonshows live data.- GPSD starts with the correct device.
cgps -sshows decoded UTC and a valid fix.ppstestshows 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.