Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Mosquitto password protection in IOTstack

Mosquitto password protection in IOTstack

Setting up passwords for Mosquitto is a topic that comes up fairly frequently in GitHub issues and on the Discord channel, usually as a result of it not working as expected.

The purpose of this gist is to explain the how-to of password setup, as at Feb 16, 2021 when 2.0.7 was the "latest" version of Mosquitto.

Mosquitto underwent some changes between 1.6.x and 2.0, including how passwords were handled. See Migrating to Mosquitto 2.0.

Contents

Assumption

These instructions assume that you have set your working directory as follows, and that you do not change your working directory while you are following these instructions:

$ cd ~/IOTstack

Step 1: Reference configuration

On your system, Mosquitto's overall behaviour is defined by the following:

  • The Eclipse-Mosquitto image version that you are running (comes from DockerHub);
  • Your active service definition:
    • the master version at ./.templates/mosquitto/service.yml, is copied to
    • ./services/mosquitto/service.yml, and then into
    • docker-compose.yml, which is the active definition;
  • Your active configuration:
    • the master version at ./.templates/mosquitto/mosquitto.conf, is copied to
    • ./services/mosquitto/mosquitto.conf , which is the active definition; and
  • Any pre-existing password file at ./volumes/mosquitto/pwfile/pwfile.

The exact situation on your system is the product of many variables, including:

  • when you first installed IOTstack;
  • when you last synchronised with GitHub;
  • whether you are running the old or new menu;
  • when you last ran the menu and what choices you made;
  • whether you have pinned Eclipse-Mosquitto to a specific version;
  • when you last pulled an updated image from DockerHub;
  • whether you have ever edited Mosquitto's service definition or configuration file;
  • and so on …

Rather than putting you to the trouble of retracing your steps and figuring out what's what, or trying to write instructions to cover all possible combinations and contingencies, the purpose of this step is to make sure that your copy of IOTstack is in a known state.

Sync IOTstack with GitHub

Ensure that your copy of IOTstack is up-to-date:

$ git pull

Note:

  • If the pull doesn't work, you have issues to resolve before continuing with this gist. The best thing to do is to capture the evidence, put it into a PasteBin paste (the account is free if you don't have one already), then include the paste URL in a question on the IOTstack Discord Channel.

Use known-good service definition

  1. Select the text below and copy it to the clipboard.

      mosquitto:
        container_name: mosquitto
        image: eclipse-mosquitto
        restart: unless-stopped
        user: "1883"
        ports:
          - "1883:1883"
        volumes:
          - ./volumes/mosquitto/data:/mosquitto/data
          - ./volumes/mosquitto/log:/mosquitto/log
          - ./volumes/mosquitto/pwfile:/mosquitto/pwfile
          - ./services/mosquitto:/mosquitto/config:ro
         networks:
          - iotstack_nw
    

    Notes:

    • If you are running old-menu, omit the last two lines.

    • At the time of writing, the IOTstack template for Mosquitto included these lines under volumes:

       - ./services/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
       - ./services/mosquitto/filter.acl:/mosquitto/config/filter.acl
      

      I have replaced those with:

       - ./services/mosquitto:/mosquitto/config:ro
      

      See Issue 269 for the explanation.

  2. Open ./docker-compose.yml in your favourite text editor.

  3. Replace the Mosquitto service definition with the contents of the clipboard.

  4. Save the file.

Use known-good configuration file

  1. Select the text below and copy it to the clipboard.

    listener 1883
    	
    persistence true
    persistence_location /mosquitto/data
    	
    #log_dest file /mosquitto/log/mosquitto.log
    log_dest stdout
    	
    #password_file /mosquitto/pwfile/pwfile
    allow_anonymous true
    	
    #acl_file /mosquitto/config/filter.acl
    	
    log_timestamp_format %Y-%m-%dT%H:%M:%S
    

    Notes:

    • The password_file line is commented out and anonymous access is permitted. Those options must be set that way at this stage. Please don't get ahead of yourself!
    • There are some other differences between the text above and the IOTstack template (grouping related elements and removing the trailing slash from the persistence location) but those are cosmetic rather than material changes.
  2. Open ./services/mosquitto/mosquitto.conf in your favourite text editor.

  3. Replace the entire file with the contents of the clipboard.

  4. Save the file.

Terminate Mosquitto

If Mosquitto is running, terminate it:

$ docker-compose stop mosquitto
$ docker-compose rm -f mosquitto

Notes:

  • Those two commands are the equivalent of sending the down command. However, down takes down your whole stack whereas the above commands only affect Mosquitto.

  • See also TERMINATE in Useful aliases for working with IOTstack.

Remove password file

Remove any existing password file:

$ sudo rm -f ./volumes/mosquitto/pwfile/pwfile

Ensure correct ownership

Make sure permissions are correct in the persistent storage area:

$ ./.templates/mosquitto/directoryfix.sh
...found user 1883

Notes:

  • directoryfix.sh is normally run by the menu. Running it here, by hand, serves to correct any anomalies that may have crept in over time (eg maybe you tried changing ownership while trying to get passwords working).
  • directoryfix.sh must be run from ~/IOTstack. You must execute it exactly as written.
  • do not use sudo to run directoryfix.sh.

Ensure the Mosquitto image is up-to-date

The use known-good service definition step implicitly removed any pinning of Mosquitto to a particular version, so the following command should result in the eclipse-mosquitto:latest image being downloaded onto your system (assuming it is not there already):

$ docker-compose pull mosquitto
$ docker system prune

Note:

  • The prune command is a good general-purpose Docker cleanup utility.

Activate Mosquitto

Bring up Mosquitto:

$ docker-compose up -d mosquitto

Note:

Check Mosquitto log

Check the log to make sure Mosquitto looks happy:

$ docker logs mosquitto

The expected output should be similar to the following:

2021-02-16T03:22:56: mosquitto version 2.0.7 starting
2021-02-16T03:22:56: Config loaded from /mosquitto/config/mosquitto.conf.
2021-02-16T03:22:56: Opening ipv4 listen socket on port 1883.
2021-02-16T03:22:56: Opening ipv6 listen socket on port 1883.
2021-02-16T03:22:56: mosquitto version 2.0.7 running

Notes:

  • The first line usually appears immediately but you often have to wait a while for the next few lines to appear. Be patient!

  • Rather that repeatedly retrying the logs command, you can place a "watch" on the log like this:

     $ docker logs -f mosquitto
    

    Terminate the command by pressing Control+C.

Step 2: Create password scheme

Create first password

Create the FIRST password like this:

$ docker exec mosquitto mosquitto_passwd -c -b /mosquitto/pwfile/pwfile «username» «password» 

Replace "«username»" and "«password»" as appropriate, for example:

$ docker exec mosquitto mosquitto_passwd -c -b /mosquitto/pwfile/pwfile hello world 

Note:

  • The -c option says "create the password file".

Create second and subsequent passwords

Create SECOND and SUBSEQUENT passwords like this:

$ docker exec mosquitto mosquitto_passwd -b /mosquitto/pwfile/pwfile «username» «password» 

Example:

$ docker exec mosquitto mosquitto_passwd -b /mosquitto/pwfile/pwfile theworld isnotenough

Note:

  • The -c flag is omitted.

Check password file

Verify that the password file exists and has the expected content:

$ cat ./volumes/mosquitto/pwfile/pwfile 

If you created two usernames and passwords, there should be two lines in the file, and you should be able to see the usernames at the start of each line:

hello:$7$101$rGEPZWRc6q8wX6KW$FRwyoemymo5RMUE71uTXVy2Oqfwl5aDf2VJNBgwCQtK7gqH2LSnn4OHKVG3FIRF15nO8AGwhZPbJq6jK2m7XPQ==
theworld:$7$101$fHV4JIZwqkF79gAa$3blXsRd4zO9vUoTEpCLXgVeP/I8tMty21j27nXXzK4kd8GLuwJvsi2kTIQFZ4E2ttF5fuRAHEoxPGxvUw50lSA==

Step 3: Activate password scheme

Edit Mosquitto configuration

Edit ./services/mosquitto/mosquitto.conf to activate password enforcement. The resulting file should look like this:

```
listener 1883

persistence true
persistence_location /mosquitto/data

#log_dest file /mosquitto/log/mosquitto.log
log_dest stdout

password_file /mosquitto/pwfile/pwfile
allow_anonymous false

#acl_file /mosquitto/config/filter.acl

log_timestamp_format %Y-%m-%dT%H:%M:%S
```

Note - there are two changes:

  1. Uncomment the password_file line; and
  2. Set allow_anonymous to false.

Restart Mosquitto

Restart Mosquitto. This causes it to re-read the configuration file:

$ docker-compose restart mosquitto

Note:

Check Mosquitto log

Check the log for any obvious signs of error:

$ docker logs mosquitto

The output should be similar to what was shown in an earlier step but you should pay close attention to any complaints about the password file. If you see any errors relating to the password file:

  1. Undo the Edit Mosquitto configuration step;
  2. Repeat the Restart Mosquitto step; and then
  3. Start over at Create password scheme.

Step 4: Test password scheme

Install testing tools

If you do not have the Mosquitto clients installed on your Raspberry Pi (ie $ which mosquitto_pub does not return a path), install them using:

$ sudo apt install -y mosquitto-clients

Test: anonymous access is prohibited

Test without providing credentials:

$ mosquitto_pub -h 127.0.0.1 -p 1883 -t "/password/test" -m "up up and away"
Connection Refused: not authorised.
Error: The connection was refused.

Note:

  • The error is the expected result and shows that Mosquitto will not allow anonymous access.

Test: access with credentials is permitted

Test with credentials

$ mosquitto_pub -h 127.0.0.1 -p 1883 -t "/password/test" -m "up up and away" -u hello -P world
$ 

Note:

  • The absence of any error message means the message was sent. Silence = success!

Test: round-trip with credentials is permitted

Prove round-trip connectivity will succeed when credentials are provided. First, set up a subscriber as a background process. This mimics the role of a process like Node-Red:

$ mosquitto_sub -v -h 127.0.0.1 -p 1883 -t "/password/test" -F "%I %t %p" -u theworld -P isnotenough &
[1] 25996

Repeat the earlier test:

$ mosquitto_pub -h 127.0.0.1 -p 1883 -t "/password/test" -m "up up and away" -u hello -P world
2021-02-16T14:40:51+1100 /password/test up up and away

Note:

  • the second line above is coming from the mosquitto_sub running in the background.

When you have finished testing you can kill the background process:

$ kill %1
[1]+  Terminated              mosquitto_sub -v -h 127.0.0.1 -p 1883 -t "/password/test" -F "%I %t %p" -u theworld -P isnotenough

Step 5: Apply password scheme

You will need to provide credentials to all publishers (eg IoT devices) and all subscribers (eg Node-Red flows).

Keep in mind that you can define the scheme, test it, then re-enable allow_anonymous while you work towards implementing credentials in all your publishers and subscribers. In other words, your mosquitto.conf can look like this:

password_file /mosquitto/pwfile/pwfile
allow_anonymous true

Any publisher or subscriber that attempts access:

  • without any credentials – will be permitted.
  • with credentials – will only be permitted if the credentials match the password file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment