CLI tool
Yeraze/meshmonitor avatar
Yeraze/meshmonitor

MeshMonitor: A Docker-First Dashboard for Meshtastic, MeshCore and MQTT Mesh Networks

Web tool for monitoring Mesh Node Deployment over TCP/HTTP

659 stars93 forksTypeScriptBSD-3-Clause

At a glance

What is it?
MeshMonitor is a TypeScript web application that aggregates off-grid mesh nodes into one dashboard. It installs fastest as a container, but its proxy authentication and production defaults need reading before you expose it.
Who is it for?
Adopt MeshMonitor if you already run Meshtastic or MeshCore nodes over IP and want one dashboard with SQLite, PostgreSQL or MySQL behind it. Skip it if your nodes are only reachable over Bluetooth or you need a hosted service with no server to run.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem MeshMonitor solves for off-grid mesh operators

A Meshtastic deployment stops being simple the moment it grows past one node. Messages, telemetry, traceroutes and node positions arrive over a TCP connection to a radio, and the only built-in view is whatever the phone app shows you while you are standing next to it. MeshMonitor puts a persistent server between the radios and the browser. It connects to nodes over TCP or HTTP, stores what arrives in a database, and renders it as a web dashboard with a Catppuccin Mocha dark theme. The README describes it as covering Meshtastic, MeshCore and MQTT from a single dashboard, which matters because those three transports are usually monitored by three different tools. The audience is the operator who leaves a node on a roof or in a shed and wants history, not a live view that disappears when the app closes. It is explicitly an off-grid tool, so it assumes you host it yourself on a machine that can reach the radios.

How MeshMonitor connects to nodes and where the data lands

The data flow starts with a source. On first boot, the environment variable MESHTASTIC_NODE_IP seeds one source, and the README says additional sources are managed from Dashboard, then Sources. That wording matters: the environment variable is a bootstrap, not the configuration model. MeshCore sources work the same way, and the .env.example is explicit that the legacy 3.x MESHCORE_* environment variables were removed in 4.6, so anyone copying an old compose file will find those variables silently ignored. The server is a Node.js process built from TypeScript, with a React front end, and it persists to SQLite, PostgreSQL or MySQL. The repository ships a migrate-db CLI script for schema changes, which tells you the storage layer is treated as something you keep across upgrades rather than rebuild. Connection behaviour is tunable: MESHTASTIC_TCP_PORT defaults to 4403, MESHTASTIC_CONNECT_TIMEOUT_MS defaults to 10000, and reconnects use exponential backoff from MESHTASTIC_RECONNECT_INITIAL_DELAY_MS to MESHTASTIC_RECONNECT_MAX_DELAY_MS. There is also a virtual node server, off by default, that proxies mobile apps through MeshMonitor so they do not each hold a connection to the physical radio.

Installing MeshMonitor with Docker and logging in the first time

The README leads with a 60-second Docker path. Create a compose file that pulls the published image, maps port 8080 on the host to 3001 in the container, and mounts a named volume at /data so the database survives restarts.

yaml
services:
  meshmonitor:
    image: ghcr.io/yeraze/meshmonitor:latest
    ports:
      - "8080:3001"
    volumes:
      - meshmonitor-data:/data
    environment:
      - MESHTASTIC_NODE_IP=192.168.1.100
    restart: unless-stopped

volumes:
  meshmonitor-data:

Replace the IP with the address of your own node, then start it. The README's command is docker compose up -d, and the dashboard is at http://localhost:8080. The default credentials are admin and changeme, and the README tells you to change the password after the first login. Do that before anything else, because the same page is the entry point for every other setting.

If you run Kubernetes, the README documents a Helm repository instead of a checkout. Adding the repo and installing with a small values file is the documented route.

bash
helm repo add meshmonitor https://meshmonitor.org/charts
helm repo update
helm install meshmonitor meshmonitor/meshmonitor -f custom-values.yaml

The values file sets env.meshtasticNodeIp and env.meshtasticUseTls. The repository also keeps a local chart under helm/meshmonitor for installs from a checkout, and the Helm chart README covers ingress, TLS and persistence.

Production defaults that bite: TRUST_PROXY, CORS and the sample .env

The shipped docker-compose.yml is a development configuration, and it says so. It sets NODE_ENV=development, pins ALLOWED_ORIGINS to http://localhost:8080 with a comment that it is required for CORS, and leaves SESSION_SECRET commented out with a note that it is required in production. Copying that file to a server and changing only the node IP produces a working dashboard with development defaults. Two of those defaults are easy to miss. Since v4.13, TRUST_PROXY defaults to false, and the README states that behind any reverse proxy you must set TRUST_PROXY=1 or the appropriate hop count, otherwise client IP resolution, rate limiting and audit logs all record the proxy's address. That is a silent failure: the app runs, the logs fill up, and every entry shows the same IP. The second is that the compose file also publishes port 1883 for an embedded MQTT broker, with a comment telling you to remove it if the host already runs a broker on that port. On a machine with Mosquitto installed, that mapping collides. Neither issue produces an error message that names the cause.

Proxy authentication: useful, and the sharpest edge in the project

MeshMonitor can delegate login to Cloudflare Access, oauth2-proxy, Authelia, Traefik ForwardAuth or a generic header-based proxy. Configuration is a set of PROXY_AUTH_* variables: PROXY_AUTH_ENABLED, PROXY_AUTH_AUTO_PROVISION, PROXY_AUTH_ADMIN_GROUPS, PROXY_AUTH_ADMIN_EMAILS and PROXY_AUTH_NORMAL_USER_GROUPS. Group matching is case-insensitive, and the README documents normalization for three claim shapes: string arrays, single strings, and role objects where the name field is extracted. That last case exists for Auth0 Post-Login Actions. The security requirements are stated plainly: MeshMonitor must not be directly reachable, TRUST_PROXY must be configured, and the proxy must validate authentication before forwarding. The README also carries two warnings worth repeating. Email uniqueness is not enforced in the database schema, so if two users share an address the first match wins. And Cloudflare Access application JWTs contain only a subset of identity, typically email, aud, iss and sub, so a custom groups claim can be absent from the Cf-Access-Jwt-Assertion header. When that happens, group-based admin never triggers and the failure is invisible. The documented fallback is an email allowlist via PROXY_AUTH_ADMIN_EMAILS, and the documented way to check is decoding a real request token from browser DevTools. Cloudflare may nest custom claims under a custom object rather than the flatter layout shown in examples, and the README says your decoded token is the ground truth for your tenant.

Where MeshMonitor is the wrong tool

The connection model is the limit. MeshMonitor talks to nodes over TCP and HTTP, and the environment variables are named MESHTASTIC_NODE_IP and MESHTASTIC_TCP_PORT. If your only radio is reachable over Bluetooth, the documented configuration does not cover you, and the repository's separate docker-compose.ble.yml exists but the README does not walk through it. A single-node setup where you check the phone app occasionally also gains little: you would be running a Node.js server, a database and a container to replace a view you already have. The project is also moving quickly. The releases listed for late August 2026 are all v4.15.2 release candidates, and package.json on main reports 4.16.1-rc3, so the version you pull from the latest image tag is not the version documented in the repository. If you need a frozen, audited release line, pin the image to a specific tag rather than latest. Finally, the README leans on the external documentation site for installation, configuration and troubleshooting; the repository copy is a starting point, not a complete manual.

How it compares with Meshsense and MQTT-only dashboards

People searching for a MeshMonitor alternative usually land on Meshsense, and the difference is architectural rather than cosmetic. Meshsense is aimed at the same Meshtastic monitoring problem, but MeshMonitor's distinguishing choices are its multi-database support and its multi-transport scope. The README lists SQLite, PostgreSQL and MySQL as storage options, which means an operator who already runs PostgreSQL can keep mesh history in the same place as everything else, and the migrate-db script exists to move schema forward. The second difference is scope: MeshMonitor treats Meshtastic, MeshCore and MQTT as three source types in one dashboard, while a plain MQTT subscriber or a Grafana stack gives you the MQTT half and nothing else. The repository does ship examples/grafana, so the project itself acknowledges that Grafana is a reasonable place to visualise exported data. The trade-off is weight. MeshMonitor is a full application with authentication, user accounts and a database, where a small MQTT-to-influx pipeline is a few lines of configuration. Pick MeshMonitor when you want history, users and a UI; pick the pipeline when you only want the numbers.

Licence, upgrades and what maintenance costs you

MeshMonitor is BSD-3-Clause, a permissive licence that allows modification and redistribution provided the copyright notice and disclaimer are retained. That is a practical advantage over copyleft alternatives if you intend to fork or ship it inside a product, but it also means no warranty, and the SECURITY.md file in the repository is where the project documents its own vulnerability reporting process rather than a support commitment. The last push to main was on 2026-08-27, so the codebase is current. The upgrade path has two documented shapes. The compose file mentions an auto-upgrade overlay, invoked as docker compose -f docker-compose.yml -f docker-compose.upgrade.yml up -d, with details in docs/configuration/auto-upgrade.md. The Helm route upgrades through helm repo update and a new install. Either way, the database schema moves with the migrate-db CLI, and the persistent volume at /data is what you must back up before an upgrade, since that is where the database lives. The cost of running this is not the licence, it is the operational surface: a Node.js container, a database, an optional MQTT broker on port 1883, and a reverse proxy if you want TLS.

Editorial conclusion

Adopt MeshMonitor if you already run Meshtastic or MeshCore nodes over IP and want one dashboard with SQLite, PostgreSQL or MySQL behind it. Skip it if your nodes are only reachable over Bluetooth or you need a hosted service with no server to run. Before you expose it, verify three things: that you have changed the admin password from changeme, that TRUST_PROXY is set to 1 whenever a reverse proxy sits in front, and that the port mapping 8080:3001 matches your deployment. The repository's own docs at meshmonitor.org are the ground truth for anything the README leaves out.

Frequently asked questions

How do I set up MeshMonitor?

The README's quick start creates a docker-compose.yml that pulls ghcr.io/yeraze/meshmonitor:latest, maps host port 8080 to container port 3001, mounts a volume at /data, and sets MESHTASTIC_NODE_IP to your node. Then run docker compose up -d and open http://localhost:8080. Kubernetes users can install from the Helm repository instead.

What is the default password for MeshMonitor?

The README states the default login is admin with the password changeme, and instructs you to change it after the first login. The repository also ships reset-admin.mjs and check-admin.mjs scripts at the top level for recovering or inspecting the admin account.

What is MeshMonitor?

MeshMonitor is a web application for monitoring off-grid mesh networks, covering Meshtastic, MeshCore and MQTT from a single dashboard. It is built with React, TypeScript and Node.js, and stores data in SQLite, PostgreSQL or MySQL.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/yeraze-meshmonitor.svg)](https://hysenlabs.com/projects/yeraze-meshmonitor)