Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GitHub

This documentation is part of the "Projects with Books" initiative at zenOSmosis.

The source code for this project is available on GitHub.

Overview

Relevant source files

This document provides a high-level introduction to the Docker MQTT Mosquitto Cloudflare Tunnel system. It covers the system's purpose, architecture, key components, and how they interact to provide secure MQTT message brokering accessible over the internet.

For detailed setup instructions, see Getting Started. For in-depth component documentation, see Components. For security architecture details, see Security Model.

System Purpose

The Docker MQTT Mosquitto Cloudflare Tunnel system provides a secure MQTT broker deployment that is accessible from the public internet without exposing ports directly on the host machine. It accomplishes this by combining Eclipse Mosquitto (an MQTT message broker) with Cloudflare Tunnel (a secure proxy service).

The system solves the following challenges:

  • Port Exposure : Eliminates the need for port forwarding or firewall rules to expose MQTT services
  • Secure Access : Provides encrypted transport between external clients and the internal broker through Cloudflare's global network
  • DDoS Protection : Leverages Cloudflare's infrastructure for traffic filtering and protection
  • Easy Deployment : Uses Docker Compose for simplified orchestration and deployment

This system is particularly suited for IoT applications, home automation, and message brokering scenarios where devices need to communicate with a central MQTT broker over the internet.

Sources : README.md:1-21

Key Components

The system consists of two containerized services orchestrated by Docker Compose, plus configuration files and authentication credentials.

graph TB
    subgraph "docker-compose.yml"
        mosquitto_service["mosquitto service"]
cloudflared_service["cloudflared service"]
end
    
    subgraph "Container Images"
        mosquitto_image["eclipse-mosquitto:latest"]
cloudflared_image["cloudflare/cloudflared:latest"]
end
    
    subgraph "Configuration Files"
        mosquitto_conf["mosquitto.conf"]
env_file[".env"]
env_sample[".env.sample"]
end
    
    subgraph "Environment Variables"
        token_var["CLOUDFLARE_TUNNEL_TOKEN"]
end
    
    subgraph "Data Storage"
        data_dir["data/ directory"]
end
    
 
   mosquitto_service -->|uses image| mosquitto_image
 
   mosquitto_service -->|volume mount| mosquitto_conf
 
   mosquitto_service -->|may store data in| data_dir
    
 
   cloudflared_service -->|uses image| cloudflared_image
 
   cloudflared_service -->|reads from| env_file
    
 
   env_file -->|contains| token_var
 
   env_sample -->|template for| env_file
    
 
   token_var -->|authenticates| cloudflared_service

Component Map

Sources : docker-compose.yml:1-18 mosquitto.conf:1-6 .env.sample README.md51

Service Definitions

ServiceContainer NameImagePurpose
mosquittomosquittoeclipse-mosquitto:latestMQTT message broker with two listeners (TCP and WebSocket)
cloudflaredcloudflaredcloudflare/cloudflared:latestCloudflare Tunnel client that proxies traffic to the broker

Sources : docker-compose.yml:4-17

Configuration Files

FilePurposeVersion Controlled
docker-compose.ymlService orchestration and container definitionsYes
mosquitto.confMosquitto broker configuration (listeners, protocols, access control)Yes
.envEnvironment variables including CLOUDFLARE_TUNNEL_TOKENNo (secret)
.env.sampleTemplate for .env fileYes

Sources : docker-compose.yml:1-18 mosquitto.conf:1-6 README.md51

Service Architecture

The following diagram shows how the two Docker services are configured and how they relate to their configuration sources.

Sources : docker-compose.yml:3-17 mosquitto.conf:1-6

graph TB
    subgraph "Docker Compose Services"
        direction LR
        
        subgraph mosquitto["mosquitto service (container_name: mosquitto)"]
mosq_image["image: eclipse-mosquitto:latest"]
mosq_restart["restart: unless-stopped"]
mosq_volume["volume: ./mosquitto.conf:/mosquitto/config/mosquitto.conf"]
end
        
        subgraph cloudflared["cloudflared service (container_name: cloudflared)"]
cf_image["image: cloudflare/cloudflared:latest"]
cf_command["command: tunnel --no-autoupdate run --token"]
cf_restart["restart: unless-stopped"]
cf_env["environment: CLOUDFLARE_TUNNEL_TOKEN"]
end
    end
    
    subgraph "Configuration Sources"
        conf_file["mosquitto.conf\n- listener 1883\n- listener 9001 (websockets)\n- allow_anonymous true"]
env_file[".env\nCLOUDFLARE_TUNNEL_TOKEN=..."]
end
    
 
   conf_file -->|mounted into| mosq_volume
 
   env_file -->|provides| cf_env

Mosquitto Service Configuration

The mosquitto service docker-compose.yml:4-9 runs the Eclipse Mosquitto broker with the following characteristics:

The broker exposes two listeners defined in mosquitto.conf:1-6:

Anonymous access is enabled mosquitto.conf2 meaning no authentication is required to connect to the broker. For details on anonymous access implications, see Anonymous Access.

Sources : docker-compose.yml:4-9 mosquitto.conf:1-6

Cloudflared Service Configuration

The cloudflared service docker-compose.yml:11-17 establishes a secure tunnel to Cloudflare's network with the following configuration:

The --no-autoupdate flag prevents automatic updates of the cloudflared binary, ensuring consistent behavior. The token authenticates the tunnel client with Cloudflare's network.

Sources : docker-compose.yml:11-17 README.md51

sequenceDiagram
    participant Client as "MQTT Client"
    participant CFEdge as "Cloudflare Edge Network"
    participant cloudflared as "cloudflared container"
    participant mosquitto as "mosquitto container"
    
    Note over cloudflared: Startup with CLOUDFLARE_TUNNEL_TOKEN
    cloudflared->>CFEdge: Establish encrypted tunnel
    CFEdge-->>cloudflared: Tunnel connected
    
    Note over Client,mosquitto: Client Connection Flow
    Client->>CFEdge: MQTT CONNECT to public hostname
    CFEdge->>cloudflared: Route through tunnel
    cloudflared->>mosquitto: Proxy to mosquitto:9001
    mosquitto-->>cloudflared: MQTT CONNACK
    cloudflared-->>CFEdge: Through tunnel
    CFEdge-->>Client: MQTT CONNACK
    
    Note over Client,mosquitto: Message Publishing
    Client->>CFEdge: MQTT PUBLISH topic/message
    CFEdge->>cloudflared: Through tunnel
    cloudflared->>mosquitto: Proxy to port 9001
    mosquitto->>mosquitto: Deliver to subscribers
    mosquitto-->>Client: MQTT PUBACK (via tunnel)

Traffic Flow

The following diagram illustrates how MQTT traffic flows from external clients to the internal broker through Cloudflare's tunnel.

Traffic Flow Steps

  1. Tunnel Establishment : The cloudflared container connects outbound to Cloudflare using the CLOUDFLARE_TUNNEL_TOKEN from .env docker-compose.yml:16-17
  2. Client Connection : External MQTT clients connect to the Cloudflare public hostname configured in the Zero Trust dashboard README.md:59-64
  3. Proxy Routing : Cloudflare routes the traffic through the encrypted tunnel to the cloudflared container
  4. Internal Forwarding : The cloudflared container proxies traffic to mosquitto:9001 README.md62
  5. MQTT Processing : The mosquitto container processes MQTT messages on its WebSocket listener mosquitto.conf:4-5

Note that the cloudflared service proxies to mosquitto:9001 specifically, which corresponds to the WebSocket listener mosquitto.conf:4-5 rather than the standard TCP listener on port 1883 mosquitto.conf1

Sources : README.md:15-73 docker-compose.yml:13-14 mosquitto.conf:1-6

Project Structure

The repository contains the following key files:

File Descriptions

File PathPurposeNotes
README.mdSetup guide and documentationIncludes Cloudflare dashboard walkthrough
docker-compose.ymlService definitions for mosquitto and cloudflaredOrchestrates both containers
mosquitto.confMosquitto broker configurationDefines listeners on ports 1883 and 9001
.envEnvironment variables (contains CLOUDFLARE_TUNNEL_TOKEN)Not version controlled (secret)
.env.sampleTemplate for .env fileShows required variables without actual values
.gitignoreGit exclusionsPrevents committing .env and data/*
.github/workflows/ci.ymlGitHub Actions CI pipelineTests mosquitto startup

Sources : README.md:1-73 docker-compose.yml:1-18 mosquitto.conf:1-6

How the System Works

Network Topology

The system eliminates the need for port forwarding or inbound firewall rules because the cloudflared container establishes an outbound connection to Cloudflare's network docker-compose.yml14 This architectural pattern is known as a reverse tunnel.

Sources : README.md:15-20 docker-compose.yml:11-17

Key Characteristics

  1. No Direct Internet Exposure : The mosquitto broker is never directly accessible from the internet
  2. Outbound-Only Connection : The cloudflared container initiates the tunnel connection to Cloudflare
  3. Service Discovery : Docker's internal DNS resolves mosquitto to the mosquitto container docker-compose.yml6
  4. WebSocket Routing : Public traffic is routed to the WebSocket listener on port 9001 mosquitto.conf:4-5
  5. Anonymous Access : No authentication is required at the MQTT protocol level mosquitto.conf2

For detailed architectural information, see System Architecture. For security considerations, see Security Model.

Sources : docker-compose.yml:1-18 mosquitto.conf:1-6 README.md:15-73

Quick Start Reference

To deploy this system, you need to:

  1. Create a Cloudflare Tunnel and obtain the CLOUDFLARE_TUNNEL_TOKEN README.md:23-54
  2. Create a .env file with the token README.md51
  3. Configure a public hostname to route to mosquitto:9001 README.md62
  4. Run docker compose up README.md:70-72

For detailed step-by-step instructions, see Getting Started. For Cloudflare-specific configuration, see Cloudflare Tunnel Configuration.

Sources : README.md:23-73

Branch Variants

This repository includes a variant branch called protected-no-wildcard that adds:

  • Topic access control via ACL file (restricts wildcard searches)
  • Encrypted retained messages using gocryptfs
  • Auto-save functionality for retained messages

For information about these advanced features, see Topic Access Control (ACL)) and Encrypted Retained Messages.

Sources : README.md:5-11

Next Steps

Sources : README.md:1-73