Installation
The broker is one executable. On Linux the Debian package additionally registers a systemd unit, creates the working directory and starts the service; on Windows the file runs from wherever you put it.
wget https://elxsoftware.com/download/elxmqttbroker-linux-amd64
sudo install -m 755 elxmqttbroker-linux-amd64 /usr/local/bin/elxmqttbroker
sudo elxmqttbroker --install-service
sudo systemctl enable --now elxmqttbroker
For 32-bit and 64-bit ARM boards the procedure is identical — take arm64 or armhf instead. uname -m tells you which one the board is: aarch64 means arm64, armv7l means armhf.
Run the installer, or unpack the portable build and start elxmqttbroker.exe.
The dashboard opens at http://127.0.0.1:8567
Default credentials: admin / admin
admin / admin so that the first launch works without configuration. Change it in the dashboard before the machine becomes reachable from anywhere but your desk.The first launch
- Open
http://<address>:8567and sign in. - Change the administrator password in the profile menu.
- Create a user for your devices in Users and give it the topics it needs — the permission list is empty at first, and an empty list means no access.
- Connect one client and watch it appear in Clients: that confirms the address, the port and the credentials in one step.
- Publish a test message from Publish and check that the subscriber receives it.
Users and permissions
Every account carries a list of rules. A rule is a topic filter, an access type — subscribe, publish or both — and a verdict: allow or deny. Nothing is permitted that is not stated: an account with no rules can connect and do nothing.
| Rule | Meaning |
|---|---|
sensors/# · subscribe · allow | May read the whole sensors branch |
sensors/kitchen/+ · publish · allow | May write to any topic one level under kitchen |
devices/$u/# · both · allow | May do anything inside its own branch, and nothing outside it |
# · both · deny | Explicitly refuses everything not allowed above |
The $u placeholder expands to the account name at connection time. One rule therefore serves a thousand devices without a thousand rules: each device sees only its own subtree.
deny placed above a narrow allow hides it entirely — that is the usual reason a permission “does not work”.Where credentials come from
The broker can keep its own account list, or ask something else. The source is switched live, without a restart, so you can test a new backend while the old one is still serving.
- Built-in. Accounts stored in the broker's own database. Right for a few dozen devices.
- MariaDB / MySQL. A table you already have, with the query written in the settings. Right when a device inventory already exists elsewhere.
- SQLite. A file with the same shape, for a system that keeps its data locally.
- CSV. A plain file, re-read on change. Convenient for a fixed list produced by another tool.
- JWT. The device presents a signed token instead of a password; the broker verifies the signature and reads the permissions from the claims.
- HTTP. The broker asks your service whether this client may connect, and your service answers. Everything you already implement — device blocking, tariffs, quotas — applies without duplication.
TLS
Point the broker at a certificate and a key and the encrypted listener starts on port 8883; the dashboard can use the same pair. For a closed network the broker can generate a self-signed pair itself, which is enough to keep passwords off the wire.
openssl s_client -connect broker.example.com:8883 -servername broker.example.com </dev/null | head -20
Bridges
A bridge is a permanent connection to another broker with a list of topics to carry. Direction is per topic: out pushes local messages outward, in pulls remote messages in, both does both.
- A prefix can be added on either side, so that messages from a remote site arrive under
site-b/…and never collide with local ones. - Loop protection stops a message that came in through a bridge from being sent straight back out.
- A dropped connection is retried with a growing delay; the queue keeps going in the meantime.
- TLS and credentials are configured per bridge, so two sites can use different certificates.
Delayed publish
Publishing to $delayed/<seconds>/<topic> hands the broker a message to deliver later. The message is stored, survives a restart, and appears in the dashboard where it can be cancelled before it fires.
mosquitto_pub -h broker -t '$delayed/300/home/light/kitchen' -m 'off'
The syntax matches EMQX, so scripts written for that broker work unchanged.
Rate limits
Two mechanisms, aimed at different problems. A per-connection token bucket stops one client from flooding the broker. Per-topic rules deal with a device that is merely too enthusiastic: instead of disconnecting it, they thin the stream to a rate and keep the most recent value.
| Rule | Effect |
|---|---|
sensors/+/raw · 1 per second | At most one message a second per topic; the newest wins |
debug/# · drop | Discarded at the broker, subscribers never see it |
| Connection · 200 per second | A client exceeding it is throttled, then disconnected |
REST API
The dashboard is a client of the same API you can use. Create a token in the settings, choose whether it may write, and call it from your own system.
curl -X POST https://broker.example.com/api/users \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"name":"sensor-42","password":"...","acl":[{"filter":"devices/sensor-42/#","access":"both","allow":true}]}'
What survives a restart
- Retained messages — the last value of every topic that asked to be retained.
- Persistent sessions — subscriptions of clients that connected with
clean_sessionoff. - Offline queues — QoS 1 and 2 messages for those sessions while the client is away.
- Delayed messages that have not fired yet.
- Users, permissions, bridges, rules and settings.
All of it lives in one SQLite file. Backing the broker up means copying that file; moving it to another machine means copying it there.
When something is wrong
| Symptom | Where to look |
|---|---|
| Client connects, then disconnects immediately | Credentials, or a permission list that denies everything. The event feed names the reason. |
| Messages are published but nobody receives them | The publisher's permissions allow writing but the subscriber's do not allow reading that filter. |
| Retained value does not come back after a restart | Persistence is disabled, or the working directory is not writable by the service user. |
| A device reconnects in a loop | Two clients are using the same client identifier — each connection kicks the other off. |
| TLS client reports a certificate error | A self-signed certificate that the client does not trust, or a hostname that does not match the certificate. |
| The dashboard is unreachable from another machine | The dashboard is bound to the loopback address; change the bind address in the settings. |
Frequently asked questions
Where is the log?
journalctl -u elxmqttbroker -f. On Windows, the console window, or the log file next to the executable when it runs as a service.