MQTT Management Platform — Release 1
Web-based administration for an Eclipse Mosquitto 2.1 broker: management login/RBAC, MQTT client/group/role management with ACL editing via the Dynamic Security plugin, and generated + validated broker configuration.
Architecture and scope follow specification.md (Release 1, §68.1).
Stack
mqtt-frontend React (Vite build) served by nginx, proxies /api → backend
mqtt-backend FastAPI: management auth, RBAC, dynsec client, config engine
mosquitto Eclipse Mosquitto 2.1.2 (pinned), dynsec enabled
mosquitto-control control sidecar: validate/activate/reload configs
mqtt-db PostgreSQL (management data only; NOT host-exposed)
Networks: frontend-net (frontend↔backend) and backend-net
(backend↔db↔mosquitto↔control). Only the frontend HTTP port is published.
Quick start
cp .env.example .env # then EDIT the change-me values!
docker compose up -d --build
Open http://localhost:8080 and sign in with ADMIN_INITIAL_USERNAME /
ADMIN_INITIAL_PASSWORD from your .env.
Bootstrap sequence on first start:
- PostgreSQL starts; backend creates its schema (or run migrations explicitly, see below) and seeds the management admin.
- Mosquitto starts with
mosquitto/bootstrap/mosquitto.confon the internal network; the dynsec plugin seeds itsadminclient fromMOSQUITTO_DYNSEC_PASSWORD. - Backend connects to dynsec as that admin client — the management channel is alive.
- Configuration changes made in the UI are generated from the
PostgreSQL model, validated with
mosquitto --test-config(via the control sidecar), deployed atomically, and recorded as a revision.
Note for Windows users: the compose healthcheck for mosquitto and the control sidecar rely on Unix facilities (
pid: service:, POSIX shell commands); run the stack with Docker Desktop + WSL2 as usual — nothing here assumes a Linux host beyond Docker itself.
Configuration channels (why this design)
- Dynamic Security (runtime) — clients/groups/roles/ACLs change via
the MQTT
$CONTROL/dynamic-security/v1API. No files involved. - Generated mosquitto.conf (rare) — listeners/global settings are
generated from the DB model and deployed through
mosquitto-control, which shares the broker's PID namespace (pid: "service:mosquitto") to signal reloads. No Docker socket is mounted anywhere (spec §29). - Mosquitto 2.1's HTTP API is not used as a management channel: it has no authentication and (currently) exposes read-only plugin info.
Development
Backend (in container):
docker compose exec mqtt-backend pytest -q # API + generator tests
docker compose exec mqtt-backend ruff check app tests
docker compose exec mqtt-backend alembic upgrade head # explicit migrations
Frontend (local dev server with proxy to backend):
cd frontend && npm install && npm run dev # http://localhost:5173
Repository layout
compose.yaml stack definition (5 services, 2 networks)
.env.example environment template (secrets: edit before use)
mosquitto/bootstrap/ the one file that ships with the deployment
broker-control/ validate / atomic-activate / reload sidecar
backend/ FastAPI app, models, dynsec client, configgen
frontend/ React + Vite SPA served by nginx
Release 1 scope (see specification.md §68.1)
Included: management authentication & RBAC, dynsec clients/groups/roles with the six ACL types, config generation from the PostgreSQL model, validation, deployment with revision history.
Not yet (Release 2/3): PKI/certificates, mTLS listeners, diff view, rollback, ACL simulator, dashboard/$SYS, audit browsing UI, backup.