![]() | ||||
| 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 DocumentationXMQ User ManualXMQ is an MQTT 5, 3.1.1, and 3.1 server. This manual covers installing it, tuning the host it runs on, configuring it from the configuration interface, and proving that the result works. Supported operating systemsXMQ is built and packaged for the systems below. Each is a 64-bit x86 build, packaged in the format native to that system.
Other Linux distributions of comparable vintage generally work when built from source, but only the versions listed here are tested and packaged. Download and install binariesThe only official download location is here. Select the latest SPTK version and your operating system, and download xmq_server package. Packages are named The dependencies for Linux include brotli and pcre2 packages that are included in all major Linux distributions. On FreeBSD The package file name carries the version and the architecture, so the commands below use a wildcard. Run them in the directory the package was downloaded to. Debian and Ubuntusudo apt install ./xmq-server_*.deb Fedora and Oracle Linuxsudo dnf install ./XMQ-server-*.rpm FreeBSDsudo pkg install ./XMQ-server-*.pkg Installing through the package manager rather than What gets installed
On Windows the equivalents live under Running the serverThe package installs a systemd unit, so on Linux the server is managed the usual way: sudo systemctl enable --now xmq_server sudo systemctl status xmq_server sudo journalctl -u xmq_server -f On FreeBSD the package installs an sudo sysrc xmq_server_enable=YES sudo service xmq_server start sudo service xmq_server status On Windows, Useful options when running it by hand:
Setting the administrator password without the interfaceA freshly installed server has an administrator with no password, and until one is set the configuration interface answers on printf '%s' 'the-new-password' | sudo -u xmq xmq_server --set-password admin The password is read from standard input, not taken as an argument, so it does not appear in the process list or the shell history. On a headless server the alternative is to forward the port — Once the server runs, the configuration interface is reachable on port 18883 by default. On a server that has just been installed it answers on that machine only, at Nothing is shipped with a password. Until the administrator has one, the account cannot be used over MQTT at all and the interface cannot be reached from another machine — so the first sign-in has to be made from the server's own console, or through a forwarded port. Environment tuningA default Linux install is tuned for a few thousand sockets, not a few hundred thousand. Below roughly 10,000 concurrent connections the stock settings are fine and this section can be skipped. Above that, the limits below are the ones that bite, and each of them has been hit in real test runs. Ready-made files are installed with the package under
cd /usr/local/share/xmq/setup sudo install -m 0644 sysctl.d/mqtt.conf /etc/sysctl.d/mqtt.conf sudo install -m 0644 sysctl.d/port_range.conf /etc/sysctl.d/port_range.conf sudo install -m 0644 limits.d/mqtt.conf /etc/security/limits.d/mqtt.conf sudo modprobe nf_conntrack sudo sysctl --system Then log out and back in, so the The three that catch people out
Both ends need this. Every limit here is per host, and tuning only the server while leaving the client machine at defaults is the most common mistake. The ./preflight.sh # check this host as a client ./preflight.sh -H broker -r server -p 1883 # check a remote server host Basic MQTT setupEverything in this section can be set from the configuration interface, and is written back to The XMQ configuration interface is available through the browser at Starting from scratchThe 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 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 It is the one page that discards settings rather than changing them. Everything it does not ask about is taken from The accounts are reset with them: 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 from When the interface will not startThe 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 Port numbersListeners are configured on the Listeners page. Each one is a port, a protocol, and a thread count. The shipped configuration defines two:
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. 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 certificatesAn
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. LoggingThe 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 to Levels are Log rotation is left to the system. Session errors are always logged at Users and anonymous accessAccounts 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. PersistenceWithout 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. One setting there is a genuine trade-off. Max queued writes at 0 makes every message wait for its own record to become durable before it is sent: the safest setting, and the slowest. Above 0, record writes pipeline instead, roughly doubling throughput, and the value is approximately how many messages could be lost if the server were killed outright. Advanced setupMQTT bridgesA 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:
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 marked Things worth getting right
Bridging two XMQ servers, step by stepThis 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 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
Step 1 - add the bridge on mq-a Open
Then fill the Topics table below the settings. Press its Add and give the topic a Pattern of 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 Bridge to mq-b forwarding 1 outbound topic(s). Bridge to mq-b (mq-b:1883) connected, 1 inbound topic(s). Both counts matter. 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: one For a measured run rather than a single message, xmq_scn -s Basic/Point-To-Point-1K-1K-1K-1K.json \
--host mq-a --port 1883 --subscriber-host mq-b --subscriber-port 1883Every 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 If nothing crosses
Why one bridge, and not one on each server An 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 serversBridged 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 chain Give every pair its own bridge instead. Three servers need three: 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 XMQA 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 With a 3.1.1 remote bridge, then, keep the topic patterns from overlapping in both directions - carry Server limitsThe 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. MQTT testing suite
Scenarios ship in xmq_scn --list-scenarios A scenario file names the client groups, their counts, the topics, and the pacing. The shipped set covers connection ramps, fan-in, fan-out, and point-to-point, at sizes from 10,000 to 1,000,000 connections. Writing a new one is a matter of copying the closest and changing the numbers. xmq_scn -s Point-To-Point-50K-50K-50K-50K.json --progress xmq_scn -s 1M-Connections-5K-rate.json -h broker -p 1883
Reaching the larger sizes needs the tuning above on both hosts, and enough source addresses on the client: a connection is identified by its source address and port, so one address runs out of ports long before a million connections. The tested 1,000,000-connection runs used 30 client addresses, about 33,000 connections each. The ./make_ip_addresses.sh -s <first three octets> -p <prefix> -f <first host octet> -c 29 Scenarios spread their clients across whatever addresses the host has, so the Run the load generator on a different machine from the broker. Sharing a host means measuring the two competing for the same cores, which flatters neither. Testing your setupThree small utilities are enough to prove an installation works. All of them take Is the server up?systemctl status xmq_server tail -f /var/log/xmq/xmq_server.log The log names each listener it opened at startup, and says which storage it is using: a Redis address, or Subscribe and publishIn one terminal, subscribe. In another, publish, and watch it arrive: xmq_sub -h localhost -p 1883 -u user --password secret -t "test/#" -q 1 -v xmq_pub -h localhost -p 1883 -u user --password secret -t test/hello -m "it works" Useful Testing TLSxmq_sub -h localhost -p 8883 -u user --password secret \
-t "test/#" -q 1 -v --cafile /etc/xmq/certs/ca.crtIf this fails while the plain port works, the certificates are the place to look: the server log says whether it managed to load them at startup. Many connections at once
xmq_con -h localhost -p 1883 -u user --password secret -n 10000 --show-counters If it stops short of the number asked for, the file descriptor limit is the usual cause, on whichever host ran out first. Check both, then see the tuning section. Checking a bridgeSubscribe on the remote broker, publish on XMQ, and confirm the message crosses: xmq_sub -h remote-broker -p 1883 -t "bridged/#" -q 1 -v xmq_pub -h localhost -p 1883 -u user --password secret -t bridged/test -m "over the bridge" Nothing arriving usually means the bridge is disabled, its topic pattern does not cover the topic, or its direction excludes it. The server log, withConnections at |
