Kenyon Ralph

Time server

This page documents my project to build a stratum 1 NTP time server at my house. Its hostname is ntp.kenyonralph.com.

  1. GPS selection
  2. Cable Construction
  3. GPS preparation
  4. Debian GNU/Linux setup
  5. FreeBSD setup
    1. /etc/rc.conf
    2. /etc/devfs.conf
    3. /etc/ttys
    4. Kernel configuration
    5. /etc/make.conf
    6. /etc/ntp.conf
    7. Example output
  6. Conclusion
  7. Notes
  8. References

GPS selection

I selected the Garmin GPS 18x LVC for the following reasons:

I ordered the 18x (and a serial cable) on Amazon on 2011-09-05. UPS delivered it on 2011-09-09.

Cable Construction

I simply spliced the GPS 18x LVC wires onto serial and USB wires. This matches what’s documented in Garmin’s GPS 18x LVC Technical Specifications.

GPS preparation

I used a Windows Vista computer with Garmin’s SNSRXCFG_270.exe to upgrade the firmware from version 3.60 to the latest, 3.70. I also used SNSRXCFG_270.exe to set the PPS pulse width to 200 ms, and disable all NMEA sentences except GPGGA.

Debian GNU/Linux setup

March 2022 update: I’m now running my stratum 1 time server on a Shuttle DS10U running Debian 11 bullseye. The Garmin GPS 18x LVC is connected to the serial port. gpsd reads the NMEA sentences and pulse per second (PPS), and chrony provides NTP service. I basically followed this documentation and configured everything with puppet. This commit and the two parent commits are the implementation.

Old setups:

Here are the steps in summary (written for Debian wheezy in February 2015):

Some details:

When you do sudo ldattach PPS /dev/ttyS0, the PPS modules will be loaded automatically and the device /dev/pps0 will be created. Place some udev rules in /etc/udev/rules.d/77-local.rules to create device symlinks and run ldattach automatically:

SUBSYSTEM=="pps", MODE="0664" GROUP="dialout"
KERNEL=="ttyS2", RUN+="/bin/stty --file=/dev/ttyS2 9600"
KERNEL=="ttyS2" SYMLINK+="gps0"
KERNEL=="pps0" SYMLINK+="gpspps0"

systemd unit to run ldattach (enable with systemctl enable ldattach@ttyS2):

[Unit]
Description=PPS Line Discipline for GPS Timekeeping for %i
Before=ntpd.service

[Service]
ExecStart=/usr/sbin/ldattach pps /dev/%i
Type=forking

[Install]
WantedBy=multi-user.target

Here is my working ntp.conf:

rlimit memlock -1
driftfile /var/lib/ntp/ntp.drift
restrict localhost
restrict default limited noquery
server darwin.kenyonralph.com iburst
pool 2.pool.ntp.org iburst
server 127.127.20.0 mode 16 minpoll 3 iburst
fudge 127.127.20.0 flag1 1 flag2 0 flag3 1 time2 0.545
leapfile /etc/ntp/leap-seconds.list

Example output after letting ntpd run for about 8 hours:

kenyon@einstein ~ % ntpq -ccv -p -crv -ckern -csysinfo
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPGGA,172617,1111.3839,N,11111.4417,W,2,11,0.8,126.3,M,-35.5,M,,*71",
poll=3418, noreply=0, badformat=0, baddata=0, fudgetime2=545.000,
stratum=0, refid=GPS, flags=5
        remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
    2.us.pool.ntp.o .POOL.          16 p    -   64    0    0.000    0.000   0.000
oGPS_NMEA(0)     .GPS.            0 l    -    8  377    0.000    0.000   0.004
+darwin.kenyonra 127.67.113.92    2 u   50   64  377   28.478    4.232   0.953
-2001:470:c:4a1: 131.188.3.220    2 u   45   64  377  200.027   11.259   0.586
-2604:a880:800:1 184.105.182.7    3 u   39   64  377   82.776    4.196   1.805
-ntp.jtsage.com  216.218.254.202  2 u   24   64  377   69.561   -1.286   0.490
-2604:a880:800:1 184.105.182.7    3 u   46   64  377   82.421    3.827   0.603
*yurizoku.tk     209.51.161.238   2 u   59   64  377   80.916    1.554   0.619
+198.110.48.12 ( 204.9.54.119     2 u   35   64  377  100.437    1.796   1.330
-108.61.194.85 ( 201.198.247.252  2 u   53   64  377   45.230   -5.521   1.041
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
version="ntpd 4.2.8p1@1.3265-o Mon Feb  9 09:59:02 UTC 2015 (1)",
processor="x86_64", system="Linux/3.16.7-ckt2", leap=00, stratum=1,
precision=-23, rootdelay=0.000, rootdisp=1.015, refid=GPS,
reftime=d884bdb9.bc1f69e3  Tue, Feb 10 2015  9:26:17.734,
clock=d884bdba.e1639551  Tue, Feb 10 2015  9:26:18.880, peer=27173, tc=3,
mintc=3, offset=-0.000130, frequency=-13.457, sys_jitter=0.004033,
clk_jitter=0.051, clk_wander=0.031, tai=35, leapsec=201507010000,
expire=201512280000
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
pll offset:            0
pll frequency:         -13.4565
maximum error:         0.0015
estimated error:       3.4e-05
kernel status:         pll ppsfreq ppstime ppssignal nano
pll time constant:     3
precision:             1e-06
frequency tolerance:   500
pps frequency:         -13.4874
pps stability:         0.280609
pps jitter:            0.050
calibration interval   256
calibration cycles:    152
jitter exceeded:       45
stability exceeded:    2
calibration errors:    0
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
system peer:        GPS_NMEA(0)
system peer mode:   client
leap indicator:     00
stratum:            1
log2 precision:     -23
root delay:         0.000
root dispersion:    1.015
reference ID:       GPS
reference time:     d884bdb9.bc1f69e3  Tue, Feb 10 2015  9:26:17.734
system jitter:      0.004033
clock jitter:       0.051
clock wander:       0.031
broadcast delay:    0.000
symm. auth. delay:  0.000

I also tried setting up a time server with FreeBSD to see if it’s any easier or better.

FreeBSD setup

This section was written in October 2011. I no longer run this FreeBSD system. I’m running the NTP server on the Linux machine described above.

I am using ntp-devel from ports.

/etc/rc.conf

ntpd_enable="YES"
ntpd_flags="-N -p /var/run/ntpd.pid -f /var/db/ntpd.drift"
ntpd_program="/usr/local/sbin/ntpd"
ntpd_sync_on_start="YES"

/etc/devfs.conf

link cuau0 gps0

/etc/ttys

Commented out ttyu*.

Kernel configuration

Put this in /usr/src/sys/amd64/conf/PPS-GENERIC:

#
# PPS -- Generic kernel configuration file for FreeBSD/amd64 PPS
#
include GENERIC
ident PPS-GENERIC
options PPS_SYNC

/etc/make.conf

KERNCONF= PPS-GENERIC GENERIC

/etc/ntp.conf

server 127.127.20.0 minpoll 3
fudge 127.127.20.0 flag1 1 flag2 0 flag3 1 time2 0.600
server darwin.kenyonralph.com iburst
server voodoo.kenyonralph.com iburst
server grunt.kenyonralph.com iburst
pool 2.us.pool.ntp.org iburst

Example output

Example output after running for a few minutes and while doing buildworld and buildkernel:

kenyon@gauss ~ % ntpq -p -c clockvar -c readvar; ntpdc -c kerninfo
        remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
oGPS_NMEA(0)     .GPS.            0 l   38   64  377    0.000    0.648   0.249
    2.us.pool.ntp.o .POOL.          16 p    -   64    0    0.000    0.000   0.002
*darwin.kenyonra 127.67.113.92    2 u   63   64  377   20.431    3.263   3.354
-voodoo.kenyonra 106.61.18.129    3 u   61   64  377    0.243    4.485   0.124
+grunt.kenyonral 106.61.18.129    3 u   64   64  377    0.182    3.521   0.225
-conquest.kjsl.c 69.36.224.15     2 u   62   64  377   26.374    5.768   2.522
-bindcat.fhsu.ed 128.138.140.44   2 u   63   64  377   75.219    4.115   1.846
-peachesgeldof.k 204.9.54.119     2 u   64   64  377   94.141    3.787   2.844
-ip-173-201-38-8 198.153.152.52   2 u   58   64  377   24.752    6.104   1.801
-druid.storyinme 130.207.244.240  2 u   56   64  377   65.657   -2.773   4.542
+cheezum.mattnor 129.7.1.66       2 u   65   64  377   45.797    2.972   2.286
associd=0 status=0000 no events, clk_unspec,
device="NMEA GPS Clock",
timecode="$GPGGA,085740,1111.1111,N,11111.1111,W,1,09,0.9,103.2,M,-35.3,M,,*77",
poll=14, noreply=0, badformat=0, baddata=0, fudgetime2=600.000,
stratum=0, refid=GPS, flags=5
associd=0 status=04ad leap_none, sync_uhf_radio, 10 events, kern,
version="ntpd 4.2.7p225@1.2483-o Fri Oct 21 04:59:50 UTC 2011 (1)",
processor="amd64", system="FreeBSD/9.0-RC1", leap=00, stratum=1,
precision=-19, rootdelay=0.000, rootdisp=2.380, refid=GPS,
reftime=d24d03df.edabdc26  Sat, Oct 22 2011  1:57:03.928,
clock=d24d0405.3f696dad  Sat, Oct 22 2011  1:57:41.247, peer=38673, tc=6,
mintc=3, offset=0.648, frequency=-4.048, sys_jitter=0.249,
clk_jitter=0.000, clk_wander=0.005
pll offset:           0.000624065 s
pll frequency:        -4.048 ppm
maximum error:        2.0824e-05 s
estimated error:      1.7e-08 s
status:               2007  pll ppsfreq ppstime nano
pll time constant:    6
precision:            1e-09 s
frequency tolerance:  496 ppm
kenyon@gauss ~ % ntpq -c "rv 38673"
associd=38673 status=973a conf, reach, sel_pps.peer, 3 events, sys_peer,
srcadr=GPS_NMEA(0), srcport=123, dstadr=127.0.0.1, dstport=123, leap=00,
stratum=0, precision=-20, rootdelay=0.000, rootdisp=0.000, refid=GPS,
reftime=d24d03de.ffd6d0b6  Sat, Oct 22 2011  1:57:02.999,
rec=d24d03df.edabdc26  Sat, Oct 22 2011  1:57:03.928, reach=377,
unreach=0, hmode=3, pmode=4, hpoll=6, ppoll=6, headway=0, flash=00 ok,
keyid=0, offset=0.648, delay=0.000, dispersion=0.928, jitter=0.249,
filtdelay=     0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00,
filtoffset=    0.65    0.70    0.76    0.80    0.86    0.91    0.99    1.06,
filtdisp=      0.00    0.96    1.92    2.88    3.84    4.80    5.76    6.72

Here is what kerninfo looks like with the PPS_SYNC kernel option:

pll offset:           0.000123674 s
pll frequency:        -3.918 ppm
maximum error:        0.000111415 s
estimated error:      1.51e-07 s
status:               2107  pll ppsfreq ppstime ppssignal nano
pll time constant:    6
precision:            1e-09 s
frequency tolerance:  496 ppm
pps frequency:        -3.918 ppm
pps stability:        0.033 ppm
pps jitter:           4.729e-06 s
calibration interval: 64 s
calibration cycles:   27
jitter exceeded:      5
stability exceeded:   0
calibration errors:   10

Conclusion

FreeBSD is much nicer than Linux (as of late 2011) at being a stratum 1 NTP server using a NMEA GPS with PPS reference clock.

As of early 2015, I would say it’s about an equal amount of effort between FreeBSD and Debian Linux. Debian Linux is a little more effort if you want to create a proper Debian package of NTP.

Notes

References

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. Revision History.