Virtual Node Server β
The Virtual Node Server is a powerful feature that allows multiple Meshtastic mobile apps to connect to MeshMonitor simultaneously without overwhelming your physical Meshtastic node.
Two variants
MeshMonitor exposes a virtual node for both mesh protocols it supports:
- Meshtastic Virtual Node Server β the original feature, documented in the sections below (Meshtastic TCP protocol, historical default port
4404). - MeshCore Virtual Node (new in 4.11.0) β connect the MeshCore mobile app to a managed MeshCore device over WiFi (companion protocol, default port
5000). See MeshCore Virtual Node.
Both are configured per source in the Dashboard and follow the same proxy model: MeshMonitor holds the single physical connection and serves every app client from its mirrored state.
Overview β
The Virtual Node Server acts as a TCP proxy between your mobile devices and your physical Meshtastic node. Instead of connecting directly to your physical node (typically on port 4403), mobile apps connect to MeshMonitor's Virtual Node Server (default port 4404). MeshMonitor then manages all communication with the physical node, caching configuration data and serializing messages to prevent overload.
Architecture β
Mobile App 1 β
Mobile App 2 βββ Virtual Node (4404) ββ MeshMonitor ββ Physical Node (4403)
Mobile App 3 βKey Benefits β
- Multiple Simultaneous Connections: Connect several mobile apps without degrading performance
- Reduced Physical Node Load: Message queuing and caching minimize requests to the physical node
- Fast Connection Setup: Cached configuration messages (240+ messages) enable instant mobile app connection
- Complete UI Visibility: All messages sent from mobile apps appear in the MeshMonitor web interface
- Reliable Startup: Virtual node starts correctly even if initial physical node connection fails
- Connection Stability: Optimized message queue timing (10ms delays) ensures stable mobile app connections
How It Works β
Configuration Capture & Replay β
When MeshMonitor first connects to your physical Meshtastic node, it captures approximately 240 configuration messages including:
- Node information (MyNodeInfo)
- Channel configurations
- Node list and neighbor information
- Device settings and capabilities
- Network topology
These messages are cached in memory. When a mobile app connects to the Virtual Node Server, it receives this complete cached configuration instantly, allowing the app to connect and become fully operational in seconds instead of minutes.
Message Queue Management β
Outgoing messages from mobile apps are queued and serialized with 10ms delays between messages. This prevents overwhelming the physical node with rapid-fire requests that could cause connection instability or performance degradation.
Bidirectional Message Forwarding β
The Virtual Node Server forwards the following message types in both directions:
- Text messages (TEXT_MESSAGE_APP)
- Position updates (POSITION_APP)
- Telemetry data (TELEMETRY_APP)
- Traceroute requests and responses (TRACEROUTE_APP)
- Waypoints and other data packets
Security Filtering β
For safety, the Virtual Node Server blocks the following administrative message types from mobile clients:
- ADMIN_APP (device configuration changes)
- NODEINFO_APP (node information updates)
This prevents mobile apps from accidentally or maliciously modifying your physical node's configuration.
Configuration β
Breaking change in 4.0: Virtual Node is now configured per source through the Dashboard UI. The legacy environment variables
ENABLE_VIRTUAL_NODE,VIRTUAL_NODE_PORT, andVIRTUAL_NODE_ALLOW_ADMIN_COMMANDShave been removed. Eachmeshtastic_tcpsource owns its own Virtual Node endpoint, so two sources on different nodes can each expose a VN on different ports.
Enabling Virtual Node on a Source β
- Open the MeshMonitor Dashboard and sign in as an admin.
- On the source card for the
meshtastic_tcpnode you want to expose, open the kebab menu and choose Edit. - In the Virtual Node section, toggle Enable Virtual Node.
- Enter the TCP port mobile apps should connect to (the historical default was
4404). It must not collide with the source's upstream TCP port or another source's VN port. - Optionally enable Allow admin commands β leave off unless you trust every connected client (see Security Filtering).
- Click Save. The endpoint hot-swaps without restarting the upstream TCP connection.
Configuration lives in the sources.config JSON column as:
{
"host": "192.168.1.100",
"port": 4403,
"virtualNode": {
"enabled": true,
"port": 4404,
"allowAdminCommands": false
}
}Docker Compose Example β
services:
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
container_name: meshmonitor
ports:
- "8080:3001" # Web interface
- "4404:4404" # Virtual Node endpoint (enable on the source after first boot)
volumes:
- meshmonitor-data:/data
environment:
- MESHTASTIC_NODE_IP=192.168.1.100 # auto-creates default source on first boot
restart: unless-stopped
volumes:
meshmonitor-data:On first boot MeshMonitor auto-creates a default meshtastic_tcp source from MESHTASTIC_NODE_IP. Virtual Node is off by default β enable it via Dashboard β Edit Source as described above. Expose the VN port in your compose/Helm config so it's reachable when you turn it on.
Kubernetes/Helm Example β
env:
meshtasticNodeIp: "192.168.1.100"
service:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 3001
- name: virtual-node
port: 4404
targetPort: 4404After the pod starts, open the Dashboard and enable Virtual Node on the auto-created source.
Mobile App Setup β
iOS (Official Meshtastic App) β
- Open the Meshtastic iOS app
- From the Connection screen, tap Manual
- Select TCP as the connection type
- Enter your MeshMonitor server details:
- Address: Your MeshMonitor server IP or hostname
- Port:
4404(or the port you configured on the source)
- Tap Connect
The app will connect to MeshMonitor's Virtual Node Server instead of directly to your physical node.
Android (Official Meshtastic App) β
- Open the Meshtastic Android app
- Tap the + button to add a new device
- Select Network (TCP) as the connection method
- Enter your server information:
- Address: Your MeshMonitor server IP
- Port:
4404
- Tap Connect
Use Cases β
Home Network with Multiple Users β
Perfect for families or groups where multiple people want to use the Meshtastic mobile app simultaneously:
Family's phones βββ Virtual Node βββ MeshMonitor βββ Home mesh nodeTesting and Development β
Developers can connect multiple test devices without overwhelming a single physical node:
Test Device 1 β
Test Device 2 ββββ Virtual Node βββ MeshMonitor βββ Test node
Test Device 3 βRemote Access β
Users can connect to your mesh network remotely via the Virtual Node Server (ensure proper security measures are in place):
Remote App βββ Internet βββ VPN/Port Forward βββ Virtual Node βββ MeshMonitor βββ Local nodeMonitoring and Troubleshooting β
Checking Virtual Node Status β
The Virtual Node Server logs its startup and connection events. Check your MeshMonitor logs:
# Docker logs
docker logs meshmonitor | grep -i "virtual"
# Look for messages like:
# "Starting virtual node server on port 4404..."
# "Virtual node server listening on 0.0.0.0:4404"
# "Virtual node: client connected"Connection Problems β
Mobile app can't connect:
Verify the Virtual Node is enabled on the correct source. Hit
/api/virtual-node/status(requires auth) β the response is{ "sources": [ { sourceId, sourceName, enabled, isRunning, clientCount, clients } ] }. Any source withenabled: trueandisRunning: trueis accepting connections. You can also see aVN:<port>badge on the source card in the Dashboard sidebar.Check that the VN port is exposed in your Docker configuration
Ensure firewall rules allow TCP traffic on port 4404:
bash# Linux/iptables sudo iptables -I INPUT -p tcp --dport 4404 -j ACCEPT # macOS # System Preferences > Security & Privacy > Firewall > Firewall Options # Windows # Windows Defender Firewall > Advanced Settings > Inbound Rules > New RuleTest port accessibility:
bash# From mobile device or another machine telnet <meshmonitor-ip> 4404 # Or nc -zv <meshmonitor-ip> 4404
Mobile app connects but doesn't receive data:
- Check that MeshMonitor is connected to the physical node
- Review logs for configuration capture completion:bash
docker logs meshmonitor | grep -i "config.*complete" - Verify the physical node is reachable from MeshMonitor
Messages from mobile app don't appear in web UI:
This was fixed in v2.13.0. Ensure you're running the latest version:
docker pull ghcr.io/yeraze/meshmonitor:latest
docker compose up -dPerformance Tuning β
The Virtual Node Server is optimized for stable connections with:
- 10ms message queue delays (prevents node overload)
- 240 cached configuration messages (ensures fast client connection)
- Automatic reconnection handling
These values are tuned for optimal performance and typically don't require adjustment.
Security Considerations β
Network Exposure β
By default, the Virtual Node Server listens on 0.0.0.0 (all interfaces). Consider these security measures:
1. Firewall Rules
Restrict access to known IPs:
# Allow only local network
sudo iptables -A INPUT -p tcp --dport 4404 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 4404 -j DROP2. VPN Access
Use a VPN (WireGuard, OpenVPN, Tailscale) instead of exposing the port to the internet:
# Expose only to VPN interface
services:
meshmonitor:
ports:
- "8080:3001"
- "10.0.0.1:4404:4404" # Only listen on VPN interface3. Authentication
The Meshtastic protocol itself does not include authentication at the TCP level. Security relies on:
- Network-level access control (firewalls, VPNs)
- Mesh network encryption keys
- Channel-specific PSK (Pre-Shared Keys)
Administrative Command Blocking β
The Virtual Node Server automatically blocks these administrative commands from mobile clients:
- ADMIN_APP: Prevents configuration changes to the physical node
- NODEINFO_APP: Prevents node information updates
Text messages, positions, telemetry, and traceroutes are allowed and work normally.
Advanced Configuration β
Custom Port β
Edit the source in the Dashboard and change the Virtual Node port field. Be sure to publish the new port in your compose/Helm config so it's reachable from outside the container. Ports must be unique across sources β the API rejects collisions with a 409.
Disabling Virtual Node β
Edit the source in the Dashboard and uncheck Enable Virtual Node, then save. The endpoint shuts down without restarting the upstream TCP connection.
Multiple Sources in One MeshMonitor Instance β
MeshMonitor 4.0 supports multiple sources in a single instance β you no longer need to run multiple containers to expose multiple Meshtastic nodes. Add each node as its own source in the Dashboard and enable Virtual Node on each with a unique port:
services:
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
ports:
- "8080:3001"
- "4404:4404" # Source A virtual node
- "4405:4405" # Source B virtual node
volumes:
- meshmonitor-data:/data
volumes:
meshmonitor-data:Then in the Dashboard: add two meshtastic_tcp sources pointing at each physical node and enable Virtual Node on each with the matching port (4404 for A, 4405 for B). Mobile apps connect to the appropriate port to reach the corresponding node.
Technical Details β
Connection Flow β
- Client Connection: Mobile app establishes TCP connection to port 4404
- Config Replay: Virtual Node Server immediately sends cached configuration (MyNodeInfo, channels, nodes)
- Client Ready: Mobile app transitions through "Communicating" phase and becomes fully operational
- Bidirectional Forwarding: Messages flow in both directions with queue management
- Graceful Disconnect: When client disconnects, resources are cleaned up automatically
Message Processing β
Inbound (from physical node):
Physical Node β MeshMonitor β Virtual Node β All Connected ClientsOutbound (from mobile apps):
Mobile App β Virtual Node Queue (10ms delays) β MeshMonitor β Physical NodeProtocol Compatibility β
The Virtual Node Server implements the Meshtastic TCP streaming protocol:
- 4-byte framed packets:
[0x94][0x93][LEN_MSB][LEN_LSB][PROTOBUF] - Binary protobuf payload (FromRadio/ToRadio messages)
- Compatible with official Meshtastic mobile apps (iOS, Android, Python CLI)
Frequently Asked Questions β
Can I use the Virtual Node with meshtasticd? β
Yes! If you're using meshtasticd (virtual Meshtastic node daemon), MeshMonitor's Virtual Node Server works perfectly as a proxy:
Mobile Apps β Virtual Node (4404) β MeshMonitor β meshtasticd (4403)Does the Virtual Node work with HTTP API calls? β
No. The Virtual Node Server uses the Meshtastic TCP protocol (binary protobuf messages), not HTTP. It's designed specifically for Meshtastic mobile apps and TCP clients.
For HTTP access, use MeshMonitor's web interface or explore the /api endpoints in the running application.
What happens if MeshMonitor restarts? β
Mobile apps will disconnect when MeshMonitor restarts. They should automatically attempt to reconnect. When MeshMonitor comes back online, the Virtual Node Server starts, captures configuration from the physical node, and accepts new connections.
Can I disable the Virtual Node and use direct connections? β
Yes. In the Dashboard, edit the source and uncheck Enable Virtual Node, then connect your mobile apps directly to the physical node on port 4403. However, this means:
- Only one mobile connection may be stable
- No configuration caching
- Messages from mobile apps won't appear in MeshMonitor's web UI
Is there a limit to how many mobile apps can connect? β
There's no hard-coded limit, but practical considerations apply:
- Each connection consumes memory (cached config messages)
- More clients = more outgoing messages queued
- Your physical node's processing capacity is the real bottleneck
In practice, 3-5 simultaneous mobile connections work well. Beyond that, you may experience delays as the message queue grows.
MeshCore Virtual Node β
New in 4.11.0.
The MeshCore Virtual Node brings the same proxy model to MeshCore. A MeshCore device that MeshMonitor already manages (a TCP companion, or a USB/serial device) can be exposed as a virtual node that the MeshCore mobile app connects to over your local WiFi β no separate BLE or serial pairing required, and multiple people on the LAN can connect at once while every message and contact stays mirrored in the MeshMonitor web UI.
How it differs from the Meshtastic Virtual Node β
- Protocol: it speaks the MeshCore companion wire protocol (the same framing the MeshCore app uses over BLE/serial), not Meshtastic protobuf-over-TCP.
- Default port:
5000(the Meshtastic VN historically defaulted to4404). The port is configurable and must be unique across all sources. - Synthesised, not replayed: rather than replaying a captured config stream, MeshMonitor answers each app request from its mirrored per-source state β node identity, contacts, channels, and battery are served from MeshMonitor's database and live device state, and outgoing messages are forwarded to the real node.
MeshCore App 1 β
MeshCore App 2 βββ MeshCore Virtual Node (5000) ββ MeshMonitor ββ Physical MeshCore Node
MeshCore App 3 βWhat works β
- Identity & device info β the app connects, shows the node's identity, and reads device/firmware info.
- Contacts β served from the durable per-source contact list (so the app sees the full set even when the live companion read is flaky).
- Channels & battery β channel info (including PSK) and the local node's battery level.
- Messaging β incoming channel and direct messages are pushed to the app; outgoing direct and channel text messages are forwarded to the real node.
Enabling MeshCore Virtual Node on a Source β
- Open the MeshMonitor Dashboard and sign in as an admin.
- On the MeshCore source card, open the kebab menu and choose Edit.
- In the Virtual Node section, toggle Enable Virtual Node.
- Enter the TCP port the MeshCore app should connect to. Leave it blank to use the default
5000. It must not collide with another source's virtual-node port. - Optionally enable Allow admin commands β leave this off unless you trust every connected client (see Safety below).
- Click Save. The endpoint hot-swaps without restarting the upstream connection to the device.
Configuration lives in the source's config.virtualNode JSON:
{
"virtualNode": {
"enabled": true,
"port": 5000,
"allowAdminCommands": false
}
}As with the Meshtastic VN, expose the port in your Docker/Helm config so it's reachable when you enable it:
services:
meshmonitor:
image: ghcr.io/yeraze/meshmonitor:latest
ports:
- "8080:3001" # Web interface
- "5000:5000" # MeshCore Virtual Node endpoint
volumes:
- meshmonitor-data:/data
restart: unless-stopped
volumes:
meshmonitor-data:MeshCore App Setup β
In the MeshCore mobile app, add a new device using the TCP / network connection option and point it at your MeshMonitor server's IP/hostname on the port you configured (default 5000). MeshMonitor must already be connected to the physical MeshCore device.
Safety: admin commands β
By default the MeshCore Virtual Node is read-and-message only: read operations and sending text messages are allowed, but configuration-mutating commands (set radio params, set advert name, import private key, reboot, set channel, set TX power, etc.) are blocked and rejected back to the app. Exporting the device's private key is always blocked, regardless of settings.
Enabling Allow admin commands forwards those configuration commands through to the real node. Only enable it on a trusted LAN where you control every device that can reach the port β any connected app would then be able to reconfigure your node.
Status & Troubleshooting β
- App can't connect: confirm the source is connected to the physical device and the virtual node is enabled, that the port is published in your container config, and that a firewall isn't blocking it. The Dashboard source card shows a virtual-node badge when it's listening.
- Contacts look incomplete: the list is seeded from MeshMonitor's stored per-source contacts on connect, so reconnecting the source (or letting it complete a contact sync) fills it in.
- A config change from the app did nothing: that's expected unless Allow admin commands is enabled β config-mutating commands are blocked by default.
Version History β
- v4.11.0: MeshCore Virtual Node added β connect the MeshCore mobile app to a managed MeshCore device over WiFi (default port 5000)
- v2.13.0: Virtual Node Server officially released with capture/replay and connection stability improvements
- v2.12.x: Virtual Node Server beta testing and refinements
See Also β
- Getting Started Guide - Basic MeshMonitor setup
- Configuration Overview - All configuration options
- Production Deployment - Best practices for production use