flashmq.conf (5)
FlashMQ configuration file format
Synopsis
The flashmq.conf
file is the configuration used for configuring the FlashMQ MQTT broker. It doesn't necessarily have to be called flashmq.conf
; the flashmq
daemon program sports a --config-file
parameter.
File format#
To set a parameter, its name must appear on a single line, followed by whitespace, followed by the parameter value.
parameter-name
parameter-value
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 (
.so
file) plugin interface to add functionality, authorization and authentication, because it’s hard to provide a declarative mechanism that works for everybody. Seeflashmq_plugin.h
for 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_file
andmosquitto_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_init
true/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_checks
true/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_period
seconds
#-
The FlashMQ auth plugin interface has a function that is called periodically this amount of seconds. This can be used to refresh state, commit data, etc.
See
flashmq_plugin.h
for details.Default value:
60
log_file
/path/to/flashmq.log
#-
This configuration parameter sets the path to FlashMQ's log file. If you omit the, the output will go to stdout.
Default value:
/var/log/flashmq/flashmq.log
log_debug
true/false
#-
Debug logging obviously creates a lot of log noise, so should only be done to diagnose problems.
Default value:
false
log_subscriptions
true/false
#-
Default value:
false
allow_unsafe_clientid_chars
true/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_chars
true/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_size
bytes
#-
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_size
to limit memory use.Default value:
268435461
client_max_write_buffer_size
bytes
#-
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.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_size
bytes), room will be made up to twice their size. So, you may also want to reducemax_packet_size
from the default.Default value is
1048576
(1 MB) client_initial_buffer_size
bytes
#-
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_size
andmax_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_anonymous
true/false
#-
Default value:
false
rlimit_nofile
number
#-
The general Linux default of
1024
can be overridden. Note:systemd
blocks 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=10000000
Default value:
1000000
expire_sessions_after_seconds
seconds
#-
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
quiet
true/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.
Default value:
false
storage_dir
/path/to/dir
#-
Location to store sessions, subscriptions and retained messages. Not specifying this will turn off persistence.
max_qos_msg_pending_per_client
max_qos_bytes_pending_per_client
#-
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.
Defaults:
max_qos_msg_pending_per_client 512
max_qos_bytes_pending_per_client 65536
max_incoming_topic_alias_value
number
#-
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
max_outgoing_topic_alias_value
number
#-
FlashMQ will make this many aliases per MQTT5 client, if they ask for aliases (with the connect property
TopicAliasMaximum
).Default value:
65535
thread_count
number
#-
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_enabled
true/false
#-
When disabled, the server will not set last will and testament specified by connecting clients.
Default value:
true
retained_messages_mode
enabled/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.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_seconds
seconds
#-
Use this to limit the life time of retained messages. Without this, the amount of retained messages may never decrease.
Default value:
4294967296
expire_retained_messages_time_budget_ms
milliseconds
#-
When purging the retained messages tree, spend a maximum of this many milliseconds on it. The purge requires a write lock, so you don't want to hold up everything too long.
Currently, the purge frequency is 3949193 milliseconds, but this is subject to change.
Default value:
200
retained_messages_delivery_limit
number
#-
When clients place a subscription, they will get the retained messages matching that subscription. However, if you have millions, clients subscribing to '#' will cause a heavy load. Use this setting to limit to what you need/expect.
Note that clients will also have (buffer) limits, so even if you set this high, clients may drop messages as well.
Default value:
2048
websocket_set_real_ip_from
inet4_address/inet6_address
#-
HTTP proxies in front of the websocket listeners can set the
X-Real-IP
header to identify the original connecting client. Withwebsocket_set_real_ip_from
you 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-For
is 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.Default:
round_robin
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.
Listen parameters
Listen parameters can only be used within listen { }
blocks.
port
#-
The default port depends on the
protocol
parameter and whether or notfullchain
andprivkey
parameters 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
protocol
#-
Valid values:
mqtt
,websockets
inet_protocol
#-
Valid values:
ip4_ip6
,ip4
,ip6
Default: ip4_ip6
inet4_bind_address
inet4address
#-
Default: 0.0.0.0
inet6_bind_address
inet6address
#-
Default: ::0
fullchain
/foobar/server.crt
#-
Specifying a chain makes the listener SSL, and also requires the
privkey
to be set. privkey
/foobar/server.key
#-
Specifying a private key makes the listener SSL, and also requires the
fullchain
to be set. 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_dir
will require the listener to be TLS. 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_file
will require the listener to be TLS. client_verification_still_do_authn
true/false
#-
When using X509 client authentication with
client_verification_ca_file
orclient_verification_ca_dir
, the username will not be checked with a user database or a plugin by default. Set this option totrue
to override that. haproxy
true/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.
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. Also note that 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 could work around that by defining multiple bridges to the same server, for various topic paths. A future version of FlashMQ will likely improve upon this.
address
address
#-
The DNS name, IPv4 or IPv6 address of the server you want to connect to.
port
number
#-
The default port depends on the
tls
option, either 1883 or 8883. inet_protocol
ip4_ip6/ip4/ip6
#-
Default:
ip4_ip6
tls
off/on/unverified
#-
Set TLS mode. The value
unverified
means the x509 chain is not verified. ca_file
path
#-
File to be used for x509 certificate chain validation.
ca_dir
path
#-
Directory containing certificates for x509 certificate chain validation.
protocol_version
mqtt3.1/mqtt3.1.1/mqtt5
#-
Default:
mqtt3.1.1
bridge_protocol_bit
true/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
keepalive
seconds
#-
The time between sending ping packets to the other side.
Default:
60
clientid_prefix
prefix
#-
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
publish
filter
#-
Messages matching this filter will be published to the other side. Examples:
#
orsport/tennis/#
. This option can be repeated several times. subscribe
filter
#-
Subscriptions for this filter is placed at the other side. Examples:
#
orsport/tennis/#
. This option can be repeated several times. local_username
username
#-
Username as seen by the local FlashMQ's plugin or ACL checks. This is not always necessary.
remote_username
username
#-
Username sent to the remote connection.
remote_password
password
#-
Password sent to the remote connection.
remote_clean_start
true/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_clientid
to 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
local_clean_start
true/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 has no effect. If you want the session to be removed immediately on disconnect, use
local_session_expiry_interval
to 0.Also see understanding clean session and clean start.
Default value:
true
remote_session_expiry_interval
seconds
#-
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
local_session_expiry_interval
seconds
#-
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_start
is true.Default value:
0
remote_retain_available
true/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
use_saved_clientid
true/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_interval
andlocal_session_expiry_interval
accordingly. It only has effect when you have set astorage_dir
.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
subscribe
line 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
max_outgoing_topic_aliases
amount
#-
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
max_incoming_topic_aliases
amount
#-
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
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
flashmq(1)