== SemPiTernal: A Raspberry Pi Stratum 1 timeserver build == :description: Building and configuring a tiny Stratum 1 timeserver with RasPi :keywords: Raspberry Pi, NTP, NTPsec, time service by Eric S. Raymond version 0.1 == Introduction == This HOWTO gives complete instructions for building a headless Stratum 1 timeserver using a Raspberry Pi, a GPS daughterboard designed for the Pi, and NTPsec <>. Total parts cost should be about $80. Light soldering is required. Why do it? It's cheap, fun, and because your NTP server is running on a dedicated machine you won't have so much jitter due to variable load. A GPS daughterboard (what Pi folks call a HAT after the Pi's interface specification, Hardware Attached on Top) is a better idea than an external GPS because a HAT will also supply a battery-backed-up RTC, which the GPS can use for warm-starting. Also, the HAT uses an internal RS-232 interface that cuts latency and jitter compared to a USB GPS and can easily ship 1PPS from the receiver. Most of this build is actually independent of any one daughterboard's hardware idiosyncracies. The recipe was tested using an Adafruiit GPS HAT <>, but should also cover the Uputronics GPS Expansion Board <> == Parts list and hardware assembly == You will need: * One Raspberry Pi. I used a Raspberry Pi 3: these instructions cover older variants as well. * One Adafruit GPS HAT or Uputronics GPS Expansion Board. * One CR1220 (for Adafruit) or CR2032 (for Uputronics) 3-volt lithium coin cell. The CR1220 is cheapest ordered from Adafruit along with the HAT, but you can buy either at most places that carry hearing-aid batteries. * (Optional) A Raspberry Pi case to protect your hardware from dust and curious felines. The Adafruit HAT is shipped as two parts, a circuit board and a 40-pin header. Your first step will be to solder the header to the bottom of the board, on the opposite side from the GPS module (under what would be the east edge if the Adafruit logo were a map legend). Poke the header pins upwards through the double row of through holes at the east edge of the board and go. This is the last bit of hardware hacking absolutely required. (The device is shipped as parts almost certainly to evade a regulatory requirement for FCC conformance testing to RF emission standards, which is expensive and would have added to the unit cost.) The header on the assembled HAT fits down over the double row of pins on the east edge of the Pi, such that the two boards make a neat stack. == Understanding the GPIO connector == The pins you'll plug the HAT into are the Pi's primary or P1 GPIO (General Purpose I/O) header. There's a second or P5 GPIO connector near it consisting of a 2x3 array of through holes. This build won't use that. The Pi 3 and other recent variants have 40 pins in the P1 header. Older variants, the original Pi A and B, have only 26 pins. The assignments for those pins on later versions are backward-compatible. The GPIO pins are sometimes referenced by physical pin location on the header (1-26 or 1-40), and sometimes as the GPIO line connected to the CPU. This can cause confusion. They are best referred to as P1-[1-40], p5-[1-8] or as GPIO +[2-31]. Some are typically pre-configured for specific functions (serial, i2c, etc.) Two that will be important for this build are the TX and RX serial lines. The pinouts are described at <>. == Case and board modding == (Ignore this if you have an AdaFruit or "official" case. I thought I had one, but it seems to have been made by some third party to smaller dimensions than either the AdaFruit or Pi "official" cases.) As shipped, a daughterboard the size of the Adafruit HAT will *not* fit in the Canakit acrylic case it arrived here in. The HAT is slightly too large for that. As an optional step, you can modify the board and case so the HAT fits in. You'll do this in two steps: First, modify the flanges that are engaged by the five clips on the bottom of the case top. Unaltered, the flanges will physically interfere with the HAT. Ideally, you want to cut a rectangular piece off each flange about an eighth of an inch horizontal dimension and about a quarter-inch vertical dimension. You do _not_ want to shave the flanges all the way back to the case walls if you can avoid it: if you do that, the clips won't have anything to engage and the top will sit slightly loose. (Mine is modded that less-than-ideal way. It's not worth re-doing with a new case.) Your other problem is that an unused portion of the board (consisting of an array of through holes for mounting ICs) collides with the case shield for the Ethernet. To fix this, cut a rectangular piece off the south-east corner with a small coping saw. The piece needs to be two through-holes wide (noth-south) and nine holes high (east-west). That is just enough to clear the shield for the Ethernet jack. == Fully update Rapbian == Fully update the Raspbian on your Pi. The easiest way to do this is: ------------------------------------------------------------------------ apt-get update apt-get upgrade ------------------------------------------------------------------------ If you skip this step on an old enough Pi, 1PPS configuration will mysteriously fail because the required incantations have changed. == Behead the Pi == You first step is to configure the Pi to run headless attached to an Ethernet cable. You'll do all subsequent configuration via ssh, and your other machines will take time corrections via TCP/IP over the Ethernet. Plug in a monitor, mouse, and keyboard. Power up the Pi. Invoke a terminal emulator. Normally the Pi configures itself using DHCP when you connect it to your Ethernet, acquiring a TCP/IP address that may vary depending on what other devices are hooked to your network. For our use case, giving it a static address is more convenient. Here's how to do that: . Just in case, make a backup copy of your /etc/network/interfaces file: ------------------------------------------------------------------------ sudo cp /etc/network/interfaces /etc/network/interfaces.backup ------------------------------------------------------------------------ . Edit that file using your favorite editor: ------------------------------------------------------------------------ sudo $EDITOR /etc/network/interfaces ------------------------------------------------------------------------ . Change the contents to look something like this: ------------------------------------------------------------------------ auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.1.23 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 192.168.1.1 ------------------------------------------------------------------------ Note: This assumes that (a) You're using the usual 192.168.1.x convention for private addresses, (b) your router lives at .1, and (c) you have DNS running on your router. If any of these assumptions are false, you probably knew what you were doing when you set up your network and know how to modify the above. The "23" should change to whatever low quad you want to use to make the Pi's address unique on your network. I like to follow up by adding a line like this to the /etc/hosts files of the other machines on my network, allowing me to refer to it by name: ------------------------------------------------------------------------ 192.168.1.23 timekeeper ------------------------------------------------------------------------ . Reboot the Pi. ------------------------------------------------------------------------ sudo shutdown -r now ------------------------------------------------------------------------ . From some machine on your network, do: ------------------------------------------------------------------------ ping timekeeper ------------------------------------------------------------------------ If you don't get a ping response, troubleshoot (unplugged or loose cables are always the first thing to check for). If you do, you can log out and then disconnect the keyboard/screen/mouse, which you should do to reduce power draw and heating of the board (graphics processing for the GUI is expensive that way). You'll do the remaining steps over ssh. . Remove network-manager, because it's now just dead weight eating your cycles. ------------------------------------------------------------------------ apt-get remove network-manager ------------------------------------------------------------------------ == On Jessie: uninstall systemd == If you are running on Raspbian Jessie, next step is to uninstall systemd. It is a CPU hog (not just on the Pi; similar problems have been reported across many architectures) and a complexity sinkhole. The things that have it as a dependency are things you don't want on a headless NTP server. Additionally, systemd tries to be its own NTP client. This is undesirable for a Stratum 1 server; it might lead to unexpected interactions with your NTP installation. (Our instructions are based on <>) . First, pull in the core of sysvinit, preserving the inittab that systemd generated. Then reboot. ------------------------------------------------------------------------ apt-get install sysvinit-core sysvinit-utils cp /usr/share/sysvinit/inittab /etc/inittab reboot ------------------------------------------------------------------------ . Purge the remnants of systemd and packages that depend on it. ------------------------------------------------------------------------ apt-get remove --purge --auto-remove systemd ------------------------------------------------------------------------ . Prevent apt from installing systemd packages in the future. ------------------------------------------------------------------------ echo -e 'Package: systemd\nPin: release *\nPin-Priority: -1' > /etc/apt/preferences.d/systemd ------------------------------------------------------------------------ . Prevent apt from installing any systemd like packages in the future (note the star before and after systemd) ------------------------------------------------------------------------ echo -e '\n\nPackage: *systemd*\nPin: release *\nPin-Priority: -1' >> /etc/apt/preferences.d/systemd ------------------------------------------------------------------------ == Disable getty on your UART device == Now that you're using a System-V-like init, ensure that any /etc/inittab entries referring to ttyAMA0 or ttyS0 are commented out or removed. You do not want a getty to spawn on these. To check this, you can reboot and do ------------------------------------------------------------------------ ps ax | grep getty ------------------------------------------------------------------------ If neither ttyS0 or ttyAMA0 appears in any of the selected lines, you're in good shape. == Pi 3 only: disable Bluetooth and remap console device == The Pi 3 Raspbian implementors made a design decision on the Raspberry Pi 3 that ties the serial baud rate to the CPU clock rate (by default). This was done because the normal lines that fed the serial port were used for the built-in Bluetooth. This does not affect any other Pi variant. Your headless timeserver is not going to need Bluetooth, so you should disable it and remap the devices. Our instructions come from <>, which explains the problem in more detail. We don't use some of his steps because this build is designed to run headless. . Copy the http://www.briandorey.com/docs/Raspberry-Pi-3-UART-to-gpio-workaround/pi3-miniuart-bt-overlay.zip[boot overlay] to the root directory of your Pi 3, and unzip it. . Edit the /boot/config.txt file to append these lines: ------------------------------------------------------------------------ # Disable Bluetooth so serial-tty speed is no longer tied to CPU speed dtoverlay=pi3-miniuart-bt-overlay force_turbo=1 ------------------------------------------------------------------------ == Release the console pins == . Next, edit the boot command line. You need to be root to do this. This is what I saw on an unmodified Pi 3 running Jessie: ------------------------------------------------------------------------ address@hidden:/home/pi# cat /boot/cmdline.txt dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait ------------------------------------------------------------------------ You may want to save a copy of the original /boot/cmdline.txt before modifying it. To disable the serial console, remove all "console" options. The Adafruit setup document <> page mentions a "kgdboc" option; if present, it should also be removed. You must reboot the Pi for these changes to take effect. == Testing the GPS == Next thing you want to do is verify that the GPS works. Put your micro-server on someplace like a windowsill with a good sky view outside. The MKT3339 on the HAT has very good weak-signal discrimination and is much less fussy about siting than older GPS receivers. On first (cold) boot, the device may take 20-30 minutes to download a satellite ephemeris. After that, time to get a fix should be much faster unless you live in a canyon (including the urban kind) or dense forest. I, living in a suburb with the front of my house half-screened by tall trees, typically get lock about 30 seconds from power up. It will seem longer than it is first time: have patience. (Some material in this section is from <>.) When the red LED on the HAT blinks once per second, you don't have a satellite fix. When it achieves lock it will blink with much lower frequency. To test that you can read data from the device, do this: ------------------------------------------------------------------------ stty -F /dev/ttyS0 raw 9600 cs8 clocal -cstopb cat /dev/ttyS0 ------------------------------------------------------------------------ You should see NMEA0183 sentences issuing in bursts once per second. Now install GPSD. You won't use this for production, as we plan to direct-connect NTPsec to the GPS, but its diagnostic tools (especially gpsmon) are useful for sanity-checking the output of the HAT. ------------------------------------------------------------------------ apt-get install gpsd gpsd-clients python-gps ------------------------------------------------------------------------ Run ------------------------------------------------------------------------ gpsmon /dev/ttyAMA0 ------------------------------------------------------------------------ You should see a curses panel display that shows you both raw GPS data and the results of data reduction on it. Later, this tool will be useful for checking that you can see the 1PPS signal from your device. To avoid potential problems in later testing, disable autostartup of GPSD. ------------------------------------------------------------------------ /etc/init.d gpsd stop update-rc.d gpsd remove ------------------------------------------------------------------------ Eventually, you may want to build your own GPSD test tools from source. The prerequisites not present in a stock Raspbian can be covered with this import: ------------------------------------------------------------------------ apt-get install scons ncurses-dev python-dev bc ------------------------------------------------------------------------ == Optional: Thin out the system processes on your Pi == The Raspbian default is to install a lot of background processes that exist to support a graphical desktop. Running headless with Ethernet as the only channel to the device, you can remove these in order to reduce load variability on the processor. This will decrease your time jitter. It will also cut your power draw and heat dissipation, increasing the Pi's expected lifetime. Most importantly, it will reduce the number of ways for things to go wrong. ------------------------------------------------------------------------ apt-get -y remove --purge xserver-common apt-get -y remove --purge x11-common apt-get -y remove --purge gnome-icon-theme apt-get -y remove --purge gnome-themes-standard apt-get -y remove --purge penguinspuzzle apt-get -y remove --purge desktop-base apt-get -y remove --purge desktop-file-utils apt-get -y remove --purge hicolor-icon-theme apt-get -y remove --purge raspberrypi-artwork apt-get -y remove --purge omxplayer apt-get -y remove --purge bluez apt-get -y remove --purge avahi-daemon apt-get -y remove --purge dhcpcd apt-get -y remove --purge triggerhappy apt-get -y autoremove apt-get -y update rm -rf /home/pi/python_games ------------------------------------------------------------------------ The resulting configuration is pretty minimal, as you can verify by running "ps ax" and noticing that most of the background processes are kernel threads. WiFi is deliberately not removed, in order to give you a fallback TCP/IP access when a cable is inconvenient. == Getting 1PPS from your device == You'll need NTPsec to be able to see the high-precision PPS (pulse-per-second) signal from the GPS. But the serial interface from an Adafruit or Uputronics HAT only supplies TX/RX; the PPS signal is shipped on a different pin of the GPIO connector. The RX/TX signals are always expected on the same two pins of the GPIO, which connect to the Pi's UART. You can see them, labeled, near the north end of the connector. Most other GPIO pins can be interpreted by the Pi in different ways, configured by software. Which pin is used for 1PPS is a variable of the HAT design. Here is a table: [width="25%",frame="topbot",options="header"] |============================================ | Logical pin | Physical pin | HAT | 4 | P1 7 | Adafruit | 18 | P1 12 | Uputronics |============================================ There is a Linux kernel driver called pps-gpio which, given one of these pins, uses the signal from it to support an RFC2783 interface to PPS that NTPsec (and GPSD) can use. To see 1PPS, you need to ensure that this driver is loaded and monitoring the correct logical pin. In all versions, you force the driver to be loaded by editing /etc/modules to contain the line "pps-gpio". The procedure for declaring the GPIO pin varies by Raspbian version. We only give the formula for the current Raspbian here; you can find details about older versions at <>; Edit /boot/config.txt to contain these options, replacing N with the logical pin number for your HAT: ------------------------------------------------------------------------ dtoverlay=pps-gpio,gpiopin=N ------------------------------------------------------------------------ Any previous gpiopin option (such as bcm2708.pps_gpio_pin) sgould be removed. You must reboot your Pi for this change To test this change, use ppstest from the pps-tools package. Note, this will produce a false negative if the GPS has no fix. ------------------------------------------------------------------------ apt-get install pps-tools ppstest /dev/pps0 ------------------------------------------------------------------------ You should see repeated lines somewhat resembling this: ------------------------------------------------------------------------ source 0 - assert 1461161753.267392352, sequence: 246 - clear 0.000000000, sequence: 0 ------------------------------------------------------------------------ As the pps-gpio module is in April 2016 it has a flaw. It catches only one edge of the PPS. You have a 50/50 chance you can't see the right edge, and no good way of knowing you have the right edge. == Building and configuring NTPsec == The stock ntpd shipped with Raspbian is intended to be used as a client instance, not a server. It doesn't do 1PPS, and therefore can't be used for precision timekeeping. Thus, we're going to build a better version from source. That version is NTPsec, which runs lighter and more securely and can do more accurate time stepping. ------------------------------------------------------------------------ apt-get -y remove --purge ntp ------------------------------------------------------------------------ // More to go here. Use <> == References == [bibliography] - [[[ADAFRUIT-HAT]]] https://learn.adafruit.com/adafruit-ultimate-gps-hat-for-raspberry-pi[Adafruit GPS HAT] - [[[UPUTRONICS-HAT]]] https://store.uputronics.com/index.php?route=product/product&path=60_64&product_id=81[Raspberry Pi+ GPS Expansion Board] - [[[NTPSEC]]] https://www.ntpsec.org/[The NTPsec project] - [[[GPIO]]] https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/[GPIO: MODELS A+, B+, RASPBERRY PI 2 B AND RASPBERRY PI 3 B] - [[[REMOVE-SYSTEMD]]] http://without-systemd.org/wiki/index.php/How_to_remove_systemd_from_a_Debian_jessie/sid_installation[How to remove systemd from a Debian jessie/sid installation] - [[[DOREY]]] http://www.briandorey.com/post/Raspberry-Pi-3-UART-Overlay-Workaround[Raspberry Pi 3 UART Overlay Workaround] - [[[ADAFRUIT-SETUP]]] https://learn.adafruit.com/adafruit-ultimate-gps-hat-for-raspberry-pi/pi-setup[Pi GPS Setup] - [[[ADAFRUIT-TEST]]] https://learn.adafruit.com/adafruit-ultimate-gps-hat-for-raspberry-pi/basic-test[Basic Test] - [[[TAYLOR]]] http://www.satsignal.eu/ntp/Raspberry-Pi-quickstart.html[RPi quick start] - [[[NEVILL]]] https://darksky.io/setting-up-a-stratum-1-ntp-server-on-a-raspberry-pi.html[Setting up a Stratum 1 NTP server on a Raspberry Pi] == Other resources == http://ava.upuaut.net/?p=726[Not quite 5 minute guide to making an NTP Server]