This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Components
Relevant source files
This document provides detailed technical documentation of the major components that constitute the Docker MQTT Mosquitto Cloudflare Tunnel system. Each component is examined in terms of its Docker service configuration, runtime behavior, and integration with other system components.
For architectural overview and how these components interact at a system level, see System Architecture. For deployment instructions, see Deployment. For advanced branch-specific features like ACLs and encryption, see Advanced Topics.
Component Overview
The system consists of three primary components orchestrated by Docker Compose:
| Component | Container Name | Image | Primary Function |
|---|---|---|---|
| Mosquitto MQTT Broker | mosquitto | eclipse-mosquitto:latest | MQTT message broker providing pub/sub messaging |
| Cloudflared Tunnel Client | cloudflared | cloudflare/cloudflare:latest | Secure tunnel client connecting broker to Cloudflare network |
| Docker Compose | N/A | N/A | Service orchestration and configuration management |
Component Interaction Diagram
Sources : docker-compose.yml, README.md, mosquitto.conf
Mosquitto MQTT Broker
The Mosquitto service provides MQTT protocol brokering functionality. This component runs the Eclipse Mosquitto broker inside a Docker container, configured for WebSocket and TCP connections with anonymous access enabled.
Service Definition
The Mosquitto service is defined in docker-compose.yml:4-9 with the following configuration:
| Property | Value | Purpose |
|---|---|---|
image | eclipse-mosquitto:latest | Official Mosquitto Docker image |
container_name | mosquitto | Fixed container name for internal DNS resolution |
volumes | ./mosquitto.conf:/mosquitto/config/mosquitto.conf | Mounts configuration file into container |
restart | unless-stopped | Automatic restart policy for service reliability |
The container name mosquitto is critical as it serves as the internal DNS hostname that cloudflared uses to proxy traffic (referenced in Cloudflare tunnel configuration as mosquitto:9001).
Sources : docker-compose.yml:4-9, README.md:62
graph LR
subgraph MosquittoContainer["mosquitto Container"]
subgraph ListenerConfig["mosquitto.conf Configuration"]
Listener1["listener 1883\nprotocol mqtt"]
Listener2["listener 9001\nprotocol websockets"]
end
subgraph BrokerCore["Mosquitto Broker Process"]
MQTTEngine["MQTT Protocol Engine"]
end
Listener1 -->|standard TCP/IP| MQTTEngine
Listener2 -->|WebSocket framing| MQTTEngine
end
subgraph ExternalAccess["External Access Paths"]
TCPClient["TCP MQTT Clients\n(port 1883)"]
WSClient["WebSocket Clients\n(via cloudflared proxy)"]
end
TCPClient -.->|internal network only not exposed via tunnel| Listener1
WSClient -->|proxied through cloudflared:mosquitto:9001| Listener2
MQTT Listeners
The Mosquitto broker is configured with two distinct listeners, each serving different client connection patterns:
Listener Configuration Overview
Sources : mosquitto.conf, README.md:62, docker-compose.yml:4-9
Standard TCP Listener (Port 1883)
Configured in mosquitto.conf as:
listener 1883
protocol mqtt
This listener provides standard MQTT-over-TCP connectivity on the default MQTT port. It is accessible within the Docker internal network but is not exposed through the Cloudflare tunnel in the default configuration.
Use cases :
- Direct connections from other Docker containers on the same network
- Internal service-to-service MQTT communication
- Local development and testing
WebSocket Listener (Port 9001)
Configured in mosquitto.conf as:
listener 9001
protocol websockets
This listener provides MQTT-over-WebSocket connectivity, which is the primary listener exposed through the Cloudflare tunnel. The cloudflared service proxies external traffic to mosquitto:9001 as configured in the Cloudflare Zero Trust dashboard.
Use cases :
- Browser-based MQTT clients
- Web applications requiring MQTT connectivity
- Clients behind restrictive firewalls that block non-HTTP protocols
- The primary access method for external clients via Cloudflare tunnel
Sources : mosquitto.conf, README.md:55-66
Anonymous Access
The Mosquitto broker is configured with anonymous access enabled, meaning no authentication is required to connect or publish/subscribe to topics.
Configuration :
allow_anonymous true
This setting in mosquitto.conf permits any client that can reach the broker to perform MQTT operations without credentials.
Security implications :
| Aspect | Implication |
|---|---|
| Authentication | None - all clients are accepted |
| Authorization | No topic-level access control in main branch |
| Trust model | Broker trusts all traffic from cloudflared |
| Network security | Security relies entirely on Cloudflare tunnel and network isolation |
The security model assumes that network-level access control (via Cloudflare tunnel) provides sufficient protection. For environments requiring topic-level access control, see Topic Access Control (ACL)) which documents the protected-no-wildcard branch implementation.
Sources : mosquitto.conf, README.md:5-11
Cloudflared Tunnel Service
The cloudflared service establishes a secure, outbound-only connection to Cloudflare's network, enabling external MQTT clients to reach the internal Mosquitto broker without exposing inbound ports on the host.
Service Definition
The cloudflared service is defined in docker-compose.yml:11-17:
| Property | Value | Purpose |
|---|---|---|
image | cloudflare/cloudflared:latest | Official Cloudflare tunnel client image |
container_name | cloudflared | Fixed container name |
command | tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN} | Starts tunnel with authentication token |
restart | unless-stopped | Automatic restart policy |
environment | CLOUDFLARE_TUNNEL_TOKEN | Passes tunnel authentication token from .env file |
Sources : docker-compose.yml:11-17
Tunnel Authentication and Establishment
Tunnel Connection Flow
Sources : docker-compose.yml:11-17, .env.sample, README.md:47-53
Command Line Arguments
The command directive in docker-compose.yml14 specifies:
tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN}
| Argument | Purpose |
|---|---|
tunnel | Primary cloudflared operation mode |
--no-autoupdate | Disables automatic updates (container image updates handled via Docker) |
run | Runs the tunnel in persistent mode |
--token | Authenticates with Cloudflare using provided token |
${CLOUDFLARE_TUNNEL_TOKEN} | Environment variable interpolation from .env file |
The token is obtained during tunnel creation in the Cloudflare Zero Trust dashboard (see Cloudflare Tunnel Configuration) and stored in the .env file as documented in .env.sample
Sources : docker-compose.yml:14, .env.sample, README.md:47-53
Traffic Proxying
Once the tunnel is established, cloudflared proxies incoming traffic from Cloudflare's edge to the internal Mosquitto broker. The routing configuration is managed in the Cloudflare Zero Trust dashboard, not in local configuration files.
The public hostname configuration in Cloudflare maps to the service URL mosquitto:9001, where:
mosquittoresolves via Docker's internal DNS to the container withcontainer_name: mosquitto- Port
9001corresponds to the WebSocket listener configured in mosquitto.conf
Sources : README.md:55-66, docker-compose.yml
Docker Compose Orchestration
Docker Compose provides service orchestration, dependency management, and configuration binding for the system.
Service Orchestration Model
Docker Compose Component Relationships
Sources : docker-compose.yml
Network Configuration
Docker Compose creates a default bridge network for service communication. The network configuration is implicit (no explicit networks section in docker-compose.yml).
Network characteristics :
| Aspect | Behavior |
|---|---|
| Network type | Bridge network (default) |
| Network name | {project_name}_default (typically docker-mqtt-mosquitto-cloudflare-tunnel_default) |
| DNS resolution | Container names resolve to container IPs (mosquitto → container IP) |
| Inter-service communication | All services can reach each other using container names |
| External connectivity | Services can initiate outbound connections (used by cloudflared) |
The internal DNS resolution is critical: when the Cloudflare tunnel configuration specifies mosquitto:9001, Docker's embedded DNS server resolves mosquitto to the IP address of the container with container_name: mosquitto.
Sources : docker-compose.yml, README.md:62
Volume Management
The Mosquitto service uses a bind mount to inject configuration:
Volume mapping details :
| Source (Host) | Target (Container) | Mount Type | Purpose |
|---|---|---|---|
./mosquitto.conf | /mosquitto/config/mosquitto.conf | Bind mount | Provides broker configuration at runtime |
The configuration file is read by the Mosquitto broker on startup. Changes to mosquitto.conf require container restart to take effect:
No data persistence volumes are configured in the default setup. For persistent message storage, see Advanced Topics and the protected-no-wildcard branch documentation.
Sources : docker-compose.yml:7-8, mosquitto.conf
Environment Variable Injection
The cloudflared service receives environment variables via docker-compose.yml:16-17:
This syntax instructs Docker Compose to:
- Read
CLOUDFLARE_TUNNEL_TOKENfrom the.envfile in the same directory - Pass it as an environment variable to the
cloudflaredcontainer - Make it available for substitution in the
commanddirective via${CLOUDFLARE_TUNNEL_TOKEN}
The .env file is not version-controlled (excluded via .gitignore). Developers create it from .env.sample as documented in Environment Variables.
Sources : docker-compose.yml:16-17, .env.sample
Restart Policies
Both services use restart: unless-stopped:
Restart behavior :
| Scenario | Behavior |
|---|---|
| Container exits with error | Automatically restarts |
| Container exits cleanly (exit 0) | Automatically restarts |
| Docker daemon restarts | Containers restart automatically |
Manual docker stop | Container remains stopped after Docker daemon restart |
| System reboot | Containers restart if Docker daemon starts automatically |
This policy ensures service availability while allowing manual control via docker compose down or docker stop.
Sources : docker-compose.yml:9,15
Service Lifecycle Management
Common Docker Compose Commands :
| Command | Effect |
|---|---|
docker compose up | Creates and starts both services in foreground |
docker compose up -d | Creates and starts both services in background (detached) |
docker compose down | Stops and removes containers, networks |
docker compose restart | Restarts all services |
docker compose restart mosquitto | Restarts only Mosquitto service |
docker compose logs | Shows logs from all services |
docker compose logs -f cloudflared | Follows logs from cloudflared service |
For detailed deployment procedures, see Deployment.
Sources : docker-compose.yml, README.md:68-72