Appearance
Getting started
Prerequisites
On the Brain:
- An MQTT broker on
127.0.0.1:1883. The daemon connects there by default and retries every 5 seconds until it succeeds; it does not exit when the broker is missing. muxen-nmea2000, or anything else publishingnmea/navigationandnmea/datetimein the MUXEN JSON envelope. Without a position onnmea/navigation,muxen-sextantstarts, connects, subscribes — and publishes nothing at all. That is the normal state before the first GPS fix.- A correct system clock. Every report is computed from the Brain's own clock, not from the time in
nmea/datetime. See Position and time.
Nothing else. There is no CAN interface, no configuration file, and no network access requirement.
Install
sh
sudo apt install muxen-sextantTwo packages are involved, and apt pulls both:
| Package | Architecture | Contents |
|---|---|---|
muxen-sextant | any | the daemon, the systemd unit, the nginx snippet |
muxen-sextant-database | all | WMM.COF and tides.db in /var/lib/muxen-sextant/ |
muxen-sextant declares Depends: muxen-systemd, muxen-sextant-database, so the data package is never optional. It is split out because it is architecture-independent and large — the tide database alone carries 8117 stations and roughly 205 000 harmonic constants.
The package activates the muxen-restart-target dpkg trigger, so installing or upgrading it restarts the MUXEN target rather than requiring anything by hand.
Start and verify
The unit is muxen-sextant.service, PartOf=muxen.target, and its [Install] section is WantedBy=muxen.target.
sh
systemctl status muxen-sextant
journalctl -u muxen-sextant -n 50A healthy startup log looks like this — the daemon is deliberately terse, and these five or six lines are everything it says before it begins publishing:
Config: muxen-sextant 2.2.0 features: MQTT Astro Magnetic Tides Skymap
Config: MQTT 127.0.0.1:1883 prefix=sextant nmea-prefix=nmea
Astro: Report started
Magnetic: Report started (WMM: /var/lib/muxen-sextant/WMM.COF)
Tides: Report started (db=/var/lib/muxen-sextant/tides.db, radius=50 NM, recompute=30 min)
Skymap: Loaded 1663 stars, 695 lines, 88 constellations (built-in catalog)
Skymap: Report started
Main: Starting main loop
Subscribed to nmea/navigation and nmea/datetimeThe features: line is the quickest check that the service is doing what you expect. The unit runs /usr/bin/muxen-sextant --report-all, so all four report modules should be listed. A features: (none) line means the reports were disabled — somebody has overridden the command line.
The Subscribed to … line is printed from the MQTT connect callback, so its presence also proves the broker connection came up.
The first payloads
Nothing is published until a position arrives. Confirm the input first:
sh
mosquitto_sub -h 127.0.0.1 -t nmea/navigation -C 1
mosquitto_sub -h 127.0.0.1 -t nmea/datetime -C 1Then watch the outputs. All five topics are retained, so a subscriber gets the last payload immediately even between recomputes:
sh
mosquitto_sub -h 127.0.0.1 -t 'sextant/#' -vWithin a second or so of the first fix you should see five messages — sextant/sun, sextant/moon, sextant/magnetic, sextant/tides and sextant/skymap. After that the topics go quiet for fifteen minutes, which is correct: see When it recomputes in muxen-sextant — Overview.
A minimal sanity check on the sun report:
sh
mosquitto_sub -h 127.0.0.1 -t sextant/sun -C 1 | python3 -m json.tooljson
{
"data": {
"rise": "2026-08-16T04:52:33Z",
"riseTimestamp": 1786935153,
"riseAzimuth": 68.4,
"set": "2026-08-16T19:14:07Z",
"setTimestamp": 1786986847,
"setAzimuth": 291.7,
"altitude": 41.2,
"azimuth": 168.9
},
"metadata": { "rxDate": "2026-08-16T10:31:02Z", "expireAfterSec": 3600 }
}Compare rise and set against any almanac for your position. If they are wrong by a whole number of hours, the Brain's clock is wrong; if they are wrong by minutes at high latitude, that is the expected accuracy of the model.
Configuration
There is no configuration file. Everything is a command-line flag, and the shipped defaults are the intended configuration. The ExecStart line carries no variables, so changing a flag means a systemd drop-in.
sh
sudo systemctl edit muxen-sextantini
[Service]
ExecStart=
ExecStart=/usr/bin/muxen-sextant --report-all --tide-radius-nm 25The empty ExecStart= is required: without it systemd appends a second command rather than replacing the first.
sh
sudo systemctl restart muxen-sextantThe full flag list, with types and defaults, is in Reference.
The settings worth changing
| Flag | Default | When to change it |
|---|---|---|
--tide-radius-nm | 50.0 | A busy coast can put dozens of stations inside 50 NM, and every one carries a 216-point curve. Lower it if the payload is too large for the screens. |
--recompute-interval-min | 15 | Lower it if the live sun/moon altitude on the screen is visibly stale. |
--tide-recompute-min | 30 | Lower it if the tide curve should follow a fast passage more closely. |
--skymap-max-mag | 5.0 | Raise it for more stars, lower it for a cleaner planisphere and a smaller payload. |
Running it by hand
The daemon is an ordinary foreground program and needs no privileges, which makes a one-off run the fastest way to diagnose anything:
sh
sudo systemctl stop muxen-sextant
muxen-sextant --report-all --verbose-all--verbose-all turns on per-module tracing: every recompute trigger with its reason, every publish with a one-line summary of what went out.
Recompute: first GPS fix (48.3833, -4.4950)
Astro: Published sun: alt=41.2 az=168.9
Astro: Published moon: alt=-8.4 phase=0.31 illum=0.68
Magnetic: Published: decl=-1.23 incl=64.50 F=48250.0 nT
Tides: Published 7 stations
Skymap: Published skymap: 412 stars, 51 constellations, 4 planets--data-dir falls back to ./data when /var/lib/muxen-sextant does not exist, so a copy of WMM.COF and tides.db sitting beside the program is found without arguments.
Add --no-mqtt to compute without publishing anything — useful when a live broker is serving screens and you do not want to disturb the retained payloads.
The web client
The package installs /etc/nginx/snippets/muxen-ws-sextant.conf, which publishes a WebSocket endpoint at /ws/sextant and proxies it to http://127.0.0.1:1884/. Nothing in this package listens on 1884: muxen-sextant speaks plain MQTT to port 1883 as a client and opens no socket of its own. Port 1884 is the broker's WebSocket listener, and it is the muxen-boat package that configures it, in /etc/mosquitto/conf.d/mosquitto-boat.conf.
The browser-side counterpart is the @muxen/sextant package in typescript/@muxen-sextant/, whose default endpoint is /ws/sextant.
Where to go next
- What triggers a recompute, and what happens when the fix is lost — Position and time
- The declination's expiry date — Magnetic declination
- Why a tide height can be negative — Tides
- When something does not work — Troubleshooting
