Advanced Room Server Topics

Running Multiple Rooms

A MeshCore room server is a single node that hosts a single room. There is no multi-room mode: one room server node = one room. To offer several separate spaces across a community (for example, a public room and a private emergency operations room), you deploy multiple room-server nodes — one node per room. This page covers how a single room server works and how to run several of them as a coordinated set.

How a room server works

A MeshCore room server is a store-and-forward node configured entirely over its serial/BLE CLI — there is no configuration file. A single room server has:

A client connects to a room server (supplying the guest password if one is required) to access that server's single room. There is no "choose which room to join" selection, because a server hosts only one room. A client can, however, hold multiple room servers as contacts and interact with each separately.

Exact password defaults, ACL levels, and the unseen-message count should be verified against your firmware version and the current MeshCore CLI reference at docs.meshcore.io/cli_commands (as of 2026-06-08).

Deploying multiple room servers

Because one node hosts one room, separate spaces require separate nodes. A community that wants a public room and a restricted emergency room runs two room-server nodes, each configured independently over its own CLI. Each node is a separate piece of hardware (for example a Heltec V3 or an nRF52840 board) with its own name, passwords, ACL, and history store.

For example, to set up three room servers across a region you would, on each node in turn, connect over serial/BLE and configure it:

# --- Node 1: public regional room ---
set name RegionMesh-Public
password <newAdminPassword>
set guest.password <publicGuestPassword>   # or leave blank for open guest access
set allow.read.only on                     # optional: allow unauthenticated read-only
advert

# --- Node 2: restricted emergency room (separate hardware) ---
set name EmergencyNet
password <newAdminPassword>
set guest.password <emergencyGuestPassword>
setperm <coordinatorPubkey> 2             # grant a coordinator Read-write
advert

# --- Node 3: club room (separate hardware) ---
set name ClubNet
password <newAdminPassword>
set guest.password <clubGuestPassword>
advert

All of these nodes — like every node in the network — must share the same radio preset (frequency, bandwidth, spreading factor, coding rate) as the companions and repeaters around them; otherwise their packets and adverts cannot be received by other nodes. Use the named region preset in the app or web flasher rather than hand-entering values. Give each node a clear, distinct name so users can tell the rooms apart.

Controlling access to each room

Access to a room is governed by the room server's guest password and per-contact ACL, not by a per-room PSK. Anyone who has a room's guest password can join and read that room's messages, so treat it like a shared secret: distribute it through a separate secure channel (encrypted email, in person, Signal, etc.), not over the mesh itself, and rotate it with set guest.password <new> if it may have leaked.

For finer control on a given node, grant individual contacts specific permission levels with setperm <pubkey> <level> (Guest/Read-only/Read-write/Admin) and review the current list with get acl. For a restricted emergency room, the guest password is typically shared only with vetted local emergency-management personnel, ARES/RACES members, and CERT team leads — not published publicly — and trusted operators can be given Read-write or Admin via the ACL.

Monitoring a room server

A MeshCore room server has no HTTP status endpoint and no management script — it is firmware on a microcontroller (nRF52840/ESP32). You monitor it over the serial/BLE CLI using the built-in stats commands:

# System stats: battery, uptime, queue length, debug flags
stats-core

# Radio-layer stats
stats-radio

# Packet-level stats
stats-packets

These commands are issued over the serial console (or the companion app's CLI). To monitor several rooms, connect to each room-server node and query it individually.

Internet Bridging and MQTT

A MeshCore room server runs as firmware on a single LoRa node (typically nRF52840 or ESP32 hardware). It is a store-and-forward node on the RF mesh and does not have a native internet, TCP, or MQTT bridge. There is no MeshCore feature that lets phone users without LoRa hardware join a room over the internet, and there is no MeshCore MQTT integration. If you want MeshCore-related traffic on the internet or in a monitoring stack, you bridge to a separate Linux host, or use Meshtastic's documented MQTT path on a co-located gateway. This page explains what MeshCore actually supports and how to do internet/monitoring integration correctly.

What "bridge" means in MeshCore

MeshCore's only built-in "bridge" is a radio-layer link, compiled into the firmware, used to join two co-located boards so they extend RF coverage. It is configured through the device CLI (over serial/BLE), for example:

This bridge does not relay between LoRa radio and the internet, and it does not let off-mesh clients participate over TCP. MeshCore companion clients (phone, computer) connect to a node locally over BLE, USB, or serial - not over the internet to a remote room server. A person in another city cannot join your local mesh purely through a MeshCore room server; reaching the internet requires a separate gateway host (see below).

Getting mesh data to the internet (the supported paths)

MeshCore room-server firmware does not publish to MQTT. If you need mesh traffic on an MQTT broker, a dashboard, or the wider internet, use one of these real options:

Do not expect MeshCore CLI keys such as a mqtt: config block, a topic_prefix, or meshcore/... topics - they do not exist in MeshCore firmware.

Monitoring stack (InfluxDB / Telegraf / Grafana) runs on a separate host

A time-series monitoring stack is a legitimate way to visualize mesh data, but every component runs on a separate Linux host, never on the nRF52840/ESP32 microcontroller of the room server:

  1. Install InfluxDB (time-series database) on a Linux host.
  2. Feed it from a real data source - for a Meshtastic mesh, Telegraf's MQTT input plugin can consume the Meshtastic MQTT topics and write to InfluxDB. (There is no MeshCore MQTT feed; for MeshCore you would write your own collector that reads the node's serial output on the gateway host.)
  3. Install Grafana on the host and build dashboards (active nodes over time, node battery levels, message rates, coverage from GPS data).

This entire stack lives on the Linux host, not on the MeshCore room-server hardware.

Exposing a Linux gateway host to the internet (TLS)

If - and only if - you are running an actual web/dashboard service on a separate Linux gateway host (for example a Grafana instance or a custom collector's web UI), you can put it behind a reverse proxy with TLS. This nginx example terminates TLS in front of a local service; replace the upstream port with whatever your service actually listens on (e.g. Grafana's default 3000). A MeshCore room server itself exposes no HTTP service, so there is nothing on the node to proxy to.

# Example nginx configuration on a Linux gateway host
# (fronting a real local service, e.g. Grafana on :3000)
server {
 listen 443 ssl;
 server_name mesh.yournetwork.com;

 ssl_certificate /etc/letsencrypt/live/mesh.yournetwork.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/mesh.yournetwork.com/privkey.pem;

 location / {
 proxy_pass http://127.0.0.1:3000; # your service's actual port
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
 }
}

Get free TLS certificates from Let's Encrypt using certbot. TLS protects the connection to that gateway host's service; it has nothing to do with the RF mesh, which is encrypted independently at the LoRa layer.

Security considerations for an internet-facing gateway host

Any Linux host you expose to the internet (broker, dashboard, collector) needs proper hardening:

Alerting on node failure (on the gateway host)

If you are collecting Meshtastic data via MQTT on your Linux host, you can alert when a node stops checking in using a small Python script (this consumes the Meshtastic MQTT topics, not any MeshCore topic):

import paho.mqtt.client as mqtt
import time

nodes = {}
ALERT_TIMEOUT_SECONDS = 3600 # Alert if not heard in 1 hour

def on_message(client, userdata, msg):
 node_id = msg.topic.split('/')[-1]
 nodes[node_id] = time.time()

def check_timeouts():
 now = time.time()
 for node_id, last_seen in nodes.items():
 if now - last_seen > ALERT_TIMEOUT_SECONDS:
 print(f"ALERT: {node_id} has not been heard in over 1 hour!")

# Subscribe to the Meshtastic JSON topic tree on your broker
# (requires mqtt.json_enabled on the gateway; not available on nRF52)
client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883)
client.subscribe("msh/+/2/json/+/+")
client.loop_start()

while True:
 check_timeouts()
 time.sleep(300)

For a MeshCore-only deployment there is no MQTT feed to subscribe to; you would instead read the node's serial output (and its stats-core / stats-radio / stats-packets CLI output) on the gateway host and build alerting from that.