DIY Dry box — Part 5

Everything is now in place… except there’s nothing to monitor the humidity in the boxes anymore. As I said before, I’m not fond of the battery powered hygrometers.

The best solution here is to have desiccant that change color when wet and design the desiccant box in a way that allows to see the color from the outside.

But that’s not what I chose. I wanted to experiment with something else. Being a software engineer, this project was lacking software so far 😉.

The idea is to put a hygrometer chip in each box, link them to a microcontroller through an I²C bus. Then develop a program for the microcontroller to fetch the humidity level of each sensor and send it to an MQTT server.

First the MQTT server. MQTT is a message queuing system, so the microcontroller will send messages to it, and they will be consumed by something else (a bit more on that later). Mosquitto is probably the most well known MQTT server implementation, and there are docker images for it.

A well known thing about IoT, is that the “S” in “IoT” stands for security… so there are a few things I want to put in place:

MQTT encryption

As it could be expected, securing an MQTT channel simply consists in tunneling it through TLS. TLS works better with a valid certificate, we can generate one with Let’s encrypt.

There are plenty of ways to do so. Here I’ll use Traefik proxy, which is a reverse proxy that can generate Let’s encrypt certificates automatically. All incoming connections will go through Traefik, Traefik will be in charge of the TLS part, but then the connections between Traefik and the other Docker containers will not be encrypted.

Example of docker compose file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
version: '3'

services:

  proxy:
    image: traefik:latest
    ports:
      - 80:80
      - 443:443
      - 8883:8883
    networks:
      - internal
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.mqtts.address=:8883
      - --providers.docker=true
      - --providers.file.directory=/configuration/
      - --providers.file.watch=true
      - --certificatesresolvers.le.acme.email=your-email@address
      - --certificatesresolvers.le.acme.storage=/configuration/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /path/to/traefik/configuration/:/configuration/

  mqtt:
    image: eclipse-mosquitto:latest
    depends_on:
      - proxy
    volumes:
      - /path/to/mosquitto/configuration:/mosquitto/config
      - /path/to/mosquitto/data:/mosquitto/data
      - /path/to/mosquitto/log:/mosquitto/log
    networks:
      - internal
    labels:
      - "traefik.enable=true"
      - "traefik.tcp.routers.mqtt.rule=HostSNI(`mqtt.example.com`)"
      - "traefik.tcp.routers.mqtt.tls=true"
      - "traefik.tcp.routers.mqtt.tls.certresolver=le"
      - "traefik.tcp.routers.mqtt.entrypoints=mqtts"
      - "traefik.tcp.services.mqtt.loadbalancer.server.port=1883"

networks:
  internal

Some explanations:

Authentication

In mosquitto.conf file, make sure anonymous connections are not allowed and specify the path to a password file. Example of configuration file:

listener 1883
persistence true
persistence_location /mosquitto/data
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false
password_file /mosquitto/config/mosquitto.passwd

Now, create the password file, give mosquitto user (1883) ownership of the file, make sure its readable only by that user and call the mosquitto_passwd command (living inside the docker container) in order to add credentials to the file:

sudo touch mosquitto.passwd
sudo chown 1883:1883 mosquitto.passwd
sudo chmod 600 mosquitto.passwd
docker exec <mqtt-container-name> mosquitto_passwd -b /mosquitto/config/mosquitto.passwd <username> <password>

ACL

In mosquitto.conf file, specify a file for ACL:

acl_file /mosquitto/config/mosquitto.acl

Then create the matching file on the server. Here is an example of a user home_automation that can do everything and a user drybox that can only write to a specific topic:

user home_automation
topic readwrite #

user drybox
topic write devices/drybox/#

More about security

This is a basic example, a few more things to consider:

Test

Make sure mosquitto has been restarted to take into account the modifications made in the configuration file.

Install an MQTT client, for instance on debian:

sudo apt install mosquitto-clients

In a terminal, subscribe to all topics:

mosquitto_sub -h mqtt.example.com -p 8883 -u home_automation -P <password> -t '#' -v

In another terminal, send messages like:

mosquitto_pub -h mqtt.exmaple.com -p 8883 -u home_automation -P <password> -t devices/drybox/humidity -m 36

On the first terminal, the messages and their topic should be displayed.

Any messages sent to a topic the user is not allowed to write should not be received by the subscribed user. A wrong login and/or password should throw an error message, likewise when not providing any credentials.

More on this:

Comments Add one by emailing me.