As MeshOregon began its initial rollout, one of the first goals we had after getting initial infrastructure connections was adding services to the mesh – such as BBSs, MeshLink, and others. However, most of these services require a connection with a dedicated node over USB/TCP, which cannot be shared with any other software. Further this connection also blocks a client app from properly connecting with the node, meaning “remotely driving” the node to change settings / etc requires first disconnecting the service app, which is tying up the client connection.
Luckily, with the advent of Mesh over UDP, and thanks to Linux Native meshtastic with attached radio hats plus “sim mode”, it turns out there’s a better way. And it’s pretty easy to implement!
While neither I nor any others in the group make any claims as to the “discovery” of this “feature”, it does seem that we were one of the first to start using it in this way with this intent.
One note of an important limitation first: While the vNodes and “real” node can have different channel settings, they cannot have different modem settings. So you can’t use a vNode to transmit on LongFast when your “real” node (with control of the radio) is set to different modem settings.
Implementing Virtualized Nodes (vNodes)
Meshtasticd runs on linux systems as a service. Typically, when you start the service, you would want and expect the service to connect to physical radio hardware to join the mesh. For our root (host/physical/”real”) meshtasticd instance, this is correct and desired. We set up the first linux node as you would any other. The only important thing to be sure of is that you enable UDP in the network settings of the node from your Meshtastic client app.
Next, we create the files and directories for a virtual node. This is the way I have arbitrarily chosen to organize mine, but feel free to do something different.
mkdir -p /etc/meshtasticd/vnodes/v1/vfs
cp /etc/meshtasticd/config.yaml /etc/meshtasticd/vnodes/v1/config.yaml
chown -R meshtasticd:meshtasticd /etc/meshtasticd/vnodes
Next, edit the config file for your vnode (in this example, /etc/meshtasticd/vnodes/v1/config.yaml
Comment out the line that says module: auto
Uncomment the line saying module: sim
If using the web server, change the port to a unique value.
Comment out the lines for ConfigDirectory and AvailableDirectory
Change the MAC address to something unique. I usually increment one at a time from the MAC address used by the physical /”real” node.
Next, create a service file. Here’s what I’d put for this example at /etc/systemd/system/meshtasticd-v1.service
Note that the value specified under -p in the ExecStart line is the TCP port you will connect to the vNode on manage/use it. Make sure you increment this for each vNode. The default is 4403 for the real/physical node unless otherwise defined.
[Unit]
Description=Meshtastic Native Daemon
Requires=meshtasticd.service
After=network-online.target meshtasticd.service
StartLimitInterval=200
StartLimitBurst=5
[Service]
ExecStartPre=/bin/sleep 5
AmbientCapabilities=CAP_NET_BIND_SERVICE
User=meshtasticd
Group=meshtasticd
Type=simple
WorkingDirectory=/etc/meshtasticd/vnodes/v1
ExecStart=/usr/bin/meshtasticd -d /etc/meshtasticd/vnodes/v1/vfs -p 4404 -c /etc/meshtasticd/vnodes/v1/config.yaml
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
Load your new service in and start it
systemctl daemon-reload
systemctl enable --now meshtasticd-v1
journalctl -u meshtasticd-v1 -f
You should see the log output of the node starting up. You can now connect your client app via TCP to the node on the node’s IP at the chosen port.
Once logged into the node, configure the settings just as you would for a physical/real node. Just be sure to enable UDP in the network tab just like you did for the real node. Also, it’s worth noting that some software (like MeshLink) behaves better on vNodes if you set the CLIENT_MUTE role. Setting the vNode’s role will not impact the real node’s behavior.
Once you’re done, you should start to see nodes populate in the list, and you can test everything out by sending out messages and seeing if they connect. It should function pretty much identically to a real node.
Now, all you have to do is disconnect your client app from the vNode, set up your software of choice to connect to the vNode’s TCP port, and everything should work! Your “real” node will also be left available for your client app to continue to connect to.
If you have any questions, feel free to reach out in the PDXMesh discord!
Some services we have run successfully on vNodes:
- MeshingAround BBS
- MeshLinkBeta
- “Point-to-point” (private broker) MQTT bridges
- Simple non-service nodes (for example, publicizing something in the node name, or an additional endpoint for an additional client to connect)
- Development binaries (our Store & Forward ++ test nodes are all vNodes, allowing us to test those dev binaries without running early code on the main “real” node)