A LoRa mesh reaches across a valley but not out of it. A satellite modem reaches orbit but not the next street. A phone can still push an SMS when the carrier happens to be up. Each one is an island. MeshSat is the layer between them: a Go service on a Raspberry Pi that takes a message from whatever network can carry it locally and hands it to whatever network can carry it onward. Mesh to satellite, satellite to SMS, one island to the next, and out of the affected area to someone who can act on it.
This page was first written in March 2026 for version 0.2, when MeshSat was a Meshtastic-to-Iridium SBD bridge. It has grown since, so here is the current state.
### What changed since March
- The RockBLOCK 9704 (Iridium Messaging Transport, JSPR protocol) is now a first-class modem next to the 9603 SBD, and it is the satellite leg that has been verified in both directions over a real Iridium link.
- Cellular SMS (LilyGO T-Call A7670E), APRS/AX.25 through a bundled Direwolf, ZigBee (CC2652P) and Bluetooth LE joined the transport list. In total that is eight transport bearers across nine wired Reticulum interfaces.
- A Reticulum routing layer sits underneath every bearer. MeshSat interoperates with the upstream Python Reticulum stack (RNS 1.1.4), so an RNode or any other Reticulum node can peer with it over TCP.
- The Meshtastic side now uses the official buf.build protobuf bindings instead of the hand-rolled codec.
- The project moved to its own organisation: https://github.com/meshsat/meshsat. The old cubeos-app link redirects.
### How routing works
Every bearer is a Reticulum interface with a cost. Free interfaces (LoRa, TCP, BLE, ZigBee, MQTT) are preferred, metered ones (satellite, SMS) are used only when no free path exists, and a failover resolver picks the best online interface in a group by priority. Access rules decide what may cross from one interface to another, so position beacons and telemetry never burn satellite credits while a text from a named node does get through. Every outbound message goes through a delivery ledger with status, retries and a dead-letter queue with modem-aware backoff.
The satellite pass predictor from the first version is still there: SGP4 propagation on CelesTrak TLE data drives a four-state scheduler (idle, pre-wake, active, post-pass) so the modem is only asked to transmit when a pass is predicted, which matters in valleys and urban canyons where blind retries just drain the battery. On the 9603, Iridium's own geolocation estimate (AT-MSGEO) is available as a coarse position fallback; the 9704 has no equivalent, so a USB GPS is the primary source on both kits.
New since spring: a spectrum monitor that drives an RTL-SDR v4 through rtl_power, calibrates a noise baseline per band (LoRa 868, APRS 144.8, GPS L1, LTE 800/900) and marks an interface as jammed when occupancy, spectral flatness and dwell time all say so, at which point the router fails over automatically. It has only ever been tested against ambient noise, never against a real jammer.
### The field kit
Two kits exist, built in Leiden for a field programme. Each is a Raspberry Pi 5 (8 GB) in an IP67 case with a Geekworm X1202 UPS (four 18650 cells), a LilyGO T-Call A7670E for LTE/SMS, an ESP32-S3 LoRa node for the Meshtastic side, a RockBLOCK 9603 or 9704 on a Taoglas Iridium antenna, a Quansheng UV-K5 with an AIOC adapter for APRS, an RTL-SDR v4, a CC2652P ZigBee coordinator, a u-blox USB GPS, a DCF77 receiver and a 3.7 inch e-paper display. Five SMA bulkheads bring the antennas outside the case.
Hardware notes that cost real time, for anyone building something similar:
- On the Pi 5, put the 9704 on UART2 (GPIO 4/5, dtoverlay uart2-pi5, 230400 baud), not UART0. The 9704's TX line is undefined during power-on, and with the kernel console on UART0 that garbage caused boot panics.
- The Pi 5 bootloader caps USB peripheral current at 600 mA unless PSU_MAX_CURRENT=5000 is set in the EEPROM. A kit like this draws about 1.5 A on USB, and without the setting the LTE modem browns out on its first transmit burst.
- Use the GPIO character device (libgpiod), not sysfs. Sysfs GPIO is unusable from a container with a read-only /sys, and the Pi 5's gpiochip numbering starts at 512 anyway.
- The A7670E needs about 30 seconds after SIM unlock before its AT interface answers. It is not hung, it is initialising.
### What is proven, and what is not
- Meshtastic serial, full protocol: working on hardware, both kits.
- Iridium 9704 IMT, mobile-originated and mobile-terminated: verified over a real satellite link, March 2026.
- Iridium 9603 SBD, cellular SMS both directions, APRS via Direwolf: working on hardware.
- Reticulum interoperability: passes against upstream Python RNS 1.1.4.
- HeMB, a bonding layer that spreads one message across several bearers with network coding: three-bearer field test over LoRa, TCP and SMS with zero failures. Not yet validated over a paid satellite bearer.
- RTL-SDR jamming detection: implemented, tested against ambient noise only.
- Deployment to a real end user: never. Use in an actual emergency: never.
The test suite is 1,333 test functions and it gates every deploy. That says the code does what the tests describe, not that the system has been proven in the field. It is a prototype and it says so on every page.
### Stack and running it
Go 1.24 backend without CGO, Vue 3 dashboard embedded in the binary, SQLite, server-sent events for live updates, Prometheus metrics. One multi-arch Docker image (arm64 and amd64) on ghcr.io/meshsat/meshsat. Plug in whatever radios you have, start the container, open port 6050. USB devices are identified by VID:PID and a protocol probe, so there is no port configuration. A single Meshtastic radio is enough to start; missing hardware just leaves that interface offline.
### Costs
The software is free. Iridium SBD line rental is around EUR 15 a month plus per-message credits, roughly EUR 0.30 for a 340-byte message, no annual contract. The 9704's IMT plan is priced separately by the airtime provider. Cellular SMS costs whatever your prepaid SIM charges. Everything else is free air.
### Links
- Code: https://github.com/meshsat/meshsat (GPLv3)
- Site and install one-liner: https://meshsat.net
- Documentation: https://docs.meshsat.net
- Two-minute introduction: https://youtu.be/Q-JKNwWlzpE
- Chat: #meshsat on matrix.nuclearlighters.net
Built by Elli and Kyriakos in Leiden, the Netherlands. From November 2026 the two kits go to people in the field for six months, with support from SIDN Fonds, which is where the "never deployed" line above finally gets tested.
Discussion (0 comments)