GPS time: keeping the clock right when the network is gone¶
With the internet up, ntpsec keeps the laptop's clock right from network
time servers. At a field site or on a served agency's deployment with no
internet, nothing corrects it, and it drifts. This guide sets the clock to
follow your GPS receiver when the network is not there, shows how to read
what the clock is following, and how to take all of it back out. The
decision record behind it is D-058 in docs/DECISIONS.md.
Status. Built and tested in containers and fakes. The field laptop has run the first part (bench session 13, 2026-10-02: the files and grants installed, the mode read, the GPS source configured with no fix yet); GPS time taking over has not been seen. Where a behaviour below depends on a bench run still owed, it says so.
docs/reference/bench-verification-5430.mdis where the results will be recorded.
1. First: fit a battery-backed hardware clock (RTC)¶
Before any of the rest: a battery-backed hardware clock (RTC) is what carries the time across a power-off when there is neither network nor GPS, and nothing in software replaces it. Most laptops have one. Check:
rtc0 (or any entry) means you have one; the kernel writes the
synchronised time back to it every eleven minutes, so what it holds is the
last good time. An empty directory means you do not, which is the usual
case on a Raspberry Pi. hammunition doctor warns about it. The fix is
hardware: a supported RTC HAT, or on a Raspberry Pi 5 a battery fitted to
its own RTC connector.
On a machine with no RTC, hammunition hardware apply offers
fake-hwclock from the archive. It saves the time at shutdown and hourly
and restores it at boot. It is a stopgap, not a substitute: the time it
restores is wrong by however long the machine was off. It is never offered
where a real clock exists. sudo apt remove fake-hwclock removes it.
2. Why it matters¶
- Weak-signal modes. FT8 and its relatives stop decoding once the clock is off by more than about a second.
- Logs. Every QSO, message and net log carries a time; a wrong clock makes them wrong.
- EMCOMM. The station clock is the one everybody else trusts.
3. Setting it up¶
GPS time works only where the time daemon is ntpsec (Parrot's default).
It needs a GPS receiver the catalog knows (docs/hardware/gps-receiver-class.md)
and gpsd, which the navigation profile installs.
Besides udev rules and the power-control helper, hardware apply changes
these, and prints each one before it runs:
| What | Why | Inspect | Reverse |
|---|---|---|---|
/etc/systemd/system/ntpsec.service.d/hammunition-gps.conf — AmbientCapabilities=CAP_IPC_OWNER |
gpsd writes the time into shared memory only root can read; ntpd runs as the ntpsec user |
systemctl cat ntpsec |
hammunition hardware unapply |
/etc/systemd/system/gpsd.service.d/hammunition-gps.conf — Environment=OPTIONS=-n |
gpsd reads the receiver, and publishes its time, only while some program is connected to it; -n makes it poll the receiver continuously, so ntpd always has time to read. The same file and text as the chrony unit writes. gpsd takes it at the next boot |
systemctl cat gpsd, then after a reboot ps -o args= -C gpsd shows -n |
hammunition hardware unapply, unless the chrony unit still uses it |
capability ipc_owner, added to /etc/apparmor.d/local/usr.sbin.ntpd (the file Debian keeps for local additions), and ntpd's profile reloaded |
AppArmor must allow the same capability | cat /etc/apparmor.d/local/usr.sbin.ntpd |
hammunition hardware unapply removes only that block |
/etc/ntpsec/ntp.d/ created |
ntpd reads *.conf here after ntp.conf |
ls /etc/ntpsec/ntp.d |
left in place, empty |
The first time mode, auto, set through the helper (the files in section 4) and ntpsec restarted |
hammunition time |
hammunition hardware unapply |
|
The GPS receiver's resume step: /usr/local/libexec/hammunition-gps-resume and /etc/systemd/system/hammunition-gps-resume.service, enabled for the four sleep targets |
With -n, gpsd holds the receiver open all the time, so every suspend can leave it holding a tty that has gone quiet (issue #177). After each resume the step gives gpsd a fresh open of the receiver. See After suspend |
systemctl cat hammunition-gps-resume, journalctl -u hammunition-gps-resume |
hammunition hardware unapply |
Read this before you agree: CAP_IPC_OWNER bypasses permission checks on
all System V IPC, not only gpsd's segment, and ntpd is a daemon that talks
to the network. That is the price of letting it read gpsd's time. If you
will not pay it, run hammunition hardware apply --no-gps-time: device
rules, groups and the power-control helper are set up, and ntpsec, its
grants and fake-hwclock are left alone. Without gpsd installed,
hardware apply leaves ntpsec alone by itself, since there is no GPS time to
read, and says so.
A second cost, in every GPS mode: the GPS modes turn off the
tos minclock 4 minsane 3 line so a lone GPS can set the clock. ntpd's
minsane then falls to its default of 1, and one source can set the clock
alone. ntpsec's own manual (ntp.conf(5)) says minsane "should be at least
4 in order to detect and discard a single falseticker". Online, with four
pool servers and the GPS, that protection is weaker than Debian's default;
ntp-only keeps it. Both are printed in the plan before anything runs.
Reboot after hardware apply. gpsd reads its -n setting only when it
starts, and restarting a running gpsd in place left two gpsd processes in
testing. The receiver has to be polled continuously: without -n, gpsd
writes no time into the shared memory ntpd reads while nothing else is
asking it for a position (measured: no samples in 8 s without -n, nine
with it).
On a laptop that sleeps, the resume step comes with the grants. The
resume step is installed with them by the same hardware apply, wherever
gpsd is installed, and it is what keeps -n workable across a suspend:
measured on the field laptop (issue #177), the receiver is not re-enumerated
when the machine resumes, and a gpsd holding it open can stay silent until
something gives it a fresh open. --no-gps-time does not remove the resume
step, which also serves cgps, xgps and the map tether. To leave it out,
use --no-gps-resume. The step checks that data flows after the re-open and, if the receiver stays
silent, power-cycles it once through its USB authorized switch (what park
and wake use; the receiver then starts cold). If that fails too, the unit
fails and its last journal line names hammunition hardware park
gps-receiver and wake.
Bench: that ntpd keeps this capability after it drops to the ntpsec
user, so it can actually read the receiver, is the first thing to be
checked on the field laptop.
4. The four modes¶
| Mode | GPS awake: the clock follows | GPS parked |
|---|---|---|
auto (default) |
the network and the GPS together; the network is marked preferred | the network only |
prefer-gps |
the GPS first; the network is a check and the fallback | the network only |
ntp-only |
the network only; the GPS is never used | the network only |
gps-only |
the GPS only; network time servers are never used | nothing (holdover, below), and doctor warns |
Bench session 13 measured one half: with the receiver awake but without a
fix, auto followed the network (offset +1.4 ms) and ntpq -pn showed the
GPS source configured with reach 0. Whether auto follows the network once
the GPS has a fix is not yet measured: ntpsec treats prefer as a tie-breaker, and a GPS can win over
network servers. Until the bench says otherwise, read auto as "ntpsec
chooses between the network and the GPS".
A parked receiver (hammunition hardware park gps-receiver) never feeds
the clock whatever the mode says; waking it brings GPS time back. A receiver
kept parked across reboots keeps GPS time off across reboots too. Nothing is
rewritten on a park: ntpd stops hearing the receiver and drops it by its own
rules (inferred from ntpsec's documentation, not yet watched on the bench).
Change the mode with:
It asks for your password once through polkit, like park and wake. The mode
is remembered across reboots. What a mode change writes, all as root through
/usr/local/libexec/hammunition-devctl:
/etc/hammunition/time.yaml: the mode, one line./etc/ntpsec/ntp.d/hammunition-gps.conf: rewritten whole; the GPS linerefclock shm unit 0 refid GPS …, absent inntp-only./etc/ntpsec/ntp.conf, marked lines only. A line Hammunition turns off starts#hammunition-gps:off#; a line it keeps while adding a preferred copy below starts#hammunition-gps:was#. In the GPS modes thetos minclock 4 minsane 3line is turned off (Debian's own comment above it says to, so a lone GPS can set the clock); ingps-onlythepoollines are turned off too. Another mode orhardware unapplyputs them back exactly.- then
systemctl restart ntpsec. If ntpsec will not start on the new files, the old ones are put back and ntpsec is started on them;journalctl -u ntpsec -n 20says why.
If you have edited those marked lines by hand, the mode change and
hardware unapply refuse, name the file and line, and change nothing.
5. Reading what the clock follows¶
hammunition time # the mode, the receiver, what the clock follows
hammunition doctor # includes the time and hardware clock checks
ntpq -pn # ntpd's own view
None of these needs a password. In ntpq -pn, the row starting * is the
source the clock follows; SHM(0) with refid .GPS. is your receiver, and
its reach column counts up from 0 to 377 as ntpd hears it. Always use
-n: without it ntpq looks up every address in DNS, and with the network
down that hangs.
To measure whether the GPS takes over when the network is gone, run
hammunition time measure --minutes 10 with the network off (add --pps to
test /dev/pps0). It samples ntpq -pn every 30 s, prints the GPS and best
network peer's reach and offset, and says whether and when the GPS became the
system peer. It is read-only; with the network on, ntpd rejects the GPS by
design, so that is not the run that measures takeover. Not yet measured on the
field laptop (issue #310).
The hammunition-tray applet shows the same in its Time section and lets
you pick the mode, from its 0.4.0 (corrected 2026-10-01; the section shipped
one release later than first written here).
6. Holdover: when nothing sets the clock¶
With no network and no GPS (or gps-only with the receiver parked), the
clock keeps running on the hardware clock and on ntpsec's record of this
machine's own rate error (/var/lib/ntpsec/ntp.drift). hammunition time
says "Holdover since HH:MM UTC" and how long; doctor says it as
information for the first day and warns after that. When a source comes
back, ntpd corrects the clock. How far the laptop drifts in an hour of
holdover is not yet measured.
7. Accuracy¶
The receiver sends its time over USB as NMEA sentences, with no PPS line. That is good to tens of milliseconds: plenty for FT8 and logging, not for lab timing.
8. Security¶
With the network down and a GPS mode set, the clock follows one source. A
spoofed or faulty GPS could move it. Online, ntpsec weighs the GPS against
the network servers and outvotes a bad one. ntp-only never trusts the GPS;
gps-only never trusts the network. hammunition doctor always shows which
source the clock is following.
9. Undoing it¶
hammunition hardware unapply --dry-run
hammunition hardware unapply
dpkg --verify ntpsec # expected: no line for /etc/ntpsec/ntp.conf (not yet measured on the bench)
unapply puts ntp.conf's marked lines back exactly as they were before
Hammunition edited them (so, if you never edited it yourself, as the package
shipped it, which dpkg --verify ntpsec should confirm; not yet measured on
the bench), removes /etc/ntpsec/ntp.d/hammunition-gps.conf,
/etc/hammunition/time.yaml and the ntpsec drop-in (each only if it
carries the header Hammunition writes), removes gpsd's -n drop-in only if
it holds exactly Hammunition's text and the chrony unit's
/etc/chrony/conf.d/hammunition-gps.conf is absent (the two share it), takes only Hammunition's block out
of /etc/apparmor.d/local/usr.sbin.ntpd, reloads systemd and AppArmor, and
restarts ntpsec on the package's own configuration. It also disables and
removes the GPS resume step's unit and script, each only if it carries
Hammunition's header. hardware apply puts GPS time back.
10. Other targets¶
Debian 13, Ubuntu 24.04, Mint and some Kali installs use
systemd-timesyncd by default, which cannot read a GPS (Ubuntu 26.04 ships
chrony; Parrot's security edition ships ntpsec, the case this guide is for). There, hammunition time and doctor say so and time mode
refuses by name. Hammunition does not switch your time daemon for you; the
route for those targets is the chrony unit, which you choose and install
yourself (Time and position, D-072).