VerneMQ
What is VerneMQ?
Section titled “What is VerneMQ?”VerneMQ is a high-performance, distributed MQTT message broker designed for IoT and messaging applications. Built on Erlang/OTP, it offers excellent scalability, reliability, and fault tolerance. VerneMQ is designed to handle millions of concurrent connections and messages, making it ideal for IoT applications.
Quick Start
Section titled “Quick Start”To get started with VerneMQ, follow these steps:
After starting the OAK Platform with docker compose up -d, you can access the VerneMQ dashboard by navigating to http://localhost:8889 in your web browser. The dashboard provides an overview of the broker’s status, connections, and metrics.
MQTT Authentication
Section titled “MQTT Authentication”The VerneMQ broker is configured with secure authentication through environment variables:
- MQTT_USER: Username for MQTT authentication (configured in .env)
- MQTT_PASSWORD: Password for MQTT authentication (configured in .env)
- Anonymous access: Disabled for security
The broker automatically creates the specified user during initialization, ensuring secure access to the MQTT broker.
This single shared credential is broker-wide - every client that uses it can publish/subscribe to every topic. For individual devices or teams that shouldn’t share one password, issue scoped credentials through the LEAF Portal instead: see Per-department MQTT credentials below. That’s now the recommended way to onboard new devices; the shared .env credential is mainly there for bootstrapping the stack itself.
Network Configuration
Section titled “Network Configuration”VerneMQ is configured to operate on both the backend and frontend networks:
- Backend Network: Internal communication with other services
- Frontend Network: External client access
- Ports (as exposed by this docker-compose setup - raw container ports, no TLS termination in front by default):
- 1883: MQTT (standard)
- 8883: MQTT over TLS/SSL
- 8080: MQTT over WebSockets
- 8889: HTTP status/metrics endpoint
In a production deployment, you’d typically put a TLS-terminating reverse proxy/ingress in front of the WebSocket port rather than exposing 8080 directly - clients then connect over
wss://on the standard 443, with the proxy forwarding internally to VerneMQ’s 8080. VerneMQ itself doesn’t listen on 443; that’s the reverse proxy’s job.
Security Features
Section titled “Security Features”The VerneMQ configuration includes several security features:
- Anonymous access disabled: Only authenticated users can connect
- Environment variable configuration: Credentials are securely managed through Docker secrets
- Health checks: Automated monitoring of broker health
- Resource limits: Memory and CPU constraints to prevent resource exhaustion
Per-department MQTT credentials (strongly recommended)
Section titled “Per-department MQTT credentials (strongly recommended)”Not required for the stack to run - the shared credential alone is enough to bootstrap VerneMQ - but strongly advised for anything beyond initial setup: with only the shared credential, every connected client can publish/subscribe to every topic, so one leaked device credential exposes the whole broker.
VerneMQ also supports authenticating individual clients against the database via its vmq_diversity Postgres-auth plugin. This unlocks the MQTT Accounts page in the LEAF Portal admin section, where superadmins and department admins can issue per-department MQTT credentials scoped to that department’s own topic namespace - so a leaked or misused device credential only ever exposes its own department, not the whole broker.
Each account is a username/password an MQTT client (sensor, gateway, script) connects with. Both publish and subscribe are limited to leaf/<organisation>/<department>/# - nothing outside that department’s namespace. The password is shown once at creation and never displayed again, so treat it like any other secret: store it in the client’s own config, not somewhere you’d need to look it up later.
This connects as leaf_vernemq_user, a role scoped to exactly one grant: SELECT on vmq_auth_acl, nothing else in the schema - deliberately not a readers/writers member, since VerneMQ only ever needs to read that one credentials table to authenticate a connecting client. See Database Access for how this fits alongside the other service accounts.
This feature only appears in the portal once the vmq_auth_acl table exists. It doesn’t replace the shared credential above - Node-RED and other system-level clients still connect with it - but individual devices and teams should get their own scoped credential here rather than sharing that broker-wide password.
Connecting Clients
Section titled “Connecting Clients”To connect MQTT clients to the VerneMQ broker, use the following connection parameters:
# Basic MQTT connectionmosquitto_pub -h localhost -p 1883 -u "$MQTT_USER" -P "$MQTT_PASSWORD" -t "leaf/demo/example" -m "Hello World"
# MQTT over TLSmosquitto_pub -h localhost -p 8883 -u "$MQTT_USER" -P "$MQTT_PASSWORD" -t "leaf/demo/example" -m "Hello World" --capath /etc/ssl/certs
# MQTT over WebSockets# Use WebSocket client libraries with URL: ws://localhost:8080/mqttIf you’re connecting with a per-department credential from MQTT Accounts rather than the shared
$MQTT_USER, the topic must start with that account’s ownleaf/<organisation>/<department>/prefix - publishing anywhere else will be rejected.
Topic Structure
Section titled “Topic Structure”LEAF adapters use a structured topic hierarchy for organizing data:
leaf/<organisation>/<department>/<adapter_id>/<instance_id>/experiment/<experiment_id>/measurement/<measurement>
# Where <xxx> is a placeholder for the actual value.The leaf/<organisation>/<department>/ prefix is what per-department MQTT Accounts (above) actually enforce publish/subscribe access down to - everything after that within the same department is open to a device holding that department’s credential.
This structure is coordinated through the YAML configuration file in combination with the adapter used.
Monitoring and Metrics
Section titled “Monitoring and Metrics”The VerneMQ dashboard at http://localhost:8889 provides:
- Connection statistics
- Message throughput metrics
- Client connection details
- System resource usage
- Real-time monitoring of MQTT activity
Troubleshooting
Section titled “Troubleshooting”Common issues and solutions:
- Connection Refused: Check if VerneMQ is running with
docker compose ps vernemq - Authentication Failed: Verify MQTT_USER and MQTT_PASSWORD in .env file
- No Messages: Check topic structure and client subscriptions
- High Memory Usage: Monitor connection count and message rates
For detailed logs, use:
docker compose logs -f vernemq