How to Configure Mosquitto MQTT Broker in Docker
An MQTT broker (sometimes referred to as an MQTT server) is an intermediary between MQTT clients that publish messages and subscribers that receive them. All published messages first go to the broker before reaching the subscribers. The broker receives those messages, filters them by topics, and distributes them among subscribers.
Many industries widely use MQTT brokers in IoT (Internet of Things), smart home automation systems, Cloud platforms, mobile Internet, Internet of Vehicles, industrial manufacturing, energy, and other areas.
In this tutorial, I will guide you through installing and configuring the Mosquitto™ MQTT broker Docker container on Windows, Linux, and macOS operating systems and show you how to test it.
How to install and configure Mosquitto MQTT broker in Docker from scratch
This article will use the Eclipse Mosquitto open-source MQTT broker, which implements MQTT protocol version 5, 3.1.1, and 3.1. The free version of the broker is available for Windows 10 and 11, Linux, and macOS as a native package. However, this article will focus on a cross-platform setup with Docker. If you want to explore installing a Pro Edition for Eclipse Mosquitto™ using Docker, check out this “How to Install Mosquitto on Ubuntu Linux” guide. While it details the required installation steps for Ubuntu Linux, the same steps will work for any other operating system.
Now, let’s proceed with the open-source version of the broker. For the installation process, I will use the official eclipse-mosquitto image.
Sign up for a Cedalo MQTT Platform trial to experience Pro Mosquitto MQTT broker functionality. Get access to advanced broker and client monitoring, role-based user management, rich integrations, and more.
Installing and configuring the Mosquitto Docker container is a uniform process across different operating systems. This ensures a consistent experience regardless of your platform. Prerequisites: you must have Docker installed (Windows users must install Docker Desktop application unless the installation happens under WSL).
Installation on Windows, Linux, or macOS using Docker
In order to install the MQTT broker, run the following command:
docker run -it -d --name mos1 -p 1883:1883 -v $HOME/mosquitto.conf:/mosquitto/config/mosquitto.conf
eclipse-mosquitto:2
The specified commands have several options:
-it
keeps the container’s virtual terminal open in interactive mode. This allows it to attach to it and access the container later.--name
assigns a name to the Docker container. You can use the name specified after this option (in our case,mos1
) to identify the container, access it, or perform other docker commands.-p 1883:1883
maps a port on your host machine (Docker host) to a container port. If port 1883 on the Docker host is busy, you can use another port, for example-p 18883:1883
. By convention, MQTT uses port 1883 as a default non-TLS listener. However, you can change this or add more listeners for other types of traffic.- For example, you may add another
-p
to map port 9001 for Websocket protocol (-p 9001:9001
) and/or map 8883 to 8883 for the MQTTS listener. You can map as many ports as you need. But by default,-p
maps all host network interfaces to the container. This means, it maps 0.0.0.0:1883 from your host to 0.0.0.0:1883 of your container. This will directly open the port on your machine for external connections unless you have a firewall. If you need to, you can specify which particular interface of your Docker host to map to. For example:-p 127.0.0.1:1883:1883
to map to your host machine’s localhost (127.0.0.1) interface.
- For example, you may add another
-v
mounts volumes. It links (maps) local files/folders to the container’s files/folders. You can also chain multiple-v
flags to create multiple volumes.-d
runs the container as a daemon (in the background).
eclipse-mosquitto is the name of the Dockerhub Mosquitto image that will be used as the container’s blueprint. The :2 is an image tag, meaning it will download the latest 2.x.x Mosquitto image (currently 2.0.21).
Running the above command for the first time downloads the eclipse-mosquitto:2 image from Dockerhub and starts it.
Command -v $HOME/mosquitto.conf:/mosquitto/config/mosquitto.conf
maps a configuration file mosquitto.conf from your Docker host to the container. Basically, your host machine and the docker container will share this file. So, any changes you perform on this local file will also apply to that same file inside the container.
I’ll use the path $HOME/mosquitto.conf
as an example. The environment variable $HOME should expand to your user’s home directory (e.g. /home/myuser
) on Unix systems such as Linux or macOS. You can change the path, but ensure it exists (together with the mosquitto.conf file, which can remain empty for now). The path to the file in the container (i. e. /mosquitto/config/mosquitto.conf
) should stay the same as in the example.
If you plan to add more volumes, map them to the /mosquitto
directory inside the container. For example: -v $HOME/dir:/mosquitto/dir
or $HOME/my/long/path/to/something:/mosquitto/something
. Mapping to the /mosquitto
directory specifically will mitigate potential permission issues because the Eclipse Mosquitto container’s entrypoint script ensures that the mosquitto user, which also runs the broker, owns everything within the /mosquitto
directory.
Note:
- For Windows, change the path to Windows format like:
C:\mosquitto\mosquitto.conf
I also recommend avoiding any users or groups on your Linux or macOS system with UID or GID 1883. The mosquitto user and group uses this id inside the Docker container. Mixing these IDs could cause issues. For more information on “Troubleshooting Mosquitto MQTT Broker Docker container,” refer to the “Conflicting UIDs and GIDs inside and outside of the container” section.
After starting the Docker Mosquitto container with the command above, the broker will run and open its default listener.
However, by default Mosquitto is configured not to accept external connections. It is started in local-only mode, so it will only be available inside the container at mqtt://127.0.0.1:1883. This basically means that you will be able to access your broker only after entering the container. You can of course change this if you add some configuration to the mosquitto.conf file that you mapped. I will explore how this file can be configured in the sections below. The simplest but least secure configuration is just adding allow_anonymous true
to the config file.
Note that the local-only mode applies to Mosquitto version 2.0.0 and higher. The older versions will listen on all network interfaces directly.
Before diving into the next section and exploring the authentication settings needed for the broker’s proper operation, I will go over a few docker commands that will be useful for managing the container.
To attach to the container, i.e., enter the filesystem of the created Mosquitto container, consider the following command:
docker exec -it mos1 sh
By default, you will attach to a container as a root user. However, for the eclipse-mosquitto image, we recommend entering the container under the mosquitto
user, which runs the broker. This will minimize the risk of getting permission or ownership issues if you modify any files in the container. The mosquitto
user has the UID (user id) 1883, so to enter a container as this user, run the command below:
docker exec -it -u 1883 mos1 sh
To exit from the container, enter exit
.
If you are an advanced Docker user and want to look at the broker’s Dockerfile – refer to the Eclipse Mosquitto Github repository.
If you want to deploy Mosquitto at scale using a container orchestration system,check out this article explaining how to configure Mosquitto MQTT broker in Kubernetes.
Other useful Docker commands
To verify that the container is running, use the command:
docker ps -a
Find your Mosquitto container by its name or id and check its status.
If the container is not running, you can find the reasons in the Docker logs:
docker logs <container name or id>
// in our case the container name is mos1
For example:
docker logs mos1
You can stop the Mosquitto MQTT Docker container using the following command:
docker stop <container name or id>
To start the container, use the following command:
docker start <container name or id>
To restart the container, use the following:
docker restart <container name or id>
Typically to reload configuration you would have to restart the docker container as shown above, but Mosquitto broker is able to reload the configuration upon receiving SIGHUP
signal. To send a SIGHUP
to the container, run:
docker kill --signal=SIGHUP <container name or id>
Run the following command to delete the container:
docker rm <container name or id>
To delete the downloaded image, run:
docker rmi <image name or id>
For example:
docker rmi eclipse-mosquitto:2
Mosquitto MQTT Docker authentication settings
You can keep your MQTT broker open – but then any device on your network can reach your Mosquitto server, post messages and subscribe to topics.
To achieve the above and allow external anonymous connections (i.e., without using a dedicated Mosquitto user), you can add the following to the configuration file (mosquitto.conf
which you mapped into the container):
allow_anonymous true
listener 1883 0.0.0.0
The lines above define an anonymous listener that listens on all available network interfaces on port 1883. If you mapped the ports with the -p
option when running the docker run command as described earlier, this listener will be available to your host machine at mqtt://0.0.0.0:1883
. This means your broker will also be available to the outside world at port 1883 of your host machine (note that you might have to ensure that your firewall does not block this port if you want it to be freely externally accessible).
It is possible to omit the IP address (0.0.0.0
) in the listener above, but it is recommended to leave it to be more explicit.
Now, to allow config file changes to take effect, restart the container. This can be done by issuing the docker restart mos1
command or docker kill --signal=SIGHUP mos1
to dynamically reload the config without restarting. After that your broker should be functional and be able to accept connections from the outside. You can check the Docker container logs to see if there are no errors (docker logs mos1
).
It is important to be very careful with anonymous connections. If you want to achieve higher security, do not allow this setting and connect only using authentication. This will require clients to enter the correct username and password to write or read messages from the broker.
To set up authentication, first, attach to the container with docker exec -it -u 1883 mos1 sh
and create a password file. Run the following command to create the file and add an initional user to it (note that /mosquitto/passwd_file
can be changed to a different path. You can also create a password file inside a mapped volume if you need to persist the changes after deleting the broker container):
mosquitto_passwd -c /mosquitto/passwd_file user_name
After that, you will be asked to enter the password for the user you have created and confirm it. For security reasons, the password you enter will not be visible. Once you press enter, your password will be set.
- To add more users to the password file, use the
mosquitto_passwd -b /mosquitto/passwd_file user_name password
command. - If you want to remove a user, run:
mosquitto_passwd -D /mosquitto/passwd_file user_name
Now, add the following settings to the mosquitto.conf configuration file (and make sure any unsafe anonymous mode settings (i.e. allow_anonymous true
) presented earlier have been deleted):
password_file /mosquitto/passwd_file
allow_anonymous false
listener 1883 0.0.0.0
The parameter allow_anonymous false
prevents unauthenticated clients from connecting to the broker. This parameter is set to false
by default, but it’s always a good idea to mention it explicitly.
Now exit the container using the exit
command and restart it with docker restart mos1
. After that, your changes should be applied to the broker. You should now be able to access it from outside and test the basic operations using MQTT clients (basic functionality testing is explored in the subsequent sections of the article).
Alternatively, create a password file on your docker host and map it inside the container (-v
option of the docker run command). You would have to install the mosquitto_passwd
utility onto your Docker host for this.
To install mosquitto_passwd
on Linux, you can typically run yum install mosquitto-clients
or apt install mosquitto-clients
, depending on your distribution.
For macOS: run brew install mosquitto
. Note that you need to have brew package manager installed first. However, together with the mosquitto_passwd
tool, this command will also install the Mosquitto broker itself on your host machine.
For Windows: install Mosquitto from here and find the mosquitto_passwd
executable in the installation directory.
After installing mosquitto_passwd
, you can use the same commands to create a password file as shown earlier. mosquitto.conf file changes should be the same as in the example above.
When mapping a password file from your host machine into the docker container, see the following command for reference:
docker run -it -d --name mos1 -p 1883:1883 -v $HOME/mosquitto.conf:/mosquitto/config/mosquitto.conf -v $HOME/passwd_file:/mosquitto/config/passwd_file
eclipse-mosquitto:2
Again, I recommend mounting all your files and directories into the /mosquitto
directory in the container (as done in the example command above) to avoid potential permission issues.
You may also refer to the following docs page about Mosquitto authentication methods.
Note that for enhanced security, it is also recommended to set up a TLS Mosquitto listener (also called the MQTTS listener), which should be added to the mosquitto.conf file. By convention, MQTTS listeners use port 8883. Be aware that you must also add more configuration and set up certificates. The section below demonstrates the basic setup of an MQTTS listener, but for more detailed instructions on obtaining valid certificates, refer to this article.
How to set up persistent storage and logging to a file for Mosquitto Docker Container
Inside the container are three special directories for configuration, permanent storage of data, and logging:
/mosquitto/config
/mosquitto/data
/mosquitto/log
As you have already seen, /mosquitto/config
is used for storing configuration like mosquitto.conf. Now, two other directories (/mosquitto/data
and /mosquitto/log
) are the go-to places for storing persistent data and logs, respectively.
If you want persistent storage and logging for your Mosquitto broker, add the following lines to the beginning of the mosquitto.conf configuration file under the $HOME
directory that you mounted when creating the container.
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
Logs will be stored in /mosquitto/log/mosquitto.log
, and all the broker data in the /mosquitto/data/
directory. Note that after applying the directives above, Mosquitto will redirect the logs exclusively to the specified file and will no longer output them to the console. This means you won’t be able to inspect them using the docker logs <container name or id>
command. However, if you also want to use this command to view the logs, then add the following to mosquitto.conf right after log_dest file
directive:
log_dest stdout
If you want to specify which log types to log, then you can do so by including several log_type
directives with the desired log types:
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
Possible values for log_type
are: debug
, error
, warning
, notice
, information
, subscribe
, unsubscribe
, websockets
, none
, and all
. The default values are: error
, warning
, notice
, and information
.
Now that you have learned to configure data and logs, make dedicated volumes for them. To do this, when executing the docker run command, add two -v
flags with <host machine path to data directory>:/mosquitto/data/
and <host machine path to log directory>:/mosquitto/log
.
If you have already started the Mosquitto container before, you must stop and delete it with docker stop mos1
and then docker rm mos1
. Afterward, run a fresh docker run command with more volumes.
Here is an example which extends the docker run command introduced in the beginning:
docker run -it -d --name mos1 -p 1883:1883 -v $HOME/mosquitto.conf:/mosquitto/config/mosquitto.conf -v $HOME/data:/mosquitto/data -v $HOME/log:/mosquitto/log
eclipse-mosquitto:2
For additional information on logging in the Mosquitto MQTT broker, check out this article.
Example Mosquitto configurations (mosquitto.conf files)
Below is a very basic mosquitto.conf file example, which contains recommended settings from the sections above and some additional ones.
Feel free to take a look at the default mosquitto.conf for a detailed explanation of every option I have discussed so far and more.
You can also find a complete list of configuration options for the mosquitto.conf file in this documentation.
Basic mosquitto.conf file example:
persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
password_file /mosquitto/passwd_file
allow_anonymous false
# MQTT Default listener
listener 1883 0.0.0.0
# MQTT over WebSockets
listener 9001 0.0.0.0
protocol websockets
The file above defines an MQTT listener on port 1883 and a WebSocket listener on port 9001. It uses persistent data, writes logs to the console and a file, restricts anonymous access, and uses authentication with a password file for both listeners.
Try the following configuration, if you want to define an MQTTS listener with certificates (MQTT over TLS):
persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
password_file /mosquitto/passwd_file
allow_anonymous false
# MQTT Default listener
listener 1883 0.0.0.0
# MQTT over WebSockets
listener 9001 0.0.0.0
protocol websockets
# MQTT over TLS
listener 8883 0.0.0.0
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key
Below is another mosquitto.conf if you additionally want to use WebSockets over TLS:
persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
password_file /mosquitto/passwd_file
allow_anonymous false
# MQTT Default listener
listener 1883 0.0.0.0
# MQTT over WebSockets with TLS
listener 9001 0.0.0.0
protocol websockets
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key
# MQTT over TLS
listener 8883 0.0.0.0
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key
How to use Mosquitto MQTT Broker Docker-Compose setup
To avoid entering a long docker run command every time you start a container, you can use a docker-compose.yml file. It allows you to define the docker containers you need to run as services and requires a simple docker-compose up command to start everything up. This approach is especially useful for setup automation and standardization.
You must first install docker-compose (for Windows it is typically installed together with Docker Desktop by default). Then create a docker-compose.yml file with the following content:
version: '3.8'
services:
mosquitto:
image: eclipse-mosquitto:2
ports:
- 1883:1883
- 8883:8883
- 9001:9001
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
networks:
- mosquitto
networks:
mosquitto:
name: mosquitto
driver: bridge
Save your mosquitto.conf file in ./mosquitto/config
directory or choose a different path (and modify the compose file accordingly).
Remember that paths before the :
in the volumes section of the file are the paths of your host machine. You can adjust them as needed. The example above references mosquitto/* paths under the current directory (indicated by the dot in the beginning), where docker-compose.yml file was created.
Then run the following command from the directory with docker-compose.yml file to start Mosquitto in the detached mode (in the background):
docker-compose up -d
The name of the container will be the project name (which by default is the name of the directory where the docker-compose file is located), followed by the name of the service (i.e., mosquitto as per the example file above) and the instance number (relevant if you have scaled a service, the instance number equals “1” by default). For example: mosquitto_dir_mosquitto_1
(if docker-compose.yml is located in $HOME/mosquitto_dir/
).
If you want to change the project name (i.e., the first part of the container name), then specify a COMPOSE_PROJECT_NAME environment variable or use a -p
command line argument (e.g., docker-compose -p <your project name here> up -d
).
Note that if you are using the -p
flag, you must also use it when stopping docker compose (i.e., docker compose -p <your project name here> down
) .
If you want to set an entirely custom name for the container, add a property container_name (e.g., container_name: mos1) on the same level as image and ports properties right under mosquitto service entry.
Note: if you get an error saying “Version in ./docker-compose.yml is unsupported.
” or similar, consider lowering the version property in the docker-compose file from 3.8 to 3.7 or lower.
To shut down the container and delete it, execute the following command from the directory with the docker-compse.yml file:
docker-compose down
You can add more services (containers) to your compose file.
How to test the Mosquitto docker configuration
You can use any MQTT client to test the broker’s correct operation. In this article, I wil show the usage of mosquitto_pub and mosquitto_sub command line utilities and then explore a programming an MQTT client using Paho Python Client library, which provides a client class with all the necessary functionality for publishing messages and subscribing to topics..
Alternatively, you can also use a UI tool called MQTT Explorer. However, we will not describe this tool here.
Testing with mosquitto_pub mosquitto_sub
If you are using Linux, you can install mosquitto_pub and mosquitto_sub tools by installing the mosquitto-clients package.
For Windows, download the executables for these commands together with Mosquitto for Windows from here. mosquitto_pub and mosquitto_sub will be stored in the installation directory.
For macOS – install the mosquitto package using brew install mosquitto
.
Publish
Run one of the commands below by replacing <username> and <password> with credentials you created for the broker user earlier, or omit -u and -P options altogether if you are using anonymous connections.
If you are on Linux or macOS:
for i in {1..10}; do (mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: $i" -u <username> -P <password> -d & sleep 1); done
If you are on Windows and are using PowerShell, run the following:
1..10 | ForEach-Object { mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: $_" -u <username> -P <password> -d; Start-Sleep -Seconds 1 }
And for Windows Command Prompt (cmd), use the command below:
for /L %i in (1,1,10) do (mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: %i" -u <username> -P <password> -d & timeout /t 1)
Note that to run mosquitto_pub and mosquitto_sub commands on Windows, you will need to navigate inside the installation folder of your Mosquitto broker (unless you add this folder to the PATH
environment variable to make the utilities from this folder globally available). You may also need to replace mosquitto_pub and mosquitto_sub in
commands from above with .\mosquitto_pub
and .\mosquitto_sub
respectively.
If you run the above and there are no errors, this means that the publish worked. However, to ensure that your published messages reach the broker, you will need to subscribe another client to the broker and observe the published messages as described below.
Subscribe
Run the following command (regardless of your OS) in a new terminal, replacing <username> and <password> accordingly or omitting them:
mosquitto_sub -i mosq_sub1 -t "Test" -u <username> -P <password> -d
For the complete setup, run the mosquitto_pub again in a separate terminal and return to the terminal with mosquitto_sub. If you start seeing the messages published by mosquitto_pub, everything will work as expected. The expected output is as follows:
Message with ID 1
Message with ID 2
Message with ID 3
Message with ID 4
Message with ID 5
...
Testing with Paho Client
Now, I will show a more advanced approach of programming our own MQTT client using Python. This example is not strictly relevant to the topic of setting up the broker itself but it explores more advanced concepts showing how your custom MQTT application could communicate with Mosquitto. This is also another alternative in case testing the broker with mosquitto pub sub commands or MQTT Explorer doesn’t work for you.
First, install Python and pip. Then, install the Paho Python Client using the following command:
pip install paho-mqtt
Publish
Import the Paho Python Client and “time” libraries.
import paho.mqtt.client as mqtt
import time
Then, add an on_connect callback to check whether we are connected to the broker or not.
def on_connect(client, userdata, flags, return_code):
if return_code == 0:
print("connected")
else:
print("could not connect, return code:", return_code)
Then, you need to initiate a connection with the broker by specifying its hostname and port and creating a client object with a unique identifier (in our example, it is Client1).
This example can be used with the “anonymous connections” setting, both enabled and disabled. If you use the username-password approach and have anonymous connections disabled, uncomment and edit the line with client.username_pw_set
in the code snippets below.
For proper and faster communication with the broker, start the Paho Client’s network loop by calling loop_start.
broker_hostname = "localhost"
port = 1883
client = mqtt.Client("Client1")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.connect(broker_hostname, port)
client.loop_start()
To publish messages, we will create a while loop. In this loop, we will publish a new message every second for 10 seconds to the topic defined by the topic variable. Then, check whether the message was published successfully and display the corresponding message on the screen. To disconnect the client and clean up the thread where the Paho Client’s network loop lives, add a try-finally block to call client.disconnect
and client.loop_stop
at the end.
topic = "Test"
msg_count = 0
try:
while msg_count < 10:
time.sleep(1)
msg_count += 1
result = client.publish(topic, msg_count)
status = result[0]
if status == 0:
print("Message "+ str(msg_count) + " is published to topic " + topic)
else:
print("Failed to send message to topic " + topic)
if not client.is_connected():
print("Client not connected, exiting...")
break
finally:
client.disconnect()
client.loop_stop()
The complete code example for publishing messages is as follows:
import paho.mqtt.client as mqtt
import time
broker_hostname = "localhost"
port = 1883
def on_connect(client, userdata, flags, return_code):
if return_code == 0:
print("connected")
else:
print("could not connect, return code:", return_code)
client = mqtt.Client("Client1")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.connect(broker_hostname, port)
client.loop_start()
topic = "Test"
msg_count = 0
try:
while msg_count < 10:
time.sleep(1)
msg_count += 1
result = client.publish(topic, msg_count)
status = result[0]
if status == 0:
print("Message "+ str(msg_count) + " is published to topic " + topic)
else:
print("Failed to send message to topic " + topic)
if not client.is_connected():
print("Client not connected, exiting...")
break
finally:
client.disconnect()
client.loop_stop()
Now you can run the script with python <path to your python file>
or python3 <path to your python file>
. The output in the console should look like this:
Message 1 is published to topic Test
Message 2 is published to topic Test
Message 3 is published to topic Test
Message 4 is published to topic Test
Message 5 is published to topic Test
Subscribe
Now, let’s create a subscriber. As in the previous example, import the Paho Python Client and the auxiliary standard library time.
import paho.mqtt.client as mqtt
import time
Add on_connect callback to be notified when the connection to the broker is established. To subscribe to a topic, add the client.subscribe(topic_name) call to that callback to ensure that clients subscribe only when the connection is established. If the connection fails, set a custom property failed_connect
on the client object to communicate this information to the main thread and exit the program earlier.
def on_connect(client, userdata, flags, return_code):
if return_code == 0:
print("connected")
client.subscribe("Test")
else:
print("could not connect, return code:", return_code)
client.failed_connect = True
Whenever the client receives a message from the broker, it invokes the on_message callback. So, to be able to view these messages, let’s define this callback function as shown below:
def on_message(client, userdata, message):
print("Received message: ",
str(message.payload.decode("utf-8")))
Then, like the previous example, create a new client, connect to a broker, and start a network loop with loop_start.
broker_hostname ="localhost"
port = 1883
client = mqtt.Client("Client2")
client.connect(broker_hostname)
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.on_message = on_message
client.failed_connect = False
client.loop_start()
Adding a timer will keep our subscribing client alive for 15 seconds in a try-finally block that calls client.disconnect
and client.loop_stop
in the end to do some cleanup. The “finally” clause will also be called if you decide to terminate the client midway with the “Ctrl + C” shortcut (or “Command +” for MacOS), which will generate an exception in Python.Additionally, if the connection to the broker has failed and therefore client.failed_connect
is true, the timer will not be executed, and we will immediately leave the program.
# this try-finally block ensures that whenever we terminate the program earlier by hitting ctrl+c, it still gracefully exits
try:
i = 0
while i < 15 and client.failed_connect == False:
time.sleep(1)
i = i + 1
if client.failed_connect == True:
print('Connection failed, exiting...')
finally:
client.disconnect()
client.loop_stop()
Below is the complete code for creating a client subscribing to messages on the “Test” topic.
import paho.mqtt.client as mqtt
import time
def on_connect(client, userdata, flags, return_code):
if return_code == 0:
print("connected")
client.subscribe("Test")
else:
print("could not connect, return code:", return_code)
client.failed_connect = True
def on_message(client, userdata, message):
print("Received message: ",
str(message.payload.decode("utf-8")))
broker_hostname ="localhost"
port = 1883
client = mqtt.Client("Client2")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.on_message = on_message
client.failed_connect = False
client.connect(broker_hostname, port)
client.loop_start()
# this try-finally block ensures that whenever we terminate the program earlier by hitting ctrl+c, it still gracefully exits
try:
i = 0
while i < 15 and client.failed_connect == False:
time.sleep(1)
i = i + 1
if client.failed_connect == True:
print('Connection failed, exiting...')
finally:
client.disconnect()
client.loop_stop()
If you have a specific topic that you want to subscribe to and test, then edit the client.subscribe("Test")
line from above. Otherwise, you can leave it unchanged.
To test the whole setup, first run the subscribe script and, in another terminal, publish the script from the previous section. You should then see the following output in your first terminal window:
Received message: 1
Received message: 2
Received message: 3
Received message: 4
Received message: 5
If you want to learn more about how to use the Paho MQTT client in Python, check out this article here.
Advantages of Pro Edition for Eclipse Mosquitto broker
In addition to the open-source version, the Pro Edition for Eclipse Mosquitto is also available and offers a number of advantages comparable to that of the open-source version (check out this PDF document to see a complete comparison between the open-source version of Mosquitto and the Pro Edition for Eclipse Mosquitto):
- Offers a set of powerful MQTT and REST APIs that allows Pro Mosquitto to integrate features into the software infrastructure of the customers’ systems, as well as help Mosquitto Management Center manage the broker.
- Support for advanced user management and permission control, use of client certificates and custom certificate authorities, application tokens, etc., to ensure data security.
- Advanced authentication methods such as JWT or LDAP.
- Deep inspection features provides a list of connected clients on a node, and detailed information about each MQTT client (status, protocol information, IP address, TLS encryption information, last-will messages, topics you subscribe to, and more).
- Persistent Queueing allows the MQTT broker to expand its storage capacity, while optimizing resource usage and facilitating scalability for future growth and higher message volumes.
- Numerous MQTT integrations, allowing the broker to establish seamless connections with Kafka, MongoDB, Azure Event Hubs, Google Pub/Sub, Google AlloyDB, MySQL, PostgreSQL, TimescaleDB, InfluxDB, Prometheus and others to enable advanced analysis, ensure optimal service performance, reliability, capacity planning, and rapid anomaly detection and response. For an in-depth walkthrough on exporting MQTT metrics data to Prometheus using Pro Mosquitto, check out this guide. You can also find a detailed guide on how to integrate Mosquitto MQTT Broker with MySQL.
- Many deployment options, including running Pro Mosquitto in Kubernetes, Docker, OpenShift, a native Pro Mosquitto RPM package and more.
Test advanced Pro Mosquitto MQTT broker functionalities with our free Cedalo MQTT Platform trial.
Troubleshooting Mosquitto MQTT Broker Docker container
Some errors may occur during the broker’s installation and configuration. Let’s address some of the most common ones below.
Incorrect $HOME variable expansion
If you are on a Unix system and are using the $HOME
environment variable to mount volumes, ensure your username doesn’t contain spaces (e.g., “/home/my user
“). If this is the case, enclose the $HOME
variable into double quotes to avoid mounting errors (e.g., "$HOME"/mosquitto.conf
).
As a rule, always enclose a path with double quotes if it contains spaces.
Address not available
After installing the Mosquitto MQTT docker image and starting the container, the “Address not available” error may occur.
Possible solutions:
- If you want to allow clients to connect to the broker without authorization, add the following settings to the configuration file:
allow_anonymous true
listener 1883
2. If you want to prevent unauthorized clients from connecting to the broker, then create a file that will contain the username and password and add the following lines to the configuration file:
password_file /mosquitto/passwd_file
allow_anonymous false
listener 1883
After that, restart the Docker container.
Address already in use
This error may mean that the specified port is already occupied or that Mosquitto is already running.
Possible solutions:
- Try uninstalling all previously running versions of Mosquitto.
- Find which application is occupying the port and try to terminate or kill it (for example, using netstat and kill or taskkill tools)
- Use a different port for the broker.
The client does not receive the expected messages
Possible reasons:
- Unstarted network loop loop_start() in case of Paho client.
- The callback function was not created or assigned to the client.
- The client is not subscribed to the correct topics, or an error occurred while creating the subscription.
- Broker’s access restriction policies apply (you may need to check your Mosquitto configuration).
Volumes don’t work for Windows
On Windows, users can experience problems with docker volumes where the volumes might not mount at all.
Possible solutions:
- Ensure that the paths are correct and are defined in the Windows format.
- Make sure that you have shared drives enabled in your Docker Desktop settings (however, this setting might not be available in some installations).
- Try installing docker directly onto the WSL without Docker Desktop and use it from the WSL.
Permission issues
The directories and files you map into your container (with -v
option) must be accessible by the mosquitto user and the mosquitto group that the broker is running as. You can usually identify this issue by the “Permission denied” message in the logs.
Usually, this problem should not arise if all your volumes are mounted into /mosquitto directory inside the Docker container. This is because before starting the broker, the Mosquitto Docker container sets the ownership of all the files and directories inside /mosquitto to the mosquitto user and group. However, if you are not mapping into the /mosquitto directory (which is not recommended), the possible solutions are:
- Manually ensure that the mosquitto user or group owns all of your mapped files and directories. Note that the default UID and GID for this user/group is 1883. So, to assign this ownership you may execute:
chown 1883:1883 /path/to/file/or/dir
. - Alternatively, you would have to expand the
o (others)
permission bit of your mapped files and directories (not recommended).
The described approaches work for Unix systems like Linux or macOS. For Windows, we strongly advise sticking to mappings into the /mosquitto directory on the container side.
Conflicting UIDs and GIDs inside and outside of the container
This problem is relevant for Unix systems.
As mentioned, the Mosquitto broker within the container runs under the mosquitto user with UID 1883. If you have a user on your host machine with the same UID this might lead to potential problems.
If you map any directories containing files owned by the host machine user with UID 1883, then from the container’s perspective, the mosquitto user will own those files and they will be accessible to Mosquitto. This might not pose a direct security vulnerability but might lead to confusion in some instances.
A more problematic situation could arise if the broker generates any files like log files, persistent data files, potentially a password file, etc. In this case, UID 1883 will own those files. This means that if you have a user on your system with the same UID, this user will be able to access those files even if you didn’t intend it. The same is true for a group with GID 1883.
For the reason above, I recommend avoiding having users and groups with UID or GID equal to 1883 when running the Mosquitto docker image.
Possible solutions:
1. You may create a custom Dockerfile which will extend the original eclipse-mosquitto:2 image and use usermod
and groupmod
commands to modify the UID and GID of the mosquitto user such that they are different from the ones from your host machine.
In this case, you would have to create a Dockerfile similar to the one below:
FROM eclipse-mosquitto:2
RUN apk add --no-cache shadow # install usermod and groupmod utilities with a "shadow" package
RUN usermod -u 9999 mosquitto # change GID 9999 to whatever UID you don't have on your system
RUN groupmod -g 9999 mosquitto # change GID 9999 to whatever GID you don't have on your system
RUN chown -R mosquitto:mosquitto /mosquitto # Update ownership of files owned by the mosquitto user from the original container
Then, you can build your custom image with the following:
docker build -t new_image_name
And then use new_image_name:latest
instead of eclipse-mosquitto:2
.
2. It’s crucial to note that you may prefer to change the UID and GID on your host machine rather than in the container. However, in such a case it’s important to exercise caution, as there might be a lot of potential pitfalls when altering the UIDs and GIDs of existing users or groups.
Below is the example command to achieve this. You should only use it if you have a complete understanding of what you are doing as well as potential consequences.
sudo usermod -u newUID username
sudo groupmod -g newGID groupname
After that, you should update the file ownership for all the files owned by the old UID and GID to the new ones:
sudo find / -user oldUID -exec chown -h newUID {} \;
sudo find / -group oldGID -exec chgrp -h newGID {} \;
Summary
In this article, I explained how to install and configure the open-source version of the Eclipse Mosquitto broker on Windows 10 and 11, Linux, and macOS operating systems using the Docker containerization tool. We also learned how to subscribe to topics and publish messages using the Mosquitto MQTT broker.
Let’s recap the most important points:
- The installation process of the Mosquitto broker is practically the same for all the operating systems.
- To install the Mosquitto broker, use the “eclipse-mosquitto” image and run it either with a ‘docker run’ command:
docker run -it -d --name mos1 -p 1883:1883 -v "$HOME"/mosquitto.conf:/mosquitto/config/mosquitto.conf
eclipse-mosquitto:2
or use the docker-compose up -d
and the provided docker-compose.yml file.
- To configure Mosquitto to your needs, mount a volume with a mosquitto.conf configuration file, and other volumes for logs, persistent data, etc.
- You can test whether your Mosquitto installation and configuration worked using MQTT clients such as MQTT Explorer, mosquitto_pub, and mosquitto_sub commands, or Paho Python Client.
If you plan to use the open-source version of Mosquitto for commercial purposes, you might be cautious about certain issues arising in production. That is why the Cedalo team also offers open-source Mosquitto support to ensure the stability and security of your system.
About the author
Serhii Orlivskyi is a full-stack software developer at Cedalo GmbH. He previously worked in the Telekom industry and software startups, gaining experience in various areas such as web technologies, services, relational databases, billing systems, and eventually IoT.
While searching for new areas to explore, Serhii came across Cedalo and started as a Mosquitto Management Center developer. Over time, Serhii delved deeper into the MQTT protocol and the intricacies of managing IoT ecosystems.
Recognizing the immense potential of MQTT and IoT, he continues to expand his knowledge in this rapidly growing industry and contributes by writing and editing technical articles for Cedalo's blog.