12 KiB
rMesh Gateway Setup Guide
Dual-stack mesh networking: MeshCore for LoRa mesh, Reticulum for Internet backbone.
This guide covers:
- Setting up a MeshCore Companion node as your primary LoRa gateway (Part 1-3)
- Optionally adding an RNode for Reticulum Internet bridging (Part 4-5)
- Radio parameters and network architecture (Part 6-7)
Architecture
[MeshCore Nodes] <--868MHz--> [Companion WiFi] <--TCP:5000--> [rmesh-reticulum] <--TCP:4242--> [Reticulum Internet backbone]
MeshCore handles the LoRa mesh (structured routing, 64 hops, efficient spectrum use). Reticulum bridges separate LoRa islands over the Internet.
Part 0: MeshCore Companion WiFi Setup (Primary Gateway)
This is the recommended primary gateway. A MeshCore Companion node with WiFi firmware creates a TCP server that rMesh connects to directly.
Flash MeshCore Companion WiFi firmware
- Open https://meshcore.io/flasher in Chrome.
- Connect a Heltec V3 or T-Beam via USB.
- Select your device, then Companion firmware.
- Enable WiFi in the configuration (set your SSID + password).
- Flash. The device creates a TCP server on port 5000.
Find the device IP
After flashing, the device connects to your WiFi. Find its IP via your router's DHCP client list, or use:
# If mDNS is available
ping meshcore.local
Enable in rMesh
Edit /opt/apps/rmesh-reticulum/.env:
MESHCORE_ENABLED=true
MESHCORE_HOST=192.168.1.xxx # Your companion's IP
MESHCORE_PORT=5000
Restart:
cd /opt/apps/rmesh-reticulum
docker compose up -d
Check logs:
docker logs rmesh-reticulum --tail 20
You should see: MeshCore bridge ready — device: YourNodeName
Alternative: USB Serial
If the companion is plugged directly into the server:
MESHCORE_ENABLED=true
MESHCORE_SERIAL=/dev/ttyUSB0
And add to docker-compose.yml:
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
Part 0.5: MeshCore Repeaters and Room Servers
Flash a Repeater (autonomous relay)
- Same web flasher, select Repeater instead of Companion.
- Repeaters are autonomous — no phone or server connection needed.
- They learn routes and relay traffic between companions.
- Deploy on rooftops/high points with the solar kit from the BOM.
Flash a Room Server (BBS)
- Web flasher, select Room Server.
- Room Servers store posts/messages for the community.
- Users connect to Room Servers through the mesh via their Companion.
Part 1: RNode for Reticulum Internet Backbone (Optional)
If you want to bridge separate MeshCore mesh islands over the Internet, add an RNode running Reticulum as a second radio interface.
Note: RNode and MeshCore are different protocols on different radios. They don't interfere — use separate Heltec V3 boards for each.
Overview (RNode section)
[LoRa mesh nodes] <--868 MHz--> [RNode (Heltec V3)] <--USB--> [Server] <--Docker--> [rmesh-reticulum]
The RNode acts as a radio modem. It converts LoRa radio traffic into serial data
that Reticulum can process. Reticulum running inside the rmesh-reticulum container
bridges the radio network with the TCP/IP network.
Part 1: Flash RNode Firmware onto Heltec V3
Prerequisites
On any Linux/macOS machine with USB:
# Install Reticulum (includes rnodeconf tool)
pip install rns --upgrade
# Linux only: add your user to the serial port group
sudo usermod -a -G dialout $USER
# Log out and back in for this to take effect
The Heltec V3 uses a CH9102 USB chip. Modern Linux kernels include the driver
(ch341 module). No extra drivers needed on Linux. On macOS/Windows, install the
CH340/CH9102 driver from the manufacturer.
Flash the firmware
-
Connect the Heltec V3 via USB-C (use a data cable, not charge-only).
-
Run the autoinstaller:
rnodeconf --autoinstall -
When prompted:
- Device type: Heltec LoRa32 v3
- Frequency band: 868/915/923 MHz (the SX1262 variant)
-
The tool downloads and flashes the firmware. Takes about 1-2 minutes.
Alternative: Browser-based flasher
Open https://liamcottle.github.io/rnode-flasher/ in Chrome/Edge. Select Heltec LoRa32 V3, 868 MHz. Click flash. Uses WebSerial API.
Verify the flash
rnodeconf -i /dev/ttyUSB0
You should see: firmware version, device signature, hardware platform, and frequency range. The status LED will flash every ~2 seconds when idle.
Tip: Find the stable device path for later use:
ls -la /dev/serial/by-id/Use this path instead of
/dev/ttyUSB0to avoid port renumbering.
Part 2: Connect RNode to the Server
Option A: Direct USB to server (simplest)
If the Heltec V3 is plugged directly into the Netcup server (or a USB-over-IP
adapter), the device appears as /dev/ttyUSB0 or /dev/ttyACM0 on the host.
Option B: Via Raspberry Pi bridge (remote location)
If the RNode is at a different location from the server:
- Plug RNode into a Raspberry Pi via USB.
- Install Reticulum on the Pi:
pip install rns - Configure the Pi's Reticulum with:
- An
RNodeInterfacefor the radio - A
TCPClientInterfacepointing to your server's IP on port 4242
- An
- The Pi bridges radio traffic to the server over the internet.
Pi config (~/.reticulum/config):
[reticulum]
enable_transport = True
[interfaces]
[[RNode LoRa]]
type = RNodeInterface
enabled = yes
port = /dev/ttyUSB0
frequency = 867200000
bandwidth = 125000
txpower = 7
spreadingfactor = 8
codingrate = 5
[[TCP to Server]]
type = TCPClientInterface
enabled = yes
target_host = YOUR_SERVER_IP
target_port = 4242
Option C: RNode over WiFi/Bluetooth
RNode supports network connections. After flashing, configure the RNode's WiFi:
rnodeconf /dev/ttyUSB0 --wifi-ssid "YourNetwork" --wifi-pass "YourPassword"
Then in Reticulum config, use TCP instead of serial:
[[RNode LoRa]]
type = RNodeInterface
enabled = yes
port = tcp://rnode-ip-address:0
Part 3: Enable RNode in rmesh-reticulum Container
Step 1: Pass the USB device into Docker
Edit /opt/apps/rmesh-reticulum/docker-compose.yml:
services:
rmesh-reticulum:
# ... existing config ...
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
# You may also need:
# privileged: true
# Or more targeted:
# cap_add:
# - SYS_RAWIO
Use the stable path from
/dev/serial/by-id/instead of/dev/ttyUSB0to avoid issues if multiple USB devices are connected.
Step 2: Update the Reticulum config
Edit /opt/apps/rmesh-reticulum/config/reticulum.conf — uncomment and configure
the RNode interface:
[interfaces]
[[Default Interface]]
type = TCPServerInterface
interface_enabled = True
listen_ip = 0.0.0.0
listen_port = 4242
[[RNode LoRa]]
type = RNodeInterface
interface_enabled = True
port = /dev/ttyUSB0
frequency = 867200000
bandwidth = 125000
txpower = 7
spreadingfactor = 8
codingrate = 5
Step 3: Rebuild and restart
cd /opt/apps/rmesh-reticulum
# If this is first time changing the config after initial deploy,
# clear the persisted config so entrypoint.sh copies the new one:
docker compose down
docker volume rm rmesh-reticulum_reticulum_data # WARNING: resets identity
# Or exec into container and update config in-place:
docker exec rmesh-reticulum cp /app/config/reticulum.conf /data/reticulum/config
docker compose up -d
Step 4: Verify
docker logs rmesh-reticulum --tail 20
You should see the RNode interface initializing alongside the TCP interface. Check the bridge API:
curl -H "X-Bridge-API-Key: YOUR_KEY" http://localhost:8000/api/status
The path_count should increase as radio nodes announce themselves.
Part 4: Radio Parameters
Recommended EU settings (868 MHz)
| Parameter | Value | Notes |
|---|---|---|
| frequency | 867200000 | 867.2 MHz (EU general) |
| bandwidth | 125000 | 125 kHz — good range/speed balance |
| txpower | 7 | 7 dBm (~5 mW). Safe for EU with any antenna |
| spreadingfactor | 8 | SF8 — balanced range and throughput |
| codingrate | 5 | 4/5 — lowest overhead, fine for low-noise |
Tuning for range vs speed
| Goal | SF | BW | Bitrate | Range |
|---|---|---|---|---|
| Maximum speed | 7 | 250000 | ~11 kbps | Shorter |
| Balanced | 8 | 125000 | ~3.1 kbps | Medium |
| Maximum range | 12 | 125000 | ~0.29 kbps | Longest |
All nodes on the same network must use identical radio parameters. Different SF/BW/frequency = invisible to each other.
EU duty cycle
The 868 MHz band has a 1% duty cycle limit on most sub-bands (ETSI EN 300.220). Reticulum handles this automatically. With SF8/125kHz, a typical message takes ~100ms on air, allowing ~36 messages per hour within duty cycle.
The sub-band 869.4-869.65 MHz allows 10% duty cycle and 500 mW ERP — useful
for higher-traffic gateways. Set frequency = 869525000 to use it.
Part 5: Flash MeshCore on a Second Device
For a companion device that pairs with your phone:
Web flasher (easiest)
- Open https://meshcore.io/flasher in Chrome.
- Connect a second Heltec V3 via USB.
- Select: Heltec V3 → Companion.
- Click flash. Done in under a minute.
Companion apps
After flashing MeshCore Companion firmware, pair with:
- MeshCore app (by Liam Cottle) — Android/iOS/Web
- Web app: https://app.meshcore.nz
MeshCore Repeater
To flash a dedicated relay node (e.g., the T-Beam for outdoor solar deployment):
- Same web flasher, select Repeater instead of Companion.
- Repeaters are autonomous — no phone pairing needed.
- They learn routes and relay traffic between companions.
Part 6: Network Architecture
Once you have hardware deployed:
Internet
|
[Netcup Server]
rmesh-reticulum
TCP:4242 + API:8000
| |
+--------------+ +----------------+
| |
[RNode Gateway] [Remote Reticulum
Heltec V3 USB nodes via TCP]
868 MHz LoRa
|
+----------+-----------+
| |
[MeshCore Companion] [MeshCore Repeater]
Heltec V3 + Phone T-Beam + Solar
|
[More nodes...]
The RNode gateway bridges LoRa and TCP/IP. MeshCore nodes on the same frequency are heard by the RNode. Reticulum handles the routing and encryption.
Important: MeshCore and Reticulum use different protocols at the LoRa level. An RNode running Reticulum firmware talks to other Reticulum/RNode devices. MeshCore devices talk to other MeshCore devices. To bridge between them, you'd need both firmwares running on separate radios, or use the experimental Reticulum-over-MeshCore bridge (see GitHub discussions).
For a simple start: use RNode firmware on everything, and run Sideband on phones instead of the MeshCore app. This keeps the whole network on one protocol.
Troubleshooting
| Problem | Solution |
|---|---|
Permission denied: /dev/ttyUSB0 |
sudo usermod -a -G dialout $USER then re-login |
| Device not detected | Try a different USB cable (must be data-capable) |
rnodeconf can't find device |
Check ls /dev/tty* — may be ttyACM0 instead of ttyUSB0 |
| RNode flashing fails | Hold BOOT button while plugging in USB, then retry |
| Container can't see device | Add devices: ["/dev/ttyUSB0:/dev/ttyUSB0"] to docker-compose.yml |
| No radio peers discovered | Verify all nodes use same frequency/bandwidth/SF |
| Docker volume has old config | docker exec rmesh-reticulum cp /app/config/reticulum.conf /data/reticulum/config then restart |