flashmq.conf (5)
FlashMQ configuration file format
Synopsis
The flashmq.conf file is the configuration used for configuring the FlashMQ MQTT broker.
Config location#
By default, the flashmq daemon expects to find its configuration file at /etc/flashmq/flashmq.conf, but this can be overriden using the --config-file command-line argument; see the flashmq(1) man page for details.
Using the include_dir parameter in your config file, you can load all the *.conf files from that given directory.
File format#
To set a parameter, its name must appear on a single line, followed by one or more potentially quoted arguments.
parameter-name1 parameter-value
parameter-name2 'value with spaces'
parameter-name3 "escaped \" quote"
multi-value-param one 'two' "three" "with ' char"
Quoted values are the same as unquoted values when they don't need it. They are necessary for when argument values have spaces, for instance.
When setting boolean values, yes/no, true/false and on/off can all be used.
To configure the listeners, use listen blocks, defined by { and }. See EXAMPLE LISTENERS for details.
Lines beginning with the hash character (“#”) and empty lines are ignored. Thus, a line can be commented out by prepending a “#” to it.
Global parameters#
plugin/path/to/plugin.so#-
FlashMQ supports an ELF shared object (
.sofile) plugin interface to add functionality, authorization and authentication, because it’s hard to provide a declarative mechanism that works for everybody. Seeflashmq_plugin.hfor the API and its documentation. It’s written in C++ for ease of passing FlashMQ internals without conversion to C, but you can basically just use a C++ compiler and program like it was C; the C++ constructs are simple.FlashMQ will auto-detect which plugin interface you’re trying to load (Mosquitto version 2 or FlashMQ native). Keep in mind that each thread initializes the plugin, inline with multi-core programming (minimize shared data and interaction between threads). You could use static variables with thread synchronization if you really want to. And of course, any Mosquitto plugin that uses global and/or static variables instead of initializing memory in its
init()method, will not be thread-safe and won’t work.You can only have one plugin active, but you can combine it with
mosquitto_password_fileandmosquitto_acl_file. The password and ACL file take precedence, and on a ‘deny’, will not ask the plugin. plugin_opt_*value#-
Options passed to the plugin
init()function. plugin_serialize_inittrue|false#-
There could be circumstances where the plugin code is mostly thread-safe, but not on initialization. Libmysqlclient for instance, needs a one-time initialization. To add to the confusion, Qt hides that away.
The plugin should preferrably be written with proper synchronization like that, but as a last resort, you can use this to synchronize initialization.
Default value:
false plugin_serialize_auth_checkstrue|false#-
Like
plugin_serialize_init, but then for all login and ACL checks.This option may be dropped at some point, because it negates much of the multi-core design. One may as well run with only one thread then.
Default value:
false plugin_timer_periodseconds#-
The FlashMQ auth plugin interface has an optional function that is called periodically this amount of seconds. This can be used to refresh state, commit data, etc.
Setting a value of 0 disables it. You can enable and disable this timer with a config reload.
See
flashmq_plugin.hfor details.Default value:
60 log_file/path/to/flashmq.log#-
This configuration parameter sets the path to FlashMQ's log file. If you omit this option from the config file, the output will go to stdout.
- ≥ v1.11.0
log_leveldebug|info|notice|warning|error|none# -
Set the log level to specified level and above. That means
noticewill lognotice,warninganderror.Use this setting over the deprecated
log_debugandquiet. If you do have those directives, they override thelog_level, for backwards compatability reasons.Default value:
info. log_debugtrue|false#-
Debug logging obviously creates a lot of log noise, so should only be done to diagnose problems.
Deprecated. Use
log_levelinstead.Default value:
false log_subscriptionstrue|false#-
Default value:
false allow_unsafe_clientid_charstrue|false#-
If you have topics with client IDs in it, people can possibly manipulate your ACL checking by saying their client ID is 'John+foobar'. Audit your security before you allow this.
Default value:
false allow_unsafe_username_charstrue|false#-
If you have topics with usernames in it, people can possibly manipulate your ACL checking by saying their username is 'John+foobar'. Audit your security before you allow this.
Default value:
false max_packet_sizebytes#-
MQTT packets have a maximum size of about 256 MB. This memory will (temporarily) be allocated upon arrival of such packets, so there may be cause to set it lower.
This option works in conjunction with
client_max_write_buffer_sizeto limit memory use.Default value:
268435461 - ≥ v1.4.4
client_max_write_buffer_sizebytes# -
The client's write buffer is where packets are stored before the event loop has the chance to flush them out. Any time a client's connection is bad and bytes can't be flushed, this buffer fills. So, there's good reason to limit this to something sensible. A good indication is your average packet size (or better yet, a configured
max_packet_size) multiplied by the amount of packets you want to be able to buffer.Despite the name, this settings also control the read buffer's maximum size. Having a bigger read buffer may be necessary when you know your clients receive many packets.
Note that it's an approximate value and not a hard limit. Buffer sizes only grow by powers of two, and buffers are always allowed to grow to make place for ping packets. Additionally, upon arrival of large packets (up to
max_packet_sizebytes), room will be made up to twice their size. So, you may also want to reducemax_packet_sizefrom the default.Default value is
1048576(1 MB) client_initial_buffer_sizebytes#-
The buffers for reading and writing, also for websockets when relevant, start out with a particular size and double when they need to grow. If you know your clients send bulks of a particular size, it helps to set this to match, to avoid constant memory reallocation. The default value is set conservatively, for scenario's with millions of clients.
After buffers have grown, they are eventually reset to their original size when possible.
Also see
client_max_write_buffer_sizeandmax_packet_size.Value must be a power of two.
Default value:
1024 mosquitto_password_file/foo/bar/mosquitto_password_file#-
File with usernames and hashed+salted passwords as generated by Mosquitto's
mosquitto_passwd.Mosquitto up to version 1.6 uses the sha512 algorithm. Newer version use sha512-pbkdf2. Both are supported.
mosquitto_acl_file/foo/bar/mosquitto_acl_file#-
ACL (access control lists) for users, anonymous users and patterns expandable with %u (username) and %c (clientid). Format is Mosquitto's acl_file.
allow_anonymoustrue|false#-
This option can be overriden on a per-listener basis; see
listener.allow_anonymous.Default value:
false - ≥ v1.11.0
zero_byte_username_is_anonymoustrue|false# -
The proper way to signal an anonymous client is by setting the 'username present' flag in the CONNECT packet to 0, which in MQTT3 also demands the absence of a password. However, there are also clients out there that set the 'username present' flag to 1 and then give an empty username. This is an undesirable situation, because it means there are two ways to identify an anonymous client.
Anonymous clients are not authenticated against a loaded plugin when
allow_anonymousis true. With this option enabled, that means users with empty string as usernames also aren't.With this option disabled, clients connecting with an empty username will be reject with 'bad username or password' as MQTT error code.
The default is to be unambigious, but this can be overridden with this option.
Default value:
false rlimit_nofilenumber#-
The general Linux default of
1024can be overridden. Note:systemdblocks you from setting it, so it needs to be set on the unit. The default systemd unit file setsLimitNOFILE=infinity. You may also need to setsysctl -w fs.file-max=10000000Default value:
1000000 expire_sessions_after_secondsseconds#-
Expire sessions after this time. Setting to 0 disables it and is (MQTT3) standard-compliant. But, existing sessions cause load on the server (because they cost memory and are still subscribers), so keeping sessions after any client that connects with a random ID doesn't make sense.
Default value:
1209600 quiettrue|false#-
Don't log LOG_INFO and LOG_NOTICE. This is useful when you have a lot of foot traffic, because otherwise the log gets filled with connect/disconnect notices.
Deprecated. Use
log_levelinstead.Default value:
false storage_dir/path/to/dir#-
Location to store sessions, subscriptions and retained messages. Not specifying this will turn off persistence.
- ≥ v1.15.1
save_state_intervalseconds# -
The interval at which the state is saved, if enabled with
storage_dir.This setting is also applied on reload.
Default: 3623
- ≥ v1.24.0
persistence_data_to_saveall|sessions_and_subscriptions|retained_messages|bridge_info# -
When a
storage_diris defined, specify which information should be saved. The arguments are a list of one or more of the specified options, and can be negated with a !. Meaning like:all !retained_messages. The order is relevant. If you end withall, it overrides the previous.The option
bridge_infocauses a small bit of meta data of the bridges to be saved. See the bridge optionuse_saved_clientid.The default is
all, but as soon as this option is defined, it's cleared, and the desired list has to be composed. max_qos_msg_pending_per_clientnumbermax_qos_bytes_pending_per_clientbytes#-
There is a limit to how many QoS packets can be stored in a session, so you can define a maximum amount of messages and bytes. If any of these is exceeded, the packet is dropped.
Note that changing
max_qos_msg_pending_per_clientonly takes effect for new clients (also when picking up existing sessions). This is largely due to it being part of the MQTT5 connection handshake and is supposed to be adhered to.Defaults:
-
max_qos_msg_pending_per_client 512
-
max_qos_bytes_pending_per_client 65536
-
- ≥ v1.23.0
max_qosqos_value# -
The maximum QoS value FlashMQ will allow clients to use for subscriptions, publishes and wills. Subscriptions will be downgraded to this value. Publishes and wills will cause a disconnect for MQTT5 clients, and the action configured with
mqtt3_qos_exceed_actionfor MQTT3 clients.The value is updated on config reload, but only for new clients. The reason is that the max QoS is part of the handshake in MQTT5, and clients will be surprised (and cause disconnects) if that changes during the lifetime of a connection. For consistency, the MQTT3 clients behave the same.
This setting is also available per listener.
Default value:
2 - ≥ v1.23.0
mqtt3_qos_exceed_actiondrop|disconnect# -
Unlike MQTT5, MQTT3 doesn't have defined behavior for exceeding a configured maximum QoS (see
max_qos). This allows the behavior to be controlled.In case of
dropthe client gets an acknowledgement as if the publish has succeeded, to avoid stale in-flight packets.This setting is also available per listener.
Default value:
disconnect - ≥ v1.4.2
max_incoming_topic_alias_valuenumber# -
Is communicated towards MQTT5 clients. It is then up to them to decide to set them or not.
Changing this setting and reloading the config only has effect on new clients, because existing clients would otherwise exceed the limit they think applies.
Default value:
65535 - ≥ v1.4.2
max_outgoing_topic_alias_valuenumber# -
FlashMQ will make this many aliases per MQTT5 client, if they ask for aliases (with the connect property
TopicAliasMaximum).Default value:
65535 thread_countnumber#-
If you want to have a different amount of worker threads then CPUs, you can set this value. Typically you don't need to set this.
Default value:
auto-detect wills_enabledtrue|false#-
When disabled, the server will not set last will and testament specified by connecting clients.
Default value:
true retained_messages_modeenabled|enabled_without_persistence|downgrade|drop|disconnect_with_error#-
Retained messages can be a strain on the server you may not need. You can set various ways of dealing with them:
enabled. This is normal operation.enabled_without_persistence. Like 'normal', except it won't store them to disk ifstorage_diris defined.enabled_without_retaining. This somewhat counter-intuitive sounding mode is likedowngrade, except that the 'retain' flag is not removed. This allows MQTT5 subscribers that subscribe with 'retain as published' to see which messages were originally sent as retained. It's just that FlashMQ won't retain them.downgrade. The retain flag is removed and treated like a normal publish.drop. Messages with retain set are dropped.disconnect_with_error. Disconnect clients who try to set them.Default value:
enabled expire_retained_messages_after_secondsseconds#-
Use this to limit the life time of retained messages. Without this, the amount of retained messages may never decrease.
Default value:
4294967295 - ≥ v1.6.7
retained_messages_delivery_limitnumber# -
Deprecated.
- ≥ v1.8.4
retained_messages_node_limitnumber# -
When clients place a subscription, they will get the retained messages matching that subscription. Even though traversing the retained message tree is deprioritized in favor of other traffic, it will still cause CPU load until it's done. If you have a tree with millions of nodes and clients subscribe to
#, this is potentially unwanted. You can use this setting to limit how many nodes of the retrained tree are traversed.Note that the topic
one/two/threeis three nodes, and each node doesn't necessarilly need to contain a message.Default value:
4294967295 - ≥ v1.14.0
set_retained_message_defer_timeoutmilliseconds# -
The time after which FlashMQ will fall back to (b)locking vs queued mode for setting retained messages. 0, the default, disables queued mode altogether. It's disabled by default because it can incur some extra CPU and memory overhead.
Each retained message lives in a node in a tree. The topic 'one/two/three' is three nodes. When a node in that tree does not exist yet, it needs to be created. This requires a write lock on the tree. At this point, other threads reading from or writing to the retained message tree need to wait. This can cause a compounding blocking effect, especially if many threads do it at once.
This feature is to favor server responsiveness vs the speed at which retained messages become available in the server. It is primarily useful for when you have a lot of retained messages on different/changing topics. If at first a retained message can't be set, the action to do so will be retried in the event loop, asynchronously.
This setting determines the maximum amount of time to defer setting a retained message, after which it will fall back to using locks.
Also see
set_retained_message_defer_timeout_spreadDefault value:
0 - ≥ v1.14.0
set_retained_message_defer_timeout_spreadmilliseconds# -
For
set_retained_message_defer_timeout, the amount of random spread between 0 and this value for the timeout. This spreads out locking over time, reducing contention.Default value:
1000 - ≥ v1.14.0
retained_message_node_lifetimeseconds# -
The grace period after which a retained message node is eligible for deletion. The topic 'one/two/three' is three nodes, and if that topic had a message, it would be contained in 'three'.
FlashMQ will periodically clear out retained message nodes that have no message anymore. This is required to save memory. But, when you receive retained messages on the same topics repeatedly, it may be beneficial to keep the nodes around, to avoid the need for locks to recreate them. If you know that retained messages come and go within a certain period, it's benificial to set this value so that no unnecessary node destruction and creation takes place.
Default value:
0 - ≥ v1.15.1
subscription_node_lifetimeseconds# -
The grace period after which a subscription node is eligible for deletion. The subscription 'one/two/three' is three nodes.
FlashMQ will periodically clear our nodes in the subscription tree that have no entries anymore. This is required to save memory. But, when clients place the same subscriptions repeatedly, it may be beneficial to keep the nodes around, to avoid the need for locks to recreate them. If you know that certain subscription patterns come and go within a certain period, it's benificial to set this value so that no unnecessary node destruction and creation takes place.
Default value:
3600 - ≥ v1.2.0
websocket_set_real_ip_frominet4_address|inet6_address# -
HTTP proxies in front of the websocket listeners can set the
X-Real-IPheader to identify the original connecting client. Withwebsocket_set_real_ip_fromyou can mark IP networks as trusted. By default, clients are not trusted, to avoid spoofing.You can repeat the option to allow for multiple addresses. Valid notations are
1.2.3.4,1.2.3.4/16,1.2.0.0/16,2a01:1337::1,2a01:1337::1/64, etc.The header
X-Forwarded-Foris not used, because that's designed to contain a list of addresses, if applicable.As a side note about using a proxy on your listener; you can only have an absolute max of 65535 connections to an IP+port combination (and the practical limit is lower). If you need more, you have to set up multiple listeners. This can be multiple IP addresses, or simply multiple ports.
-
When having multiple subscribers on a shared subscription (like '$share/myshare/jane/doe'), select how the messages should be distributed over the subscribers.
round_robin. Select the next subscriber for each message. There is still some amount of randomness to it because the counter for this is not thread safe. Using an atomic/mutexed counter for it would just be too slow to justify.sender_hash. Selects a receiver deterministically based on the hash of the client ID of the sender. The selected subscriber will depend on how many subscribers there are, so if some disconnect, the distribution will change. Moreover, the selection may also change when FlashMQ cleans up empty spaces in the list of shared subscribers.first. Selects the first subscriber in the list. This mode can be useful for fallback. When one client disappears, the other will seamlessly take over.Default:
round_robin - ≥ v1.9.0
minimum_wildcard_subscription_depthnumber# -
Defines the minimum level of the first wildcard topic filter (
#and+). In a topic filter likesensors/temperature/#, that is 2. If you specify 2, a subscription tosensors/#will be denied. Remember that only MQTT 3.1.1 and newer actually notify the client of the denial in the sub-ack packet.The reason you may want to limit it, is performance. If you have a base message load of 100,000 messages per second, each client subscribing to
#causes that many permission checks per second. If you have 100 clients doing that, there will be 10 million permission checks per second.Default:
0 - ≥ v1.9.0
wildcard_subscription_deny_modedeny_all|deny_retained_only# -
For
minimum_wildcard_subscription_depth, specify what you want to deny. Trying to give a client all retained messages can cause quite some load, so only denying the retained messages upon receiving a broad wildcard subscription can be useful if you have a low enough general message volume, but a high number of retained messages.Default:
deny_all - ≥ v1.12.0
overload_modelog|close_new_clients# -
Define the action to perform when the value defined with
max_event_loop_driftis exceeded.When a server is (re)started, and hundreds of thousands of clients connect, the SSL handshaking and authenticating can be so heavy that it doesn't get to clients in time. They will then reconnect and try again, and get stuck in a loop. This option is to mitigate that. With
close_new_clients, new clients will be closed immediately after connecting while the server is overloaded. This will allow the worker threads to process the new clients in a controlled manner.For really large deployments, this can be augmented with extra rate limiting in iptables, or other firewalls. A stateless method is preferred, like:
iptables -I INPUT -p tcp -m multiport --dports 8883,1883 --syn -m hashlimit --hashlimit-name newmqttconns --hashlimit-above 10000/second --hashlimit-burst 15000 -j DROPThe current default is
log, but that will likely change in the future.Default:
log - ≥ v1.12.0
max_event_loop_driftmilliseconds# -
For
overload_mode, the maximum permissible thread drift before the overload action is taken.The drift values considered are those of the main loop, in which clients are accepted, and the median of all worker threads.
Default:
2000 - ≥ v1.7.0
include_dir/path/to/dir# -
Load *.conf files from the specified directory, to merge with the main configuration file.
An error is generated when the directory is not there. This is to protect against running incorrect configurations by accident, when the dir has been renamed, for example.
- ≥ v1.18.0
subscription_identifiers_enabledtrue|false# -
Subscription identifiers allow clients to see which subscription was responsible for a message. Publish messages will contain the identifier included in the original subscription.
Enabling will prevent FlashMQ from using optimizations involving packet reuse, because the packets are unique per client when it contains a subscription identifier. Therefore you may want to assess the performance difference in high message volume deployments.
As per the spec, clients sending subscription identifiers when the server reported the feature as unavailable will cause them to be disconnected. This has the side effect that changing this setting on a running server will disconnect clients when they send a subscription with an identifier in it. This was chosen as behavior over the alternatives, because of simplicity and operator control (otherwise it can't be turned off at all for existing clients).
Default value:
true
Listen parameters
Listen parameters can only be used within listen { } blocks.
port#-
The default port depends on the
protocolparameter and whether or notfullchainandprivkeyparameters are supplied:-
For unencrypted MQTT, the default port is
1883 -
For encrypted MQTT, the default port is
8883 -
For plain HTTP websockets, the default port is
8080 -
For encrypted HTTPS websockets, the default port is
4443
-
protocolmqtt|websockets|acme#-
This is a required parameter.
For
acme, see acme_redirect_url. inet_protocolip4_ip6|ip4|ip6|unix#-
When using
unix, aunix_socket_pathis required.Default:
ip4_ip6 inet4_bind_addressinet4address#-
Default: 0.0.0.0
inet6_bind_addressinet6address#-
Default: ::0
- ≥ v1.22.0
unix_socket_pathpath# -
When using
unixforinet_protocol, the file path of the socket.FlashMQ will remove pre-existing socket files if they already exist.
- ≥ v1.23.0
unix_socket_useruser# -
Use this to set the owner of the socket. It will always be attempted to set it, but a warning may be logged if not successful. Users may be specified as numeric or names.
A config test will not verify the existence of users, for portability.
- ≥ v1.23.0
unix_socket_groupgroup# -
Use this to set the group of the socket. It will always be attempted to set it, but a warning may be logged if not successful. Groups may be specified as numeric or names.
A config test will not verify the existence of groups, for portability.
- ≥ v1.23.0
unix_socket_modemode# -
Use this to specify the permission mode of the unix socket, like
600. fullchain/foobar/server.crt#-
Specifying a chain makes the listener SSL, and also requires the
privkeyto be set. privkey/foobar/server.key#-
Specifying a private key makes the listener SSL, and also requires the
fullchainto be set. - ≥ v1.20.0
minimum_tls_versiontlsv1.1|tlsv1.2|tlsv1.3# -
Set minimum supported TLS version for TLS listeners. Note that setting this value low many not actually enable that protocol version if OpenSSL won't support it (anymore).
The TLS version clients use is logged.
Default:
tlsv1.1 - ≥ v1.8.0
client_verification_ca_file/foobar/client_authority.crt# -
Clients can be authenticated using X509 certificates, and the username taken from the CN (common name) field. Use this directive to specify the certificate authority you trust.
Specifying this or
client_verification_ca_dirwill require the listener to be TLS. - ≥ v1.8.0
client_verification_ca_dir/foobar/dir_with_certificates# -
Clients can be authenticated using X509 certificates, and the username taken from the CN (common name) field. Use this directive to specify the dir containing certificate authorities you trust.
Note that the filename requirements are dictated by OpenSSL. Use the utility
openssl rehash /path/to/dir.Specifying this or
client_verification_ca_filewill require the listener to be TLS. - ≥ v1.8.0
client_verification_still_do_authntrue|false# -
When using X509 client authentication with
client_verification_ca_fileorclient_verification_ca_dir, the username will not be checked with a user database or a plugin by default. Set this option totrueto override that. - ≥ v1.22.0
acme_redirect_urlhttp://example.com/# -
This allows an ACME (automated certificate management environment) challenge to be redirected elsewhere. This allows decoupling of the certificate creation from the host(s) that run FlashMQ.
This can either be configured on a dedicated listener with
protocolacme, or multiplexed on a non-SSLmqttorwebsocketslistener. - ≥ v1.22.0
drop_on_absent_certificatetrue|false# -
When both
privkeyandfullchainare absent, don't create this listener. This can help in situations where you don't have the certificate and key yet, but you are expecting them. - ≥ v1.22.0
only_allow_frominet4_address|inet6_address# -
When set, restricts the listener to the source address/network given.
You can repeat the option to allow multiple addresses/networks. Valid notations are
1.2.3.4,1.2.3.4/16,1.2.0.0/16,2a01:1337::1,2a01:1337::1/64, etc. - ≥ v1.22.0
deny_frominet4_address|inet6_address# -
Block connections from this address or network.
You can repeat the option multiple times. Valid notations are
1.2.3.4,1.2.3.4/16,1.2.0.0/16,2a01:1337::1,2a01:1337::1/64, etc. - ≥ v1.10.0
allow_anonymoustrue|false# -
This allows you to override the global
allow_anonymoussetting on the listener level. - ≥ v1.21.0
overload_modelog|close_new_clients# -
This allows you to override the global
overload_modesetting on the listener level. - ≥ v1.1.0
haproxytrue|false# -
Setting the listener to haproxy makes it expect the PROXY protocol and set client source address to the original client. Make sure this listener is private / firewalled, otherwise anybody can set a different source address.
Note that HAProxy's server health checks only started using the 'local' specifier as of version 2.4. This means earlier version will pretend to be a client and break the connection, causing log spam.
As a side note about using a proxy on your listener; you can only have an absolute max of 65535 connections to an IP+port combination (and the practical limit is lower). If you need more, you have to set up multiple listeners. This can be multiple IP addresses, or simply multiple ports.
See haproxy.org.
- ≥ v1.13.0
tcp_nodelaytrue|false# -
tcp_nodelaywill cause theTCP_NODELAYoption to be set for the listener's socket(s), and therefore for all clients accepted on that listener.TCP_NODELAYis a OS TCP-layer option that will cause messages written by FlashMQ to the socket to be flushed immediately, without letting Nagle's algorithm (the default) collect small outgoing TCP packets into bigger packets.Foregoing Nagle's algorithm by setting
tcp_nodelaytotruemay decrease latency, at the likely cost of some network efficiency.Default:
false - ≥ v1.22.0
max_buffer_sizenumber# -
Override the
client_max_write_buffer_sizefor this listener. This is especially useful when this listener is the receiving side of a bridge, because these clients will likely see more traffic. - ≥ v1.23.0
max_qosqos_value# -
Per-listener counterpart of
max_qos. - ≥ v1.23.0
mqtt3_qos_exceed_actiondrop|disconnect# -
Per-listener counterpart of
mqtt3_qos_exceed_action.
Example listeners#
listen {
protocol mqtt
inet_protocol ip4_ip6
inet4_bind_address 127.0.0.1
inet6_bind_address ::1
fullchain /foobar/server.crt
privkey /foobar/server.key
# default = 8883
port 8883
}
listen {
protocol mqtt
fullchain /foobar/server.crt
privkey /foobar/server.key
client_verification_ca_file /foobar/client_authority.crt
client_verification_still_do_authn false
}
listen {
protocol mqtt
inet_protocol ip4
# default = 1883
port 1883
}
listen {
protocol websockets
fullchain /foobar/server.crt
privkey /foobar/server.key
# default = 4443
port 4443
}
listen {
protocol websockets
# default = 8080
port 8080
}
listen {
port 2883
haproxy on
}
Bridge configuration#
Bridges can be defined inside bridge { } blocks. A bridge is essentially just an outgoing connection to another server with loop-detection and retain flag relaying. It is not a form of clustering, although with careful design, it can be deployed to achieve some sort of load balancing. Note that normally (unless connection_count is set) one bridge is one connection, and because FlashMQ's threading model is that clients are serviced by one selected thread only, a bridge has the potential to saturate a thread, if it's heavily loaded. You can improve that with connection_count.
Bridges are dynamically created, removed or changed upon config reload. When a bridge configuration changes, it will disconnect and reconnect.
- ≥ v1.7.0
addressaddress# -
The DNS name, IPv4 or IPv6 address of the server you want to connect to.
- ≥ v1.7.0
portnumber# -
The default port depends on the
tlsoption, either 1883 or 8883. - ≥ v1.7.0
inet_protocolip4_ip6/ip4/ip6# -
Default:
ip4_ip6 - ≥ v1.7.0
tlsoff/on/unverified# -
Set TLS mode. The value
unverifiedmeans the x509 chain is not verified. - ≥ v1.20.0
minimum_tls_versiontlsv1.1|tlsv1.2|tlsv1.3# -
Set minimum supported TLS version the bridge will negotiate with the other side. Note that setting this value low many not actually enable that protocol version if OpenSSL won't support it (anymore).
Default:
tlsv1.1 fullchain/foobar/bridge.crt#-
With TLS enabled, specifying a chain makes the bridge connection authenticate to the remote broker using a public certificate, and also requires the
privkeyto be set. privkey/foobar/bridge.key#-
With TLS enabled, specifying a private key makes the bridge connection to remote broker use that key, and also requires the
fullchainto be set. - ≥ v1.7.0
ca_filepath# -
File to be used for x509 certificate chain validation.
- ≥ v1.7.0
ca_dirpath# -
Directory containing certificates for x509 certificate chain validation.
- ≥ v1.7.0
protocol_versionmqtt3.1|mqtt3.1.1|mqtt5# -
Default:
mqtt3.1.1 - ≥ v1.7.0
bridge_protocol_bittrue|false# -
An unofficial standard is to set the most significant bit of the protocol version byte to 1 to signal the connection is a bridge. This allows the other side to alter its behavior slightly. However, this is not always supported, so you can disable this if you get disconnected for reporting an invalid protocol version.
This setting has no effect when using MQTT5, because the behavior it influences is done with subscription options.
Default:
true - ≥ v1.7.0
keepaliveseconds# -
The time between sending ping packets to the other side.
Default:
60 - ≥ v1.7.0
clientid_prefixprefix# -
The prefix of the randomly generated client ID. Client IDs cannot be explicitely set for security reasons. See Understanding clean session and clean start.
Default:
fmqbridge - ≥ v1.7.0
publishfilterqos# -
Messages matching this filter will be published to the other side. Examples:
#orsport/tennis/#. This option can be repeated several times.The QoS value should be seen as the QoS value of the internal subscription causing outgoing messages. Messages that are relayed have this QoS level at most.
Default:
0 - ≥ v1.7.0
subscribefilterqos# -
Subscriptions for this filter is placed at the other side. Examples:
#orsport/tennis/#. This option can be repeated several times.The QoS value is like any subscription at a server. Messages received by the other end will be given this QoS level at most.
Default:
0 - ≥ v1.7.0
local_usernameusername# -
Username as seen by the local FlashMQ's plugin or ACL checks. This is not always necessary.
- ≥ v1.7.0
remote_usernameusername# -
Username sent to the remote connection.
- ≥ v1.7.0
remote_passwordpassword# -
Password sent to the remote connection.
- ≥ v1.7.0
remote_clean_starttrue|false# -
In MQTT3, this means 'clean session', meaning the remote server removes any existing session with the same ID on (re)connect, and destroys it immediately on disconnect. If you want reuseable sessions that survive disconnects, set this to false. If you also want to pick up remote sessions on FlashMQ restart, set
use_saved_clientidto true.In MQTT5, this option only influences reconnection behavior. It essentially has no effect on the first connect, because the client ID is random and will always be new (except when you set
use_saved_clientid). But when set to true, any reconnects, which do use the already generated client ID, will destroy the session and in-flight messages will be lost.Also see understanding clean session and clean start.
Default value:
true - ≥ v1.7.0
local_clean_starttrue|false# -
In MQTT3 mode, this means 'clean session' and means the session is removed upon disconnect. If you want to reuse sessions on reconnect, set this to false. Any new start of FlashMQ will give you a new client ID so will always be a fresh session, except if you set
use_saved_clientid.In MQTT5 mode, this only has effect on start, where any existing local session is removed if found. If you want the session to be removed immediately on disconnect, use
local_session_expiry_intervalto 0.Also see understanding clean session and clean start.
Default value:
true - ≥ v1.7.0
remote_session_expiry_intervalseconds# -
Is only used in MQTT5 mode and determines the amount of seconds after which the session can be removed from the remote server.
Default value:
0 - ≥ v1.7.0
local_session_expiry_intervalseconds# -
Determines when a local session without an active client will be removed, in both MQTT3 and MQTT5 mode. Note that in MQTT3 mode, the session is removed on disconnect when
local_clean_startis true.Default value:
0 - ≥ v1.7.0
remote_retain_availabletrue|false# -
MQTT5 allows a server to tell a client it doesn't support retained messages, or has it disabled. When using MQTT3, use this option to achieve the same.
Messages will not be relayed with 'retained as published' and the retained messages that are normally sent on matching subscription, are not sent.
Default value:
true - ≥ v1.7.0
use_saved_clientidtrue|false# -
When you want your bridges to resume local and remote sessions after restart, set this to true and set
remote_clean_start,local_clean_start,remote_session_expiry_intervalandlocal_session_expiry_intervalaccordingly. It only has effect when you have set astorage_dirand includebridge_infoinpersistence_data_to_save.It is important to fully understand the clean session / clean start behavior and the role the client ID plays in that. The primary goal of sessions is to survive link disconnects. Configuring a fixed client ID and use that each time an MQTT client starts, is often an anti-pattern, because most clients like actual IoT devices start fresh upon restart and don't store their sessions (with in-flight packets, etc) to disk. FlashMQ does store it on disk however, so it can be used legitamately. However, you can run into unexpected situations. For instance, you will get your existing subscriptions from the session too. So, if you remove a
subscribeline from your bridge configuration and restart, it will actually have no effect, because the server on the other side still has that subscription in the session.See understanding clean session and clean start for details.
Default value:
false - ≥ v1.7.0
max_outgoing_topic_aliasesamount# -
If you want FlashMQ to initiate topic aliases for this bridge, set this to a non-zero value. Note that it's floored to the value the remote side gives in the CONNACK packet, so it only works if the other side permits it.
Default:
0 - ≥ v1.7.0
max_incoming_topic_aliasesamount# -
If you want to accept topic aliases for this bridge, set this to a non-zero value. The value is set in the CONNECT packet to inform the remote side of the wish. It's not guaranteed that the other side will actually make aliases.
Default:
0 - ≥ v1.13.0
tcp_nodelaytrue|false# -
tcp_nodelaywill cause theTCP_NODELAYoption to be set for the client socket that is used to connect to the other end of the bridge.See the documentation for the
tcp_nodelaylistener parameter for further elaboration.Default:
false - ≥ v1.19.0
local_prefixprefix# -
Prefixes can be used to remap topics to and from the other end of the bridge. This makes it possible to insert a topic tree into the topic tree on another server, like a shared one.
When a message comes in, the
remote_prefixis stripped from the topic, and thelocal_prefixis added. The resulting topic is used for authorization 'write' checking.When a message goes out, the opposite happens: the
local_prefixis stripped and theremote_prefixis added. However, this time, the original topic is used for authorization 'read' checking.The prefixes aren't applied to the
subscribeandpublishbridge options. You'll have to include the prefix in the subscriptions you configure. This is so that you can have multiple subscriptions to the other end, and only have the prefix applied to the relevant one(s). Messages that come in and go out that don't match the prefixes, are sent and received unchanged.The prefixes removal isn't done to topics that match the prefix exactly. This is to avoid
one/two/three/(which has a legal empty string as last subtopic), becoming an empty string (which is illegal).If you define a prefix, they are required to end with a
/. It's valid to have only a local or remote prefix. - ≥ v1.19.0
remote_prefixprefix# -
See
local_prefix. - ≥ v1.22.0
connection_countnumber|auto# -
Normally a bridge has one TCP connection to the other side. This means that dealing with bridge traffic is limited to one thread, which also applies to the remote side if that is also FlashMQ. With this option, you can make a bridge have multiple connections, and share the traffic load over them using MQTT5 'shared subscriptions'.
When you specify a
publishorsubscribepath ofone/two/three, the topic is adjusted to$share/RANDOM/one/two/threeto create a shared subscription so that load is balanced. With FlashMQ, load balancing is especially important for the side processing publishes (because each received publish packet means subscribers have to be looked up, auth checked, etc).The
shared_subscription_targetingmode is automatically set tosender_hash. This is required to ensure sequential message relaying (to retain ordering), and it's also better in plugin code when messages from one source are kept to one thread, as it would be under normal circumstances.If FlashMQ is also on the receiving end of these load balanced connections, it uses an extra feature to group clients of one bridge together to enhance loop detection. Normally MQTT5 supports the 'no-local' subscription option for that, but the standard states that is not allowed for shared subscriptions. FlashMQ uses 'user properties' to communicate the group they belong to, so that we can still do this kind of loop detection. This allows you to specify overlapping paths in the
subscribeandpublishoptions of a bridge. Note that both ends should use FlashMQ version 1.22.0 or higher.When the target server indeed is also FlashMQ, it may be smart to create a dedicated listener, for several reasons. One is that incoming connections are given to threads in a sequential order per listener, this ensures the best spread over worker threads. It also allows you to set
overload_mode,max_buffer_sizeand posssiblyonly_allow_fromanddeny_fromdifferently for that listener.You can specify an amount of connections, or
autofor one connection per CPU. FlashMQs load is mostly on the receiver of messages, soautowill likely be a good choice if most of your message load from the other side is incoming, vs outgoing. Otherwise it's best matched to the other side's number of CPUs.Default:
1 - ≥ v1.22.0
max_buffer_sizenumber# -
Override the
client_max_write_buffer_sizefor this bridge. Whenconnection_countis used, this size applies to each connection individually.Bridges typically have more traffic than single clients, in which case it makes sense to increase this.
Example bridge#
bridge {
address demo.flashmq.org
publish send/this
subscribe receive/this
local_username my_local_user
remote_username my_remote_user
remote_password my_remote_pass
bridge_protocol_bit false
tls on
ca_file /path/to/ca.crt
}
Author
Wiebe Cazemier contact@flashmq.org.
See also
Colophon#
The sources for the FlashMQ manual pages are maintained in DocBook 5.2 XML files. The transformation to the multiple destination file formats is done using a bunch of XSLT 1.0 sheets, contributed to this project by Rowan van der Molen.