Credits:The XMQ web site is provided by Linotex.The XMQ and SPTK Windows installers are created with Advanced Installer free Open-Source license.
There were 0 unique visitors to this page

XMQ MQTT Server – Documentation

Basic MQTT setup

Everything in this section can be set from the configuration interface, and is written back to/etc/xmq/xmq_server.conf. The user data is stored in the file/etc/xmq/xmq_users.conf. Hand-editing these files is still possible; if you do, restart the server afterwards, since a running server rewrites the files when settings change and would overwrite your edit.

The XMQ configuration interface is available through the browser at https://xmq_host:18883, where xmq_host is the host the XMQ server runs on. It is administered through the admin account. A server that has never been set up is the exception in two ways: it answers at https://127.0.0.1:18883 and nowhere else, and admin has no password yet — sign in with the password field left empty, and set one on the Initial Setup page that opens.

Starting from scratch

The Initial Setup page asks for the few settings a working server cannot be without — an administrator password, a node name, the MQTT, MQTT+SSL, and interface ports, and optionally a Redis address — and builds a configuration around them. It is the quickest way to bring up a new installation, and the way back to a known state when a configuration has been edited into a corner.

The admin account comes first on that page because it is what the interface is administered through: setup creates the account if it is not there, and gives it the password entered either way, so the configuration it produces always comes with a way in. Since a session carries the password it signed in with, changing it ends the current session — sign in again with the new password.

On a server being set up for the first time, that password does one more thing: it is what moves the interface off the loopback address. Until it is set the interface accepts connections from the server's own machine only, because an account that anyone can sign in to without a password has no business being reachable from a network. The account is refused everywhere else in the meantime — an MQTT client offering admin and no password is not connected.

It is the one page that discards settings rather than changing them. Everything it does not ask about is taken from /etc/xmq/xmq_server.conf.template, the copy of the shipped configuration the installer leaves behind, so listeners, bridges, limits, and logging settings all go back to their defaults. The template itself is only read; the result is written to xmq_server.conf.

The accounts are reset with them: xmq_users.conf is rewritten withadmin, using the password entered on the page, and the internalcluster account. MQTT clients that authenticate will need their accounts adding again on the Users page. Installed certificate files are kept, being files of their own rather than configuration.

Submitting restarts the MQTT server, which disconnects every client. Changing the interface port takes effect at once too: the interface starts answering on the new port before it stops answering on the old one, and the browser is sent there. Connections already open are served to the end, so the reply announcing the move still arrives. A port that cannot be taken — because something else holds it — leaves the interface where it was, and the page says so instead of sending the browser nowhere.

A missing configuration is not an error: the server writes a starting one fromxmq_server.conf.template, or from its own defaults if the template is gone too, and comes up on the ports above. A missing xmq_users.conf is written too, with an admin account that has no password and the internal cluster account. No accounts are installed by the package: a password shipped in a file is a password everyone who downloaded the package knows.

When the interface will not start

The Initial Setup page needs the interface to be running, which is no help when the configuration is what stops the server from starting: a port already taken, a listener bound to an address this host does not have, or a file edited into something that will not parse. The same reset is available from the command line, where nothing needs to be running:

sudo systemctl stop xmq
sudo xmq_server --reset-configuration   # or start the service again afterwards

It replaces xmq_server.conf with the starting configuration and carries on into a normal start. The file it replaced is kept beside it asxmq_server.conf.old, since it is usually still worth reading. Accounts are not touched — they are in their own file, and are not what stops a server from starting — except that one for admin is created, without a password, if there are no accounts at all.

Port numbers

Listeners are configured on the Listeners page. Each one is a port, a protocol, and a thread count. The shipped configuration defines two:

PortProtocolPurpose
1883MQTTPlain TCP, the standard MQTT port
8883MQTT+SSLTLS, the standard secure MQTT port
18883HTTPThe configuration interface and its control API

These are the standard MQTT ports, so most clients need no port setting at all. If another broker on the same host already holds them, either stop it or move one of the two: the Listeners page changes XMQ's ports, and the change takes effect as soon as the listener is saved.

A listener also carries a bind address. 0.0.0.0 accepts on every interface; naming one address restricts the listener to it, which is a simple way to keep a port on an internal network. Disabling a listener keeps its settings but closes its port.

The service port itself is set on the Service page, and changing it takes effect at once: the interface starts answering on the new port before it stops answering on the old one, and the page follows it there. Connections already open are served to the end. If something else already holds the port, the interface stays where it is and the page says so.

SSL certificates

An MQTT+SSL listener needs a server key and certificate. Install them from the SSL Keys page: choosing a file uploads its contents, and the server writes it into /etc/xmq/certs(C:\ProgramData\xmq\certs on Windows) and records the path. A previous file of the same name is kept beside the new one with an .old suffix.

  • Server key and server certificate are required for TLS.
  • CA certificate is needed only to verify client certificates.
  • Verify depth of 0 means clients are not asked for a certificate: the TLS listener proves the server's identity and no more. Above 0, a client must present a certificate that the CA certificate validates, within that many intermediate signers.

If the keys are missing or fail to load, the server logs an error, skips the MQTT+SSL listener, and carries on serving the plain one. That is worth checking in the log after installing certificates for the first time.

Logging

The Logging page sets the log file and the level per subject. Theminimum log level is a ceiling rather than a floor: each subject has its own level, and the server clips it to this one. Turning the ceiling down toINFO quietens everything without touching the individual subjects, and turning it up to DEBUG lets them speak at their configured level.

Levels are PANIC, ERROR, WARNING,NOTICE, INFO, DEBUG, from quietest to most verbose. Two subjects deserve care: Publish and Acks produce a line per message, not per client. At the rates XMQ is built for, DEBUGthere can outweigh everything else the server logs and cost real throughput. Leave them at ERROR unless you are chasing something specific.

Log rotation is left to the system. Session errors are always logged atERROR and are not configurable.

Users and anonymous access

Accounts on the Users page serve both MQTT clients and the configuration interface. An administrator may change the configuration; a non-administrator can connect but not administer. Allow anonymous lets MQTT clients connect with no credentials at all; it does not affect the configuration interface, which always requires signing in.

Persistence

Without persistence the server keeps everything in memory and nothing survives a restart. With it, client sessions, their subscriptions, and undelivered QoS 1 and QoS 2 messages are stored in Redis. Redis is a separate service, not part of XMQ: install and start it yourself, then enable persistence on the Persistencepage.

If the server cannot reach Redis at startup it logs the error and keeps running with in-memory storage. The server stays up and nothing is persisted, so the log is worth a look after enabling it.

What survives a failure is decided in two places: Max queued writes on that page bounds what the server can lose, and Redis's own appendfsync setting decides what Redis loses when its machine goes down. Redis's defaults keep only periodic snapshots, so turn on appendonly yes. The two modes worth using - Durable and Super-Durable - and what each can lose are described on xmq.sptk.net/xmq_persistence.

;

Advanced setup

MQTT bridges

A bridge is a client connection XMQ makes to another MQTT broker, carrying an agreed set of topics. The remote broker does not have to be XMQ: bridging to Mosquitto, EMQX, or anything else speaking MQTT works the same way. Bridges are configured on the Bridges page.

A bridge has a direction, and so does each of its topics:

ModeMeaning
outMessages published on this server are forwarded to the remote one
inThis server subscribes to the remote one and republishes what it sends
inoutBoth directions

Each topic entry carries a pattern, a direction of its own, and the QoS to subscribe with. A topic's direction narrows the bridge's: a topic markedout on an inout bridge travels outbound only. Topics keep the name they were published with; there is no rewriting between the two servers. A bridge with no topics carries nothing.

Things worth getting right
  • Client ID must be stable. The remote broker keys the bridge's stored subscriptions and queued messages by it. An id that changes between reconnects leaves orphaned sessions accumulating on the remote. Left empty, XMQ derives one from the two node names, which is stable.
  • Leave clean session off. The remote then keeps the subscriptions and queues messages while the link is down, so a brief outage does not lose them. With it on, the session starts empty each time and anything published while disconnected is gone.
  • Loops. XMQ marks its bridge connections with an origin node, so it will not echo back a message that arrived over the bridge. Bridging through a broker that does not do the same, in both directions, on overlapping topics, can still produce a loop.
  • Encrypted bridges use key files already present on the XMQ host, given by path. That is the opposite of the SSL Keys page, which uploads content. The remote broker must be listening on its TLS port.
Bridging two XMQ servers, step by step

This walks through joining two XMQ servers so that a client on either one sees traffic published on the other. Call them mq-a and mq-b; substitute your own host names throughout. One bridge is enough, defined on mq-a and pointing at mq-b, in inout mode - that single bridge carries both directions. Do not define a second one on mq-b pointing back; see the end of this section for why.

The shipped configuration defines no bridges and no cluster nodes, so the Bridges page is empty on a fresh installation. Everything below is added by hand.

Before you start

  • Both servers installed, running, and reachable from each other on their MQTT port - a bridge is an ordinary outbound MQTT connection, so a firewall between the hosts needs that port open in both directions.
  • Decide which topics to carry. This example uses test/#. Prefer a specific prefix to #: it keeps the link's traffic to what you actually meant to share.
  • An account on each server for the other's bridge to log in as. The bridge authenticates like any client, so it needs a real account on theremote server. A non-administrator account is enough; create it on theUsers page if you do not already have one.

Step 1 - add the bridge on mq-a

Open http://mq-a:18883, sign in as an administrator, and go to theBridges page. It is a master-detail page: the bridge list on top, and the settings of the selected bridge below. Press Add, fill the settings in, and press Save Bridge:

FieldValue on mq-aNotes
Node namemq-bThe name this server knows the remote by. It appears in the log and marks messages that arrived over the link, which is how loops are prevented. A name already used by another bridge is rejected.
Host / portmq-b / 1883The remote MQTT listener, not its configuration port. A second bridge to the same host and port is rejected: it would carry every message twice.
ModeinoutBoth directions.
Usernamethe account on mq-bCredentials for the remote server, not this one.
Passwordits password
Client IDleave emptyXMQ then derives a stable id from the two node names. Set one only if the remote requires a particular id, and never one that varies.
Enabledticked
Clean sessionuntickedSo mq-b keeps the subscriptions and queues messages while the link is down.
EncrypteduntickedTick it only when bridging to the remote's TLS port; it reveals the key file fields, which are paths on this host.

Then fill the Topics table below the settings. Press its Add and give the topic a Pattern of test/#, a Direction ofinout, and a QoS of 1. A bridge with no topics connects and carries nothing, so this table is not optional.

Press Save Bridge. The bridge appears in the list with its topic count, and the configuration file is written immediately.

Step 2 - nothing to do on mq-b

mq-b needs no bridge of its own. It needs only the account the bridge signs in with, which it already has if you used one of its existing users. Nothing on mq-b records that a bridge exists: to it, mq-a's bridge is an ordinary client that subscribes and publishes.

Step 3 - press Apply on each server

This step is easy to miss. Saving a bridge stores it, but does not start the connection. Apply, on the Bridges page, rebuilds the connections from the configuration as it now stands: the bridges that were running are stopped, and the configured ones are started. Press it on mq-a.

Neither server has to be restarted, and mq-b does not have to be up yet: a bridge whose remote is not answering retries on its own, the wait between attempts growing to half a minute and dropping back as soon as it connects.

Restarting the server has the same effect, since bridges are started with it, and remains the way to apply a change made by editing the configuration file directly:

sudo systemctl restart xmq_server

Step 4 - confirm the link came up

With Connections at DEBUG on the Logging page, mq-a's log carries two lines for the bridge:

Bridge to mq-b forwarding 1 outbound topic(s).
Bridge to mq-b (mq-b:1883) connected, 1 inbound topic(s).

Both counts matter. connected with 0 inbound topics means the bridge reached the remote but carries nothing - almost always an empty or mistyped Topics field.

Step 5 - prove a message crosses

Subscribe on one server and publish on the other. The subscriber has no other way to see the message, so receiving it is itself the proof the bridge carried it:

xmq_sub -h mq-b -p 1883 -u user -P secret -t test/bridge -q 1 -v -C 1 -W 15

xmq_pub -h mq-a -p 1883 -u user -P secret -t test/bridge -q 1 -m "over the bridge"

Then swap the two hosts and repeat, to check the other direction: oneinout bridge carries both, but the two use different halves of it, and it is quite possible for one to work while the other does not.

For a measured run rather than a single message, xmq_scn can publish to one server and subscribe on the other:

xmq_scn -s Basic/Point-To-Point-1K-1K-1K-1K.json \
        --host mq-a --port 1883 --subscriber-host mq-b --subscriber-port 1883

Every message it counts has crossed the bridge, so the reported latency includes the extra broker hop and the round trip between the hosts. Compare it against the same scenario run without --subscriber-host to see what the link costs.

If nothing crosses

  • No bridge line in the log at all - Apply was not pressed after the bridge was saved, or the bridge is not enabled. Saving stores the bridge; it does not start it.
  • Repeated connect failures - the host or port is wrong, the port is blocked, or the credentials name an account that does not exist on theremote server. The log names the reason.
  • Connected, nothing carried - the topic pattern does not cover the topic being published. Patterns are matched as MQTT subscriptions:test/# covers test/bridge, while teston its own does not.
  • One direction only - check the mode on both bridges. A bridge inout mode forwards but never subscribes.
  • Everything arrives twice - a bridge is defined on both servers, each covering the same topics. One inout bridge carries both directions by itself, so the second one only moves the same message a second way; remove it. The subscribers on the publishing server still see one copy, which is what makes this look like a delivery fault rather than a configuration one. This is explained under Why one bridge, and not one on each server below.

Why one bridge, and not one on each server

An inout bridge already carries both directions on its own: it subscribes on the remote for what comes in, and subscribes locally for what goes out. A second bridge, defined on the other server and pointing back, adds nothing but a second copy - the message arrives once because this server pulled it, and again because the other server pushed it. Both copies are legitimate deliveries, so nothing detects or suppresses them: a subscriber simply receives everything twice.

Define the bridge on one of the two servers only. Which one does not matter.

Bridged traffic is not sent back the way it came - a message is marked with the node it arrived from, and a bridge subscription is never given a marked message. That marking is XMQ's own, so it only covers the bridges XMQ itself makes. When the broker at the other end is doing the bridging, what protects you is described next.

More than two servers

Bridged traffic is not passed on. A message that reached this server over one bridge is delivered to its own subscribers, but it is not handed to a second bridge - that is the same rule that stops a message going back where it came from, and it cannot tell "back" from "onward".

So the shapes that look natural do not work. In a chainA - B - C, B sees everything from both, but A and C never see each other. In a star, the hub sees every spoke and no spoke sees another.

Give every pair its own bridge instead. Three servers need three:A-B, A-C and B-C, each defined once, on either end. Every server then has a direct link to every other, so nothing needs relaying - and because nothing is relayed, nothing is duplicated either: each message arrives exactly once at each server.

The cost is that the number of bridges grows as the square of the number of servers: three servers need three bridges, four need six, five need ten. Bridging suits a handful of servers, and the arithmetic is what limits it.

Bridging to a broker that is not XMQ

A bridge to Mosquitto, EMQX, or anything else speaking MQTT is configured exactly as above; only the remote's own settings differ. One of them is worth getting right, because it decides whether messages can circulate endlessly between the two brokers.

Configure the remote's bridge to use MQTT 5. In Mosquitto that is one line in its bridge block:

connection xmq
address xmq-host:1883
topic test/# both 0 "" ""
remote_username user
remote_password secret
bridge_protocol_version mqttv50

MQTT 5 defines two subscription options that exist for precisely this purpose.No Local tells the broker not to send a subscriber back what that same connection published, which is what stops a message going round; and Retain As Published keeps a retained message retained as it crosses. A bridge that subscribes with them cannot be echoed to, and XMQ honours both, whoever set them. XMQ's own bridges set them too, which is why a bridge between two XMQ servers needs nothing configured for this.

Mosquitto defaults to mqttv311 instead. Such a bridge still connects and still carries messages, but the loop protection is absent: MQTT 3.1.1 has no subscription options to carry it, and the non-standard "bridge" protocol variant Mosquitto tries first - a protocol level with the high bit set - is not something XMQ accepts. Mosquitto notices the refusal and reconnects as an ordinary client, so the only visible cost is one rejected connection attempt, and the invisible one is that XMQ cannot tell that client is a bridge.

With a 3.1.1 remote bridge, then, keep the topic patterns from overlapping in both directions - carry a/# one way and b/# the other, rather than # both ways - or drive the link entirely from the XMQ side, where the origin marking applies.

Server limits

The Server Limits page holds the thread counts and the per-session bounds. The rule for threads is short: XMQ pins its threads to physical cores, and no thread group should be larger than the host's physical core count. The groups share those cores, so count the send threads, the receive threads, the persistence threads and the per-listener threads together rather than each on its own. Adding threads past that buys contention, not throughput.

;