Guia completa: Instal·lació de Mosquitto MQTT amb Traefik en VPS

Requisits previs

1. Configurar DNS

A Nominalia (o el teu proveïdor de DNS), afegeix:

A    broker.binefa.cat    → IP_DEL_VPS

Espera 15-30 minuts per propagació DNS.

2. Crear estructura de directoris

mkdir -p ~/mosquitto-broker/{mosquitto/{config,data,log},web,scripts,certs,certs-letsencrypt}
cd ~/mosquitto-broker

3. Generar certificats privats per MQTTS (10 anys)

cd ~/mosquitto-broker/certs

# Generar clau i certificat CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/C=ES/ST=Catalunya/L=Barcelona/O=NomEmpresa/OU=IoT/CN=broker.binefa.cat/emailAddress=admin@binefa.cat"

# Generar clau del servidor
openssl genrsa -out server.key 4096

# Generar CSR del servidor
openssl req -new -key server.key -out server.csr \
  -subj "/C=ES/ST=Catalunya/L=Barcelona/O=NomEmpresa/OU=MQTT/CN=broker.binefa.cat"

# Signar certificat del servidor (10 anys)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 3650

# Ajustar permisos
chmod 644 ca.crt server.crt ca.srl server.csr
chmod 600 ca.key server.key

cd ~/mosquitto-broker

4. Generar certificat CA per ESP32

echo "// Certificat CA per ESP32 - Còpia aquest codi"
echo "const char* ca_cert = \\"
awk 'NF {sub(/\r/, ""); printf "\"%s\\n\" \\\n",$0;}' certs/ca.crt
echo ";"

Guarda aquesta sortida per als teus microcontroladors!

5. Crear fitxer de contrasenyes

cd ~/mosquitto-broker

# Crear usuari i contrasenya
docker run -it --rm -v $(pwd)/mosquitto/config:/mosquitto/config \
  eclipse-mosquitto:latest mosquitto_passwd -c /mosquitto/config/passwd mqttuser

# Introdueix la contrasenya dues vegades (exemple: MosquittoSecure2024!)

6. Configurar Mosquitto

cat > ~/mosquitto-broker/mosquitto/config/mosquitto.conf << 'EOFCONF'
# Configuració general
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
log_type all

# Autenticació
password_file /mosquitto/config/passwd
allow_anonymous false

# Listener MQTT (port 1883)
listener 1883 0.0.0.0
protocol mqtt

# Listener MQTTS amb certificat privat (port 8883)
listener 8883 0.0.0.0
protocol mqtt
cafile /mosquitto/certs/ca.crt
certfile /mosquitto/certs/server.crt
keyfile /mosquitto/certs/server.key
require_certificate false

# Listener WebSockets Secure amb Let's Encrypt (port 9002)
listener 9002 0.0.0.0
protocol websockets
cafile /mosquitto/certs-letsencrypt/fullchain.pem
certfile /mosquitto/certs-letsencrypt/fullchain.pem
keyfile /mosquitto/certs-letsencrypt/privkey.pem
EOFCONF

7. Crear pàgina web informativa

(El codi HTML complet està a index.html)

8. Docker Compose

cat > ~/mosquitto-broker/docker-compose.yml << 'EOFCOMPOSE'
services:
  mosquitto:
    image: eclipse-mosquitto:latest
    container_name: mosquitto-broker
    restart: unless-stopped
    user: "1883:1883"
    ports:
      - "1883:1883"
      - "8883:8883"
      - "9002:9002"
    volumes:
      - ./mosquitto/config:/mosquitto/config:ro
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log
      - ./certs:/mosquitto/certs:ro
      - ./certs-letsencrypt:/mosquitto/certs-letsencrypt:ro
    networks:
      - proxy

  nginx:
    image: nginx:alpine
    container_name: broker-web
    restart: unless-stopped
    volumes:
      - ./web:/usr/share/nginx/html:ro
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.broker-nginx.rule=Host(\`broker.binefa.cat\`)"
      - "traefik.http.routers.broker-nginx.entrypoints=https"
      - "traefik.http.routers.broker-nginx.tls=true"
      - "traefik.http.routers.broker-nginx.tls.certresolver=letsencrypt"
      - "traefik.http.services.broker-nginx.loadbalancer.server.port=80"

networks:
  proxy:
    external: true
EOFCOMPOSE

9. Script d'actualització de certificats

cat > ~/mosquitto-broker/scripts/update-certs.sh << 'EOFSCRIPT'
#!/bin/bash

TRAEFIK_CERTS="/home/jordi/traefik/acme.json"
MOSQUITTO_CERTS="/home/jordi/mosquitto-broker/certs-letsencrypt"
DOMAIN="broker.binefa.cat"

mkdir -p $MOSQUITTO_CERTS

docker run --rm -v /home/jordi/traefik:/traefik alpine sh -c "
  apk add --no-cache jq openssl
  cat /traefik/acme.json | jq -r '.letsencrypt.Certificates[] | select(.domain.main==\"$DOMAIN\") | .certificate' | base64 -d > /tmp/fullchain.pem
  cat /traefik/acme.json | jq -r '.letsencrypt.Certificates[] | select(.domain.main==\"$DOMAIN\") | .key' | base64 -d > /tmp/privkey.pem
  if [ -s /tmp/fullchain.pem ] && [ -s /tmp/privkey.pem ]; then
    cat /tmp/fullchain.pem
    echo '---SEPARATOR---'
    cat /tmp/privkey.pem
  else
    echo 'ERROR: No s han pogut extreure els certificats'
    exit 1
  fi
" > /tmp/certs_output.txt

csplit -s -z /tmp/certs_output.txt '/---SEPARATOR---/' '{*}'
mv xx00 $MOSQUITTO_CERTS/fullchain.pem
mv xx01 $MOSQUITTO_CERTS/privkey.pem

chmod 644 $MOSQUITTO_CERTS/fullchain.pem
chmod 600 $MOSQUITTO_CERTS/privkey.pem
chown 1883:1883 $MOSQUITTO_CERTS/*.pem

docker restart mosquitto-broker
echo "Certificats actualitzats correctament!"
EOFSCRIPT

chmod +x ~/mosquitto-broker/scripts/update-certs.sh

10. Ajustar permisos

cd ~/mosquitto-broker

# Permisos dels directoris
sudo chown -R 1883:1883 mosquitto/data mosquitto/log mosquitto/config
sudo chown -R 1883:1883 certs certs-letsencrypt

# Permisos dels fitxers
chmod 755 mosquitto/config mosquitto/data mosquitto/log
chmod 644 mosquitto/config/mosquitto.conf
chmod 640 mosquitto/config/passwd
chmod 755 certs certs-letsencrypt
chmod 644 certs/*.crt certs/*.csr certs/*.srl
chmod 640 certs/*.key

11. Iniciar els serveis

cd ~/mosquitto-broker

# Crear certificats temporals per evitar errors inicials
touch certs-letsencrypt/fullchain.pem certs-letsencrypt/privkey.pem
sudo chown 1883:1883 certs-letsencrypt/*.pem
chmod 644 certs-letsencrypt/fullchain.pem
chmod 640 certs-letsencrypt/privkey.pem

# Iniciar contenidors
docker compose up -d

# Esperar que Traefik generi certificats SSL (1-2 minuts)
sleep 120

# Actualitzar certificats Let's Encrypt
./scripts/update-certs.sh

# Verificar logs
docker compose logs mosquitto | tail -20

12. Automatitzar renovació de certificats

Opció A: Amb systemd timer (recomanat)

# Crear servei
sudo cat > /etc/systemd/system/mosquitto-certs-update.service << 'EOFSERVICE'
[Unit]
Description=Actualitzar certificats Let's Encrypt per Mosquitto
After=network.target

[Service]
Type=oneshot
User=jordi
ExecStart=/home/jordi/mosquitto-broker/scripts/update-certs.sh
StandardOutput=append:/var/log/mosquitto-certs-update.log
StandardError=append:/var/log/mosquitto-certs-update.log
EOFSERVICE

# Crear timer
sudo cat > /etc/systemd/system/mosquitto-certs-update.timer << 'EOFTIMER'
[Unit]
Description=Actualitzar certificats Mosquitto diàriament a les 3 AM

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOFTIMER

# Activar
sudo systemctl daemon-reload
sudo systemctl enable mosquitto-certs-update.timer
sudo systemctl start mosquitto-certs-update.timer

13. Provar les connexions

Instal·lar clients MQTT

sudo apt install mosquitto-clients -y

Test MQTT (port 1883)

# Terminal 1: Subscriure's
mosquitto_sub -h broker.binefa.cat -p 1883 -t test/topic -u mqttuser -P MosquittoSecure2024! -v

# Terminal 2: Publicar
mosquitto_pub -h broker.binefa.cat -p 1883 -t test/topic -m "Hola MQTT!" -u mqttuser -P MosquittoSecure2024!

Test MQTTS (port 8883)

mosquitto_pub -h broker.binefa.cat -p 8883 -t test/secure -m "Hola MQTTS!" \
  -u mqttuser -P MosquittoSecure2024! \
  --cafile ~/mosquitto-broker/certs/ca.crt

14. Codi per ESP32

#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

// Certificat CA (el generat al pas 4)
const char* ca_cert = \
"-----BEGIN CERTIFICATE-----\n" \
"MII... (còpia el teu certificat) ...\n" \
"-----END CERTIFICATE-----\n";

const char* ssid = "TU_WIFI";
const char* password = "TU_PASSWORD";
const char* mqtt_server = "broker.binefa.cat";
const int mqtt_port = 8883;
const char* mqtt_user = "mqttuser";
const char* mqtt_password = "MosquittoSecure2024!";

WiFiClientSecure espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  espClient.setCACert(ca_cert);
  client.setServer(mqtt_server, mqtt_port);
  reconnect();
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("ESP32", mqtt_user, mqtt_password)) {
      Serial.println("✓ Connectat MQTTS!");
      client.publish("test/esp32", "Hola!");
    } else {
      Serial.print("Error: ");
      Serial.println(client.state());
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) reconnect();
  client.loop();
}

Resum

Protocol Port Xifrat Certificat
MQTT 1883 -
MQTTS 8883 Privat (10 anys)
WSS 9002 Let's Encrypt
HTTPS 443 Let's Encrypt

Documentació: Novembre 2025 · Versió 1.0


Documentació generada · Novembre 2025 · Versió 1.0