Skip to content

Instantly share code, notes, and snippets.

@gimiki
Last active July 21, 2024 20:38
Show Gist options
  • Save gimiki/628e2ca10f026975f00f34e4d1f4ff23 to your computer and use it in GitHub Desktop.
Save gimiki/628e2ca10f026975f00f34e4d1f4ff23 to your computer and use it in GitHub Desktop.
Traefik Reverse Proxy - Mosquitto MQTT Broker - Docker Container

This gist is to configure a Mosquitto MQTT Broker behind a Traefik reverse-proxy, both in a docker container. Mosquitto will be configuread as a TCP Service.

This is a simple configuration used on the same single server. Probably to be adapted for other cases. Having mosquitto behind a reverse proxy enables you to configure TLS on Traefik (likely you already do that for other applications as well) and to load balance different MQTT instances, but that goes beyond this gist.

As noted in Traefik docs, in the router you must use the rule HostSNI(`*`) when using non-TLS routers like in this example. Ref. https://docs.traefik.io/routing/routers/#rule_1

docker-compose.yml

networks:
  mqtt:
    driver: bridge

services:
  reverse-proxy:
    image: traefik:latest
    container_name: "traefik"
    # Enables the web UI
    command: 
      - "--log.level=DEBUG"
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--entrypoints.mqtt.address=:1883"
      - "--entrypoints.websocket.address=:9001"
    ports:
      # Mosquitto
      - "1883:1883"
      - "9001:9001"
    volumes:
      # So that Traefix can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - mqtt
      
  mqtt:
    container_name: mqtt
    image: eclipse-mosquitto
    networks:
      - mqtt
    restart: always
    expose:
      - 1883
      - 9001
    volumes:
      - "mqtt:/mosquitto/"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=mqtt"
      - "traefik.tcp.services.mqtt.loadbalancer.server.port=1883"
      - "traefik.tcp.services.mqtt_websocket.loadbalancer.server.port=9001"
      - "traefik.tcp.routers.tcpr_mqtt.entrypoints=mqtt"
      - "traefik.tcp.routers.tcpr_mqtt.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.tcpr_mqtt.service=mqtt"
      - "traefik.tcp.routers.tcpr_mqtt_websocket.entrypoints=websocket"
      - "traefik.tcp.routers.tcpr_mqtt_websocket.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.tcpr_mqtt_websocket.service=mqtt_websocket"

version: "3.4"

volumes: 
  mqtt: ~
@natcl
Copy link

natcl commented Apr 30, 2020

Nice!
Is there a way to make this work with TLS ?

@gimiki
Copy link
Author

gimiki commented May 31, 2020

Nice!
Is there a way to make this work with TLS ?

From what I know yes but I never tried with MQTT and I'm still experimenting with Traefik.
Normally you have to set up a proper Traefik entrypoint with TLS enabled, manually in the dynamic configuration or in another way (like Let's Encrypt auto TLS https://docs.traefik.io/https/acme/ ).

@natcl
Copy link

natcl commented Sep 22, 2020

@danclimasevschi
Copy link

danclimasevschi commented Sep 23, 2021

You should not expose the ports(in docker) if you want traefik to handle the routing. Exposing the ports binds them to the IP of the host, hence you will be able to access it even without traefik.

  mqtt:
    container_name: mqtt
    image: eclipse-mosquitto
    networks:
      - mqtt
    restart: always
    expose:
      - 1883
      - 9001

@gimiki
Copy link
Author

gimiki commented Sep 23, 2021

You should not expose the ports(in docker) if you want traefik to handle the routing. Exposing the ports binds them to the IP of the host, hence you will be able to access it even without traefik.

  mqtt:
    container_name: mqtt
    image: eclipse-mosquitto
    networks:
      - mqtt
    restart: always
    expose:
      - 1883
      - 9001

Yes you're right, this is exactly what I did in the docker-compose (y)

@EnsuingRequiem
Copy link

You should not expose the ports(in docker) if you want traefik to handle the routing. Exposing the ports binds them to the IP of the host, hence you will be able to access it even without traefik.

  mqtt:
    container_name: mqtt
    image: eclipse-mosquitto
    networks:
      - mqtt
    restart: always
    expose:
      - 1883
      - 9001

Yes you're right, this is exactly what I did in the docker-compose (y)

You've bound the ports within the reverse-proxy, though, which has the same net effect as binding them within mqtt, no? I'm still learning the ropes for traefik myself, and it doesn't seem like this setup is actually doing any reverse-proxying?

@natcl
Copy link

natcl commented Apr 13, 2022

You should not expose the ports(in docker) if you want traefik to handle the routing. Exposing the ports binds them to the IP of the host, hence you will be able to access it even without traefik.

That’s not true, expose does not open up the ports on the host, it’s only metadata,
See https://docs.docker.com/engine/reference/builder/#expose

@mstefanwalker
Copy link

mstefanwalker commented Nov 17, 2022

You should not expose the ports(in docker) if you want traefik to handle the routing. Exposing the ports binds them to the IP of the host, hence you will be able to access it even without traefik.

That’s not true, expose does not open up the ports on the host, it’s only metadata, See https://docs.docker.com/engine/reference/builder/#expose

+1

expose does not open the ports to the host and additionally it can be useful to Traefik.

Traefik relies on this metadata to do port discovery if you don't specify it yourself in Traefik config.
See https://doc.traefik.io/traefik/providers/docker/#port-detection


Alternatively, if the meaning here is that you don't need to publish the ports to the host with the ports option in the docker-compose.yml then that is very true. You can let Traefik handle all of the routing. Perhaps by "expose" you did not mean expose. Just leaving this here for disambiguation.

@simonmysun
Copy link

May I ask why you would like to configure the mqtt behind traefik? If I get it right, it only makes a difference when you have multiple instance of mqtt or the mqtt server is on another host.

@natcl
Copy link

natcl commented Dec 27, 2022

The goal is to easily setup SSL certificates via Let’s Encrypt. It’s very useful when you’re trying to secure multiple services and don’t want to configure SSL for every service individually.

@simonmysun
Copy link

The goal is to easily setup SSL certificates via Let’s Encrypt. It’s very useful when you’re trying to secure multiple services and don’t want to configure SSL for every service individually.

I see. Thanks!

@WanderingZombie
Copy link

https://github.com/synoniem/mosquitto-traefik-letsencrypt/blob/main/docker-compose.yml worked well for me with all traffic going through TLS via Traefik and to insecure ports on Mosquitto.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment