This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
MQTT Listeners
Relevant source files
Purpose and Scope
This document describes the MQTT listener configuration in the Mosquitto broker, specifically the two listeners defined in mosquitto.conf:1-6 It explains the purpose, protocol, and routing behavior of each listener. For broader Mosquitto broker configuration, see Mosquitto Configuration. For access control settings, see Anonymous Access. For Cloudflare tunnel routing configuration, see Cloudflared Tunnel Service.
Sources : mosquitto.conf, README.md
Listener Configuration Overview
The Mosquitto broker is configured with two distinct listeners, each serving different transport protocols and use cases. Both listeners are defined in mosquitto.conf:1-6 and operate simultaneously within the mosquitto container.
Listener Configuration Structure
| Listener | Port | Protocol | Anonymous Access | Primary Use Case |
|---|---|---|---|---|
| mosquitto.conf1 | 1883 | Standard MQTT/TCP | Enabled globally mosquitto.conf2 | Direct MQTT client connections |
| mosquitto.conf:4-5 | 9001 | MQTT over WebSockets | Enabled globally mosquitto.conf2 | Browser-based clients, Cloudflare tunnel |
Sources : mosquitto.conf
Listener 1883: Standard MQTT TCP
The first listener, configured at mosquitto.conf1 binds to port 1883 and provides standard MQTT protocol over TCP. This is the default MQTT port and is used by most native MQTT client libraries.
Configuration Directives
listener 1883
allow_anonymous true
Directive Breakdown :
listener 1883mosquitto.conf1: Binds the Mosquitto broker to TCP port 1883allow_anonymous truemosquitto.conf2: Applies globally to all listeners, allowing clients to connect without authentication
Protocol Characteristics
This listener implements the standard MQTT 3.1.1 and MQTT 5.0 protocols over raw TCP connections. It supports:
- Binary MQTT protocol framing
- Persistent TCP connections
- Quality of Service (QoS) levels 0, 1, and 2
- Last Will and Testament (LWT) messages
- Retained messages
Network Accessibility
The 1883 listener is not directly exposed through the Cloudflare tunnel in the current configuration. It operates only within Docker's internal network, accessible to other containers in the same Docker Compose stack.
Sources : mosquitto.conf, README.md
graph LR
subgraph "Docker Internal Network"
OtherContainer["Other Docker Container"]
MosquittoPort1883["mosquitto:1883\nTCP Listener"]
end
subgraph "External Network"
Internet["Public Internet"]
end
OtherContainer -->|Direct MQTT/TCP| MosquittoPort1883
Internet -.->|Not Accessible| MosquittoPort1883
Listener 9001: MQTT over WebSockets
The second listener, configured at mosquitto.conf:4-5 binds to port 9001 and provides MQTT protocol encapsulated over WebSockets. This is the primary listener exposed to external clients via the Cloudflare tunnel.
Configuration Directives
listener 9001
protocol websockets
Directive Breakdown :
listener 9001mosquitto.conf4: Binds the Mosquitto broker to TCP port 9001protocol websocketsmosquitto.conf5: Configures this listener to accept WebSocket connections with MQTT payloads
Protocol Characteristics
This listener encapsulates MQTT protocol messages within WebSocket frames, enabling:
- HTTP/WebSocket upgrade handshake
- Browser-based MQTT clients (JavaScript)
- Compatibility with web proxies and CDNs
- TLS/SSL termination at the proxy layer (Cloudflare)
The WebSocket protocol wrapper does not alter the MQTT protocol itself; it only provides an HTTP-compatible transport layer.
Cloudflare Tunnel Routing
The 9001 listener is configured as the target for the Cloudflare tunnel in the Zero Trust dashboard. The tunnel configuration specifies mosquitto:9001 as the service URL README.md62 routing external MQTT WebSocket connections through the cloudflared container to this listener.
sequenceDiagram
participant Client as "External MQTT Client"
participant CFEdge as "Cloudflare Edge"
participant Cloudflared as "cloudflared Container"
participant Mosquitto9001 as "mosquitto:9001\nWebSocket Listener"
participant MosqConf as "mosquitto.conf"
Note over Client: Initiates MQTT over WebSocket
Client->>CFEdge: WebSocket Upgrade Request\nto public hostname
CFEdge->>Cloudflared: Route through encrypted tunnel
Cloudflared->>Mosquitto9001: HTTP proxy to mosquitto:9001
Mosquitto9001->>MosqConf: Check listener configuration
Note over MosqConf: listener 9001\nprotocol websockets\nallow_anonymous true
MosqConf-->>Mosquitto9001: Accept WebSocket connection
Mosquitto9001-->>Cloudflared: WebSocket established
Cloudflared-->>CFEdge: Through tunnel
CFEdge-->>Client: WebSocket connection established
Note over Client,Mosquitto9001: MQTT messages flow over WebSocket
Network Accessibility
Unlike the 1883 listener, the 9001 listener is indirectly exposed to the public internet through the Cloudflare tunnel. The routing path is:
- External client connects to Cloudflare public hostname
- Cloudflare Edge routes to
cloudflaredcontainer via tunnel cloudflaredproxies HTTP traffic tomosquitto:9001- Mosquitto 9001 listener accepts WebSocket connection
Sources : mosquitto.conf, README.md
graph TB
subgraph "External Access"
PublicClient["MQTT WebSocket Client\nBrowser/JS Library"]
PublicHostname["Public Hostname\nConfigured in CF Dashboard"]
end
subgraph "Cloudflare Infrastructure"
CFEdge["Cloudflare Edge Network"]
CFTunnel["Cloudflare Tunnel\nEncrypted Connection"]
end
subgraph "Docker Host"
subgraph "cloudflared Container"
CFD["cloudflared process"]
Proxy["HTTP Proxy"]
end
subgraph "mosquitto Container"
MosqBroker["Mosquitto Broker"]
L1883["Listener 1883\nprotocol: MQTT/TCP"]
L9001["Listener 9001\nprotocol: websockets"]
end
subgraph "Docker Internal Network"
InternalClient["Internal Container\nDirect MQTT Client"]
end
end
PublicClient -->|MQTT over WS| PublicHostname
PublicHostname --> CFEdge
CFEdge -->|Encrypted Tunnel| CFTunnel
CFTunnel --> CFD
CFD --> Proxy
Proxy -->|mosquitto:9001| L9001
L9001 --> MosqBroker
L1883 --> MosqBroker
InternalClient -->|mosquitto:1883 Direct TCP| L1883
style L9001 fill:#e1f5ff
style L1883 fill:#fff3e1
Traffic Routing Architecture
The following diagram illustrates how traffic is routed to each listener based on the source and transport protocol:
Routing Configuration References :
- Cloudflare tunnel target:
mosquitto:9001README.md62 - WebSocket listener: mosquitto.conf:4-5
- TCP listener: mosquitto.conf1
- Container name resolution:
mosquittofromdocker-compose.yml
Sources : mosquitto.conf, README.md
Configuration Reference
Listener Directive Syntax
The listener directive defines a network interface and port for the broker to bind to:
listener <port> [bind_address]
Current Configuration :
- mosquitto.conf1:
listener 1883- Binds to port 1883 on all interfaces (no bind_address specified) - mosquitto.conf4:
listener 9001- Binds to port 9001 on all interfaces
Protocol Directive
The protocol directive specifies the transport protocol for a listener:
protocol <mqtt|websockets>
Current Configuration :
- Listener 1883: No protocol directive (defaults to
mqtt) - mosquitto.conf5:
protocol websockets- Configures listener 9001 for WebSocket transport
Anonymous Access Directive
The allow_anonymous directive controls whether clients can connect without authentication:
allow_anonymous <true|false>
Current Configuration :
- mosquitto.conf2:
allow_anonymous true- Applies globally to all listeners
This directive appears once and affects both listeners. For production deployments requiring authentication, this should be set to false and appropriate authentication mechanisms configured. See Anonymous Access for detailed security implications.
Configuration Interaction Matrix
| Configuration Aspect | Listener 1883 | Listener 9001 |
|---|---|---|
| Port | 1883 mosquitto.conf1 | 9001 mosquitto.conf4 |
| Protocol | MQTT/TCP (implicit default) | WebSockets mosquitto.conf5 |
| Anonymous Access | Enabled mosquitto.conf2 | Enabled mosquitto.conf2 |
| Cloudflare Routing | Not configured | Configured README.md62 |
| External Accessibility | Docker internal only | Via Cloudflare tunnel |
Sources : mosquitto.conf, README.md
Use Case Selection
When to Use Listener 1883 (TCP)
- Native MQTT client libraries : Python Paho, Mosquitto C library, MQTT.js with TCP
- High-performance IoT devices : Minimal protocol overhead
- Internal Docker services : Direct container-to-container communication
- Legacy MQTT applications : Standard MQTT port compatibility
When to Use Listener 9001 (WebSockets)
- Browser-based clients : JavaScript MQTT clients in web applications
- Cloudflare tunnel access : External clients connecting via the public hostname
- Firewall-restricted networks : HTTP/WebSocket traffic often allowed through corporate firewalls
- CDN/proxy compatibility : Works with HTTP-based reverse proxies
Current System Configuration
The current deployment configures the Cloudflare tunnel to route exclusively to listener 9001. This means:
- External clients must use MQTT over WebSockets
- The public hostname README.md60 resolves to listener 9001
- Listener 1883 remains available only for internal Docker network access
To expose listener 1883 externally, additional Cloudflare tunnel configuration would be required, though this is uncommon since WebSocket transport provides broader compatibility.
Sources : mosquitto.conf, README.md