Using the Serial Bridge with USB/Serial Meshtastic Devices
The Meshtastic Serial Bridge is a lightweight gateway that enables MeshMonitor to communicate with USB and Serial-connected Meshtastic devices by translating between Serial and TCP protocols.
What is the Serial Bridge?
The Serial Bridge is a Docker-based application that:
- Connects to Meshtastic devices via USB or Serial ports
- Exposes a TCP interface on port 4403 compatible with MeshMonitor
- Translates between Serial protocols and TCP's framed protocol
- Runs as a standalone Docker container alongside MeshMonitor
- Provides automatic reconnection and network discovery via mDNS
- Uses the battle-tested
socatutility for reliable serial bridging
When to Use the Serial Bridge
Use the Serial Bridge when:
- ✅ Your Meshtastic device is connected via USB or Serial port
- ✅ You want to monitor a directly connected Meshtastic device
- ✅ Your device doesn't have WiFi/Ethernet capabilities
- ✅ You're running MeshMonitor on a system with USB ports (server, Raspberry Pi, etc.)
Do NOT use the Serial Bridge if:
- ❌ Your device has WiFi/Ethernet - connect directly via TCP instead
- ❌ Your device is Bluetooth-only - use the MeshMonitor BLE Bridge instead
- ❌ You want to test without hardware - use meshtasticd for virtual nodes
Prerequisites
Before setting up the Serial Bridge, ensure you have:
USB or Serial-connected Meshtastic device
- Device connected to your system
- Serial port accessible (usually
/dev/ttyUSB0on Linux)
Docker and Docker Compose
- Docker Engine 20.10+
- Docker Compose v2
Device configured for serial communication
- Serial mode must be enabled on the device
- Proper baud rate configuration (115200)
Quick Start
1. Prepare Your Meshtastic Device
Before using the Serial Bridge, configure your device for serial communication:
# Enable serial mode on the device
meshtastic --set serial.enabled true
meshtastic --set serial.echo false
meshtastic --set serial.mode SIMPLE
meshtastic --set serial.baud BAUD_115200
# Verify settings
meshtastic --get serialImportant: These settings must be configured while the device is connected directly (not through the bridge).
2. Find Your Serial Port
Identify which serial port your device is using:
# List USB serial devices
ls -la /dev/ttyUSB*
# or
ls -la /dev/ttyACM*
# Common ports:
# Linux: /dev/ttyUSB0, /dev/ttyACM0
# macOS: /dev/cu.usbserial-*
# Windows: COM3, COM4, etc. (requires WSL2)3. Create Docker Compose Configuration
Create a docker-compose.yml file with both the Serial Bridge and MeshMonitor:
services:
serial-bridge:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
container_name: meshtastic-serial-bridge
devices:
- /dev/ttyUSB0:/dev/ttyUSB0 # Change to your device
ports:
- "4403:4403"
restart: unless-stopped
environment:
- SERIAL_DEVICE=/dev/ttyUSB0
- BAUD_RATE=115200
- TCP_PORT=4403
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
container_name: meshmonitor
ports:
- "8080:3001"
volumes:
- meshmonitor-data:/data
environment:
- MESHTASTIC_NODE_IP=serial-bridge
restart: unless-stopped
depends_on:
- serial-bridge
volumes:
meshmonitor-data:4. Start the Services
docker compose up -d5. Verify Connection
Check the logs to confirm the Serial Bridge is connected:
# Check Serial Bridge logs
docker compose logs serial-bridge
# Look for:
# "Device /dev/ttyUSB0 is ready"
# "mDNS service registered"
# "socat listening on 0.0.0.0:4403"
# Check MeshMonitor logs
docker compose logs meshmonitor
# Look for:
# "Connected to Meshtastic node at serial-bridge:4403"Test with the Meshtastic CLI:
meshtastic --host localhost --infoConfiguration Details
Environment Variables
The Serial Bridge supports the following configuration options:
| Variable | Default | Description |
|---|---|---|
SERIAL_DEVICE | /dev/ttyUSB0 | Path to the serial device |
BAUD_RATE | 115200 | Serial communication speed (must match device config) |
TCP_PORT | 4403 | TCP port for network connections |
SERVICE_NAME | Meshtastic Serial Bridge | mDNS service name for network discovery |
Custom Configuration Example
services:
serial-bridge:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
devices:
- /dev/ttyACM0:/dev/ttyACM0 # Different serial port
ports:
- "4404:4404" # Custom TCP port
environment:
- SERIAL_DEVICE=/dev/ttyACM0
- BAUD_RATE=115200
- TCP_PORT=4404
- SERVICE_NAME=My Custom BridgeDevice Passthrough
The devices section in docker-compose.yml passes the serial device into the container:
devices:
- /dev/ttyUSB0:/dev/ttyUSB0 # Host device : Container deviceImportant: Both paths must match for the bridge to function correctly.
MeshMonitor Configuration
When using the Serial Bridge, configure MeshMonitor to connect to it:
environment:
- MESHTASTIC_NODE_IP=serial-bridge # Container name
# or
- MESHTASTIC_NODE_IP=localhost # If using host networkDevice Preparation
Required Serial Settings
Your Meshtastic device must have these serial settings configured:
serial.enabled = true
serial.echo = false
serial.mode = SIMPLE
serial.baud = BAUD_115200Why these settings matter:
serial.enabled: Activates serial communicationserial.echo: Must be false to prevent echo interferenceserial.mode: SIMPLE mode provides direct serial communicationserial.baud: 115200 is the standard baud rate
Verifying Device Configuration
# Check all serial settings
meshtastic --get serial
# Should show:
# serial.enabled: True
# serial.echo: False
# serial.mode: SIMPLE
# serial.baud: BAUD_115200Configuring for the First Time
If your device has never been configured for serial:
# Connect device directly via USB
meshtastic --port /dev/ttyUSB0 --set serial.enabled true
meshtastic --port /dev/ttyUSB0 --set serial.echo false
meshtastic --port /dev/ttyUSB0 --set serial.mode SIMPLE
meshtastic --port /dev/ttyUSB0 --set serial.baud BAUD_115200
# Test connection
meshtastic --port /dev/ttyUSB0 --infoTroubleshooting
Device Not Found
Problem: Serial Bridge can't find /dev/ttyUSB0.
Solutions:
Verify device is connected:
bash# List USB serial devices ls -la /dev/ttyUSB* # Check system logs dmesg | grep ttyUpdate device path in docker-compose.yml:
yamldevices: - /dev/ttyACM0:/dev/ttyACM0 # Try different deviceCheck device permissions:
bash# Add user to dialout group sudo usermod -aG dialout $USER # Log out and back in for changes to take effect
Permission Denied
Problem: Bridge can't access the serial device.
Solutions:
Run with proper permissions:
bash# Option 1: Add user to dialout group (recommended) sudo usermod -aG dialout $USER # Option 2: Change device permissions (temporary) sudo chmod 666 /dev/ttyUSB0Verify Docker can access the device:
bashdocker run --rm --device /dev/ttyUSB0 alpine ls -la /dev/ttyUSB0
Port Already in Use
Problem: TCP port 4403 is already occupied.
Solutions:
Check what's using the port:
bashsudo lsof -i :4403 # or sudo netstat -tlnp | grep 4403Stop conflicting services:
bashdocker compose downUse a different port:
yamlenvironment: - TCP_PORT=4404 ports: - "4404:4404"
Device Keeps Rebooting
Problem: Meshtastic device reboots when the bridge connects.
Cause: HUPCL (hang up on close) signal is being sent.
Solution: The bridge automatically disables HUPCL on startup. Check logs:
docker compose logs serial-bridge | grep HUPCL
# Should show:
# "HUPCL disabled successfully"If HUPCL disable fails, try:
# Manually disable HUPCL on host
stty -F /dev/ttyUSB0 -hupcl
# Restart bridge
docker compose restart serial-bridgeBaud Rate Mismatch
Problem: Bridge connects but no data flows.
Solutions:
Verify device baud rate:
bashmeshtastic --get serial.baudMatch bridge configuration:
yamlenvironment: - BAUD_RATE=115200 # Must match device setting
Serial Mode Not Enabled
Problem: Can't communicate with device through bridge.
Solution:
Check serial settings:
bashmeshtastic --get serial.enabledEnable if disabled:
bashmeshtastic --set serial.enabled true meshtastic --set serial.mode SIMPLE
MeshMonitor Can't Connect to Bridge
Problem: Serial Bridge starts but MeshMonitor shows "Connection failed".
Solutions:
Verify TCP server is listening:
bash# From host netstat -tln | grep 4403 # Should show: tcp 0.0.0.0:4403 LISTENTest with meshtastic CLI:
bashmeshtastic --host localhost --infoCheck bridge logs:
bashdocker compose logs serial-bridgeVerify network connectivity between containers:
bashdocker compose exec meshmonitor ping serial-bridge
Advanced Configuration
Using Host Network Mode
For simpler networking, use host network mode:
services:
serial-bridge:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
network_mode: host
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
environment:
- SERIAL_DEVICE=/dev/ttyUSB0
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
network_mode: host
volumes:
- meshmonitor-data:/data
environment:
- MESHTASTIC_NODE_IP=localhostNote: Host networking removes container isolation but simplifies port management.
Running on Raspberry Pi
The Serial Bridge works perfectly on Raspberry Pi:
services:
serial-bridge:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
ports:
- "4403:4403"
restart: unless-stoppedRaspberry Pi tips:
- USB serial devices usually appear as
/dev/ttyUSB0or/dev/ttyACM0 - Add
piuser to dialout group:sudo usermod -aG dialout pi - Use
restart: unless-stoppedfor automatic recovery after power outages
Windows WSL Setup
Community Contribution: These instructions were contributed by @andresee for running MeshMonitor and the Serial Bridge on Windows using WSL (Windows Subsystem for Linux) with USB passthrough.
Running the Serial Bridge on Windows requires WSL2 and the usbipd-win tool to pass USB devices from Windows to WSL.
Prerequisites
Windows Subsystem for Linux (WSL2)
- Install WSL2 if not already installed
- Use a supported Linux distribution (Ubuntu recommended)
usbipd-win
- Download and install from: usbipd-win releases
- Recommended version: v5.3.0 or later
- Official documentation: WSL support guide
Step 1: Find Your USB Device
In Windows PowerShell or Command Prompt (run as Administrator):
# List all USB devices
usbipd listExample output:
BUSID DEVICE STATE
1-7 USB Input Device Not shared
4-4 STMicroelectronics STLink dongle, STMic... Not shared
5-2 Surface Ethernet Adapter Not shared
1-8 239a:8029 USB Serial Device (COM7) Not sharedIdentify your Meshtastic device's BUSID (e.g., 1-8 for the USB Serial Device above).
Step 2: Bind the Device to WSL
Bind the device to make it available for WSL sharing:
# Replace 1-8 with your device's BUSID
usbipd bind --busid 1-8Verify the device is now shared:
usbipd listYou should see the device state changed to "Shared":
BUSID DEVICE STATE
1-8 239a:8029 USB Serial Device (COM7) SharedStep 3: Attach Device to WSL
Attach the shared device to your WSL instance:
# Replace 1-8 with your device's BUSID
usbipd attach --wsl --busid 1-8Verify the device is attached:
usbipd listThe device state should now show "Attached":
BUSID DEVICE STATE
1-8 239a:8029 USB Serial Device (COM7) AttachedStep 4: Verify Device in WSL
Open your WSL terminal and verify the device is available:
# List USB devices
lsusbExample output:
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 009: ID 239a:8029 Adafruit WisCore RAK4631 Board
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hubFind the TTY device path:
# Check kernel messages for TTY assignment
dmesg | grep ttyExample output:
[1211963.942117] cdc_acm 1-1:1.0: ttyACM0: USB ACM deviceVerify the device path exists:
ls /dev/ttyACM*Expected output:
/dev/ttyACM0Step 5: Configure Docker Compose
Create or update your docker-compose.yml with the WSL device path:
services:
serial-bridge:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
container_name: meshtastic-serial-bridge
devices:
- /dev/ttyACM0:/dev/ttyACM0 # WSL serial device → container
ports:
- "4403:4403"
restart: unless-stopped
environment:
- SERIAL_DEVICE=/dev/ttyACM0 # Must match device mapping
- BAUD_RATE=115200
- TCP_PORT=4403
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
container_name: meshmonitor
ports:
- "8080:3001"
volumes:
- meshmonitor-data:/data
environment:
- MESHTASTIC_NODE_IP=serial-bridge
restart: unless-stopped
depends_on:
- serial-bridge
volumes:
meshmonitor-data:Important notes:
- Replace
/dev/ttyACM0with your actual device path from Step 4 - The device path in
devices:andSERIAL_DEVICEenvironment variable must match - Common device paths in WSL:
/dev/ttyACM0,/dev/ttyUSB0
Step 6: Start the Services
In your WSL terminal:
docker compose up -dStep 7: Verify Operation
Check that both services are running correctly:
# Check Serial Bridge logs
docker compose logs serial-bridge
# Check MeshMonitor logs
docker compose logs meshmonitorAccess MeshMonitor at: http://localhost:8080
Windows WSL Troubleshooting
Device not appearing in WSL:
- Ensure usbipd-win is running as Administrator
- Try detaching and reattaching:
usbipd detach --busid 1-8thenusbipd attach --wsl --busid 1-8 - Verify WSL2 is being used:
wsl --list --verbose
Permission denied in WSL:
- Add your WSL user to the dialout group:
sudo usermod -aG dialout $USER - Log out and back into WSL
- Check device permissions:
ls -la /dev/ttyACM0
Device path changes after reboot:
- The device path (
/dev/ttyACM0vs/dev/ttyUSB0) may vary - Update your docker-compose.yml if the path changes
- Consider using udev rules for consistent device naming
USB device resets when attaching:
- This is normal WSL behavior
- Wait a few seconds after attaching before starting Docker services
- Check
dmesgto confirm device enumeration completed
Docker can't access device:
- Verify Docker Desktop is using WSL2 integration
- Ensure WSL integration is enabled for your distribution in Docker Desktop settings
- Restart Docker Desktop if needed
Multiple Serial Devices
To bridge multiple devices, run separate instances:
services:
serial-bridge-1:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
container_name: bridge-device1
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
ports:
- "4403:4403"
environment:
- SERIAL_DEVICE=/dev/ttyUSB0
- SERVICE_NAME=Device 1
serial-bridge-2:
image: ghcr.io/yeraze/meshtastic-serial-bridge:latest
container_name: bridge-device2
devices:
- /dev/ttyUSB1:/dev/ttyUSB1
ports:
- "4404:4404"
environment:
- SERIAL_DEVICE=/dev/ttyUSB1
- TCP_PORT=4404
- SERVICE_NAME=Device 2Network Discovery with mDNS
The Serial Bridge automatically registers itself via Avahi mDNS for network discovery.
Browse available services:
# Install avahi-utils if needed
sudo apt-get install avahi-utils
# Discover Serial Bridges on network
avahi-browse -rt _meshtastic._tcpService information includes:
- Service type:
_meshtastic._tcp - Bridge type and version
- TCP port
- Serial device path
- Baud rate
Performance and Resource Usage
The Serial Bridge is extremely lightweight:
- Memory: ~15-25 MB
- CPU: Minimal (< 1% on idle)
- Network: ~1-5 KB/s (depends on mesh activity)
- Disk: ~47 MB Docker image (Alpine-based)
- Startup time: < 2 seconds
Technical Details
Architecture
The bridge uses socat (SOcket CAT) for serial-to-TCP translation:
meshtastic CLI → TCP:4403 → socat → /dev/ttyUSB0 → Meshtastic DeviceWhy socat?
- Battle-tested serial protocol handler
- Proper low-level serial communication
- Handles wake sequences correctly
- No async I/O blocking issues
- Reliable for long-running connections
Startup Process
When the container starts:
- Display version information
- Verify serial device exists at configured path
- Disable HUPCL to prevent device reboots
- Register mDNS service via Avahi
- Start socat listener on 0.0.0.0:TCP_PORT
- Establish bidirectional serial bridge at configured baud rate
Serial Protocol
The bridge maintains a direct serial connection with these characteristics:
- Baud rate: 115200 (configurable)
- Data bits: 8
- Parity: None
- Stop bits: 1
- Flow control: None (raw mode)
TCP Protocol
The bridge exposes the standard Meshtastic TCP protocol:
- Frame Structure:
[0x94][0xC3][LENGTH_MSB][LENGTH_LSB][PROTOBUF_DATA] - Port: 4403 (default, configurable)
- Format: 4-byte header + protobuf payload
All translation between serial and TCP protocols is handled automatically by socat and the Meshtastic firmware.
Security Considerations
USB device access:
- Container requires direct device passthrough
- Use minimal privileges where possible
- Consider running in isolated Docker networks
Serial port security:
- Restrict access to serial devices on host
- Use dialout group membership instead of root
- Monitor device permissions
Network security:
- The TCP interface is unencrypted
- Use firewall rules to restrict access to port 4403
- Consider running on isolated network segment
- Use Docker networks to control container communication
Next Steps
- Configure notifications for real-time alerts
- Set up a reverse proxy for remote access
- Deploy to production with monitoring
- Serial Bridge GitHub Repository for source code and updates
Alternative Solutions
If the Serial Bridge doesn't meet your needs:
- WiFi/Ethernet devices: Connect directly via TCP (no bridge needed)
- Bluetooth devices: Use the MeshMonitor BLE Bridge instead
- Virtual nodes: Use meshtasticd for testing without hardware
- Network-based deployment: Consider adding WiFi to your Meshtastic device