Debian 12 UART - BYO-NTP/recipes GitHub Wiki

This page is a build recipe for a Stratum 1 NTP server on a server with serial (UART) ports, Debian 12, one of the 4 GNSS listed in the table, and any of the NTP daemons listed. For the best precision, this recipe connects the GNSS to the server via a RS232 Serial to TTL adapter. This build is comparable to the Pi-only GPIO build and superior to the USB build for servers without either.

date server os gnss daemon 🗣️
2025-07 Generic Debian12 LEA-M8TMAX-M8Q chronyNTPsecntp discuss

1. Install OS

Install Debian per the Debian install guide.

Note: a visit to the computers BIOS may be required to enable the UART / serial port.

remote login

ssh xeonE5
su -
cat $HOME/.ssh/authorized_keys > ~root/.ssh/authorized_keys
echo 'SSHD_OPTS=-o PermitRootLogin=without-password' > /etc/default/ssh
service sshd restart
exit; exit  # disconnect
ssh root@xeonE5

install prereqs, fixups, and niceties

apt install -y sudo curl gpg
apt update && apt -y upgrade
apt autoremove -y

systemctl disable systemd-timesyncd.service
curl -sS https://byo-ntp.github.io/tools/zsh/install.sh | sh

systemctl stop brltty; systemctl disable brltty

2. Configure GNSS

Follow the assembly instructions for your GNSS on the Assemble UART TTL page.

Connect the RS-232 adapter to the computer and plug in the USB to TTL adapter to power it.

3. Configure UART

Liberate ttyS0 from getty:

systemctl disable --now [email protected]
systemctl mask [email protected]

Configure the serial port and verify we get serial output:

/bin/stty -F /dev/ttyS0 cs8 clocal -cstopb -parenb -echo raw 115200
cat /dev/ttyS0
# TODO: add real data

Create a symlink to /dev/gps0, and enable low_latency on the serial port:

apt install -y setserial
cat > /etc/udev/rules.d/10-gps.rules <<EOL
# symlink /dev/ttyS0 to /dev/gps0
KERNEL=="ttyS0", SYMLINK+="gps0", GROUP="dialout", MODE="0660"

# configure the serial port for low latency.
KERNEL=="ttyS0", RUN+="/bin/setserial /dev/ttyS0 low_latency"
EOL

udevadm control --reload-rules
udevadm trigger

4. Configure PPS

apt install -y pps-tools

modprobe pps_ldisc
ldattach PPS /dev/ttyS0

5. Install a NTP daemon

Offsets

The latency of each GNSS requires a custom offset (in milliseconds), so export the GNSS specific value from the table:

gnss NMEA
M8Q 0.5
export GNSS_OFFSET_NMEA="0.5"

If needed, each section heading is a link with many more details about installing, configuring, and verifying that particular NTP daemon. Otherwise, choose the commands for the NTP daemon you want and the installer will do the rest.

chrony

export NTP_REFCLOCKS=$(cat <<EO_CHRONY
refclock SHM 0 refid NMEA poll 2 precision 2e-2 offset $GNSS_OFFSET_NMEA
refclock SHM 1 refid PPS  poll 2 precision 3e-6 lock NMEA trust
EO_CHRONY
)
curl -sS https://byo-ntp.github.io/tools/chrony/install.sh | sh

NTPsec

export NTP_REFCLOCKS=$(cat <<EO_NTPSEC
refclock nmea refid NMEA minpoll 3 maxpoll 4 time2 $GNSS_OFFSET_NMEA baud 115200 prefer
refclock pps  refid PPS  minpoll 1 maxpoll 2
EO_NTPSEC
)
curl -sS https://byo-ntp.github.io/tools/ntpsec/install.sh | sh

ntp

export NTP_REFCLOCKS=$(cat <<EO_NTP
server 127.127.20.0 minpoll 3 maxpoll 4 mode 80 prefer
fudge  127.127.20.0 refid NMEA time2 $GNSS_OFFSET_NMEA minjitter 0.3

server 127.127.22.0 minpoll 3 maxpoll 4 prefer
fudge  127.127.22.0 refid PPS minjitter 0.01
EO_NTP
)
curl -sS https://byo-ntp.github.io/tools/ntp/install.sh | sh

Observe

  • watch the status in near real time (requires installing gnu-watch):
    • printf '\e[8;9;80t'; ssh -t pi5 gnu-watch -n2 chronyc sources
    • printf '\e[8;9;80t'; ssh -t pi5 gnu-watch -n2 ntpq -c peer
  • Measure the offset
  • Gather statistics with telegraf + influxdb + grafana or similar.

References

Performance

gnss chrony NTPsec ntp
M8Q 8.8 µs ? µs ? µs