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.

Configuration Reference

Loading…

Configuration Reference

Relevant source files

This page provides comprehensive reference documentation for all configuration files and settings in the Docker MQTT Mosquitto Cloudflare Tunnel system. Each configuration file is documented with complete syntax specifications, available directives, default values, and behavioral implications.

The system uses three configuration files:

  • docker-compose.yml - service orchestration and container definitions
  • mosquitto.conf - MQTT broker listener and access control configuration
  • .env - runtime environment variables containing sensitive credentials

For architectural context, see page 1.1. For security implications of configuration choices, see page 1.2. For setup instructions, see page 2.

Configuration Files Overview

The system uses three primary configuration files:

FilePurposeVersion ControlledContains SecretsFormat
docker-compose.ymlService orchestration and container definitionsYesNoYAML (Compose v3.8)
mosquitto.confMQTT broker configuration (listeners, protocols, access control)YesNoMosquitto INI-style
.envRuntime secrets and environment variablesNo (.gitignore)YesKEY=VALUE pairs
.env.sampleTemplate for .env fileYesNoKEY=VALUE pairs

Sources: docker-compose.yml:1-18 mosquitto.conf:1-6 .env.sample:1-3 .gitignore1

Configuration File Relationships

Configuration Directive Mapping to Runtime Behavior

The following diagram maps natural language concepts to specific configuration directives and code symbols used in the system:

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

graph TB
    subgraph "docker-compose.yml Directives"
        Version["version: '3.8'"]
MosqService["services.mosquitto"]
MosqImage["image: eclipse-mosquitto:latest"]
MosqContainer["container_name: mosquitto"]
MosqVolume["volumes:\n./mosquitto.conf:/mosquitto/config/mosquitto.conf"]
MosqRestart["restart: unless-stopped"]
CFService["services.cloudflared"]
CFImage["image: cloudflare/cloudflared:latest"]
CFContainer["container_name: cloudflared"]
CFCommand["command: tunnel --no-autoupdate run --token"]
CFEnv["environment:\nCLOUDFLARE_TUNNEL_TOKEN"]
CFRestart["restart: unless-stopped"]
end
    
    subgraph "mosquitto.conf Directives"
        Listener1883["listener 1883"]
AllowAnon["allow_anonymous true"]
Listener9001["listener 9001"]
ProtocolWS["protocol websockets"]
end
    
    subgraph ".env Variables"
        TunnelToken["CLOUDFLARE_TUNNEL_TOKEN=<value>"]
end
    
    subgraph "Runtime Behavior"
        TCPPort["TCP MQTT on port 1883"]
WSPort["WebSocket MQTT on port 9001"]
NoAuth["No authentication required"]
TunnelAuth["Tunnel authentication to Cloudflare"]
end
    
 
   Listener1883 --> TCPPort
 
   Listener9001 --> WSPort
 
   ProtocolWS --> WSPort
 
   AllowAnon --> NoAuth
    
 
   TunnelToken --> CFEnv
 
   CFEnv --> TunnelAuth
    
 
   MosqVolume -.->|mounts| Listener1883
 
   MosqVolume -.->|mounts| AllowAnon
 
   MosqVolume -.->|mounts| Listener9001
 
   MosqVolume -.->|mounts| ProtocolWS

docker-compose.yml Reference

The docker-compose.yml file defines the multi-container application using Docker Compose specification version 3.8. It orchestrates two services: mosquitto (MQTT broker) and cloudflared (tunnel connector).

graph TB
    Root["docker-compose.yml"]
Version["version: '3.8'\n(line 1)"]
Services["services:\n(line 3)"]
MosqService["mosquitto:\n(line 4)"]
MosqImage["image: eclipse-mosquitto:latest\n(line 5)"]
MosqContainer["container_name: mosquitto\n(line 6)"]
MosqVolumes["volumes:\n(line 7)"]
MosqVolMount["./mosquitto.conf:/mosquitto/config/mosquitto.conf\n(line 8)"]
MosqRestart["restart: unless-stopped\n(line 9)"]
CFService["cloudflared:\n(line 11)"]
CFImage["image: cloudflare/cloudflared:latest\n(line 12)"]
CFContainer["container_name: cloudflared\n(line 13)"]
CFCommand["command: tunnel --no-autoupdate run --token $CLOUDFLARE_TUNNEL_TOKEN\n(line 14)"]
CFRestart["restart: unless-stopped\n(line 15)"]
CFEnv["environment:\n(line 16)"]
CFEnvToken["- CLOUDFLARE_TUNNEL_TOKEN\n(line 17)"]
Root --> Version
 
   Root --> Services
 
   Services --> MosqService
 
   Services --> CFService
    
 
   MosqService --> MosqImage
 
   MosqService --> MosqContainer
 
   MosqService --> MosqVolumes
 
   MosqService --> MosqRestart
 
   MosqVolumes --> MosqVolMount
    
 
   CFService --> CFImage
 
   CFService --> CFContainer
 
   CFService --> CFCommand
 
   CFService --> CFRestart
 
   CFService --> CFEnv
 
   CFEnv --> CFEnvToken

File Structure

Sources: docker-compose.yml:1-18

Service: mosquitto

Directives

DirectiveValueLineDescription
imageeclipse-mosquitto:latest5Docker Hub image for Eclipse Mosquitto broker. Uses the latest tag, which tracks the most recent stable release.
container_namemosquitto6Static container name. Used by cloudflared service for DNS resolution via Docker’s internal DNS server.
volumes./mosquitto.conf:/mosquitto/config/mosquitto.conf7-8Bind mount that injects custom configuration. Host path is relative to docker-compose.yml location. Container path is the default Mosquitto config location.
restartunless-stopped9Restart policy. Container automatically restarts on failure or daemon restart, but not if manually stopped.

Sources: docker-compose.yml:4-9

Volume Mount Behavior

The volume directive at docker-compose.yml8 creates a bind mount from the host filesystem:

  • Host path: ./mosquitto.conf (relative to the directory containing docker-compose.yml)
  • Container path: /mosquitto/config/mosquitto.conf
  • Mount type: Bind mount (read-only by default in this configuration)
  • Effect: Overrides the default Mosquitto configuration with custom listener definitions

The Mosquitto process reads this file at startup. Changes to the host file require container restart to take effect.

Sources: docker-compose.yml:7-8

Service: cloudflared

Directives

DirectiveValueLineDescription
imagecloudflare/cloudflared:latest12Official Cloudflare tunnel connector image. The latest tag should be pinned to specific versions in production.
container_namecloudflared13Static container name for identification and logging.
commandtunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN}14Overrides the default container entrypoint. Runs the tunnel in persistent mode with auto-update disabled. The ${CLOUDFLARE_TUNNEL_TOKEN} is substituted from the environment.
restartunless-stopped15Matches the restart policy of the mosquitto service for consistency.
environmentCLOUDFLARE_TUNNEL_TOKEN16-17Declares that the CLOUDFLARE_TUNNEL_TOKEN environment variable should be passed from the host environment to the container. Value is sourced from the .env file.

Sources: docker-compose.yml:11-18

Command Breakdown

The command directive at docker-compose.yml14 constructs the following runtime command:

tunnel --no-autoupdate run --token <token_value>

Command components:

  • tunnel - The cloudflared subcommand for tunnel operations
  • --no-autoupdate - Disables automatic updates of the cloudflared binary (recommended in containerized environments)
  • run - Starts the tunnel in persistent connection mode
  • --token - Authentication token for the tunnel (required for cloudflared tunnel connectivity)
  • ${CLOUDFLARE_TUNNEL_TOKEN} - Environment variable substitution performed by Docker Compose

Sources: docker-compose.yml14

Network Configuration

Docker Compose automatically creates a bridge network for inter-service communication. The default network name follows the pattern <project-name>_default.

Service Discovery:

  • The mosquitto service is resolvable via DNS at hostname mosquitto
  • The cloudflared service references this hostname when configured in the Cloudflare dashboard
  • No explicit networks section is required; services communicate on the default bridge network

Port Exposure:

  • Neither service exposes ports to the host (ports directive not used)
  • All external access routes through the Cloudflare Tunnel
  • Internal communication occurs on Docker’s isolated network

Sources: docker-compose.yml:1-18


graph TB
    Conf["mosquitto.conf"]
Block1["Listener Configuration 1"]
L1Port["listener 1883\n(line 1)"]
L1Anon["allow_anonymous true\n(line 2)"]
Block2["Listener Configuration 2"]
L2Port["listener 9001\n(line 4)"]
L2Proto["protocol websockets\n(line 5)"]
Conf --> Block1
 
   Conf --> Block2
    
 
   Block1 --> L1Port
 
   Block1 --> L1Anon
    
 
   Block2 --> L2Port
 
   Block2 --> L2Proto
    
    Runtime1["Runtime Effect:\nTCP MQTT on 0.0.0.0:1883\nNo authentication required"]
Runtime2["Runtime Effect:\nWebSocket MQTT on 0.0.0.0:9001\nUses same allow_anonymous setting"]
L1Port --> Runtime1
 
   L1Anon --> Runtime1
 
   L2Port --> Runtime2
 
   L2Proto --> Runtime2

mosquitto.conf Reference

The mosquitto.conf file configures the Eclipse Mosquitto MQTT broker. It defines two listeners with different protocols.

File Structure

Sources: mosquitto.conf:1-6

Listener Directives

Listener 1: TCP MQTT (Port 1883)

DirectiveValueLineDescription
listener18831Defines a listener on port 1883 (standard MQTT port). Binds to all interfaces (0.0.0.0) by default.
allow_anonymoustrue2Permits connections without username/password authentication. Applies to this listener and subsequent listeners unless overridden.

Protocol: Native MQTT (TCP-based)
Bind address: 0.0.0.0 (all interfaces, default when not specified)
Authentication: None (anonymous access enabled)
Encryption: None (plaintext). Encryption is handled by Cloudflare Tunnel at the edge.

Sources: mosquitto.conf:1-2

Listener 2: WebSocket MQTT (Port 9001)

DirectiveValueLineDescription
listener90014Defines a listener on port 9001. This port is referenced by the Cloudflare Tunnel configuration.
protocolwebsockets5Enables WebSocket protocol for this listener. Allows browser-based MQTT clients to connect.

Protocol: MQTT over WebSockets
Bind address: 0.0.0.0 (default)
Authentication: Inherits allow_anonymous true from line 2
Encryption: None at broker level (handled by Cloudflare Tunnel)

Sources: mosquitto.conf:4-5

Directive Scope and Inheritance

The allow_anonymous true directive at mosquitto.conf2 has global scope and applies to all subsequent listeners. The configuration does not explicitly set allow_anonymous for the second listener, so it inherits the global setting.

Scope hierarchy:

  1. Global directives apply to all listeners
  2. Per-listener directives override global settings
  3. Subsequent global directives override previous global directives

In this configuration:

  • Line 2 sets global anonymous access to true
  • Both listeners (lines 1 and 4) permit anonymous connections

Sources: mosquitto.conf:1-5

graph LR
    Client["MQTT Client\n(Browser or Native)"]
CFEdge["Cloudflare Edge\n(TLS termination)"]
Tunnel["Cloudflare Tunnel\n(cloudflared container)"]
Mosq9001["mosquitto:9001\n(WebSocket listener)"]
Mosq1883["mosquitto:1883\n(TCP listener)"]
Client -->|WSS/HTTPS| CFEdge
 
   CFEdge -->|Encrypted tunnel| Tunnel
 
   Tunnel -->|HTTP to mosquitto:9001| Mosq9001
    
 
   Mosq9001 -.->|Not directly accessible| Mosq1883
    
    Note1["listener 9001\nprotocol websockets\n(mosquitto.conf:4-5)"]
Note2["listener 1883\n(mosquitto.conf:1)"]
Mosq9001 --- Note1
    Mosq1883 --- Note2

Protocol Mapping to Cloudflare Tunnel

The Cloudflare Tunnel must be configured to route traffic to http://mosquitto:9001:

Critical configuration requirement: The Cloudflare Tunnel public hostname must route to http://mosquitto:9001 (the WebSocket listener), not port 1883. Port 1883 is the native MQTT protocol and cannot be proxied through HTTP-based Cloudflare Tunnels.

Sources: mosquitto.conf:1-5 docker-compose.yml:6-13

Security Implications

The allow_anonymous true directive at mosquitto.conf2 disables authentication:

Security PropertyStatusImplication
Username/password authenticationDisabledAny client can connect without credentials
Access control lists (ACLs)Not configuredAll topics are readable and writable by all clients
TLS/SSL at broker levelNot configuredPlaintext MQTT within Docker network (acceptable because traffic is encrypted by Cloudflare Tunnel before reaching the internet)

Recommended for: Development, testing, or trusted environments where the Cloudflare Tunnel provides sufficient access control.

Not recommended for: Production environments with multiple tenants or sensitive data without additional access controls.

For authentication and ACL configuration, see page 6.1.

Sources: mosquitto.conf2


Environment Variables Reference

Environment variables provide runtime configuration, particularly for sensitive credentials that must not be committed to version control.

CLOUDFLARE_TUNNEL_TOKEN

Variable name: CLOUDFLARE_TUNNEL_TOKEN
Defined in: .env (user-created, not version controlled)
Template in: .env.sample:1
Referenced in: docker-compose.yml:14,17
Used by: cloudflared service

Purpose

This variable contains the authentication token for the Cloudflare Tunnel. The token is a long-lived credential that authorizes the cloudflared container to establish an outbound connection to Cloudflare’s network and receive inbound traffic routed through the tunnel.

Token format: Base64-encoded JSON Web Token (JWT) with tunnel metadata and credentials.

Sources: .env.sample1 docker-compose.yml:14-17

Token Lifecycle

Sources: .env.sample1 docker-compose.yml:14-17

Configuration Method

The token is injected into the cloudflared container via two mechanisms:

  1. Environment variable declaration at docker-compose.yml:16-17:

This instructs Docker Compose to pass the variable from the host environment to the container.

  1. Command substitution at docker-compose.yml14:

Docker Compose performs variable substitution before starting the container, replacing ${CLOUDFLARE_TUNNEL_TOKEN} with the actual token value.

Sources: docker-compose.yml:14-17

Security Best Practices

PracticeImplementationPurpose
Never commit to version control.gitignore contains .env at line 1Prevents accidental token exposure in Git history
Use .env.sample as templateContains placeholder your_tokenProvides documentation without exposing real credentials
Restrict file permissionschmod 600 .env (not enforced by repository)Limits token access to file owner on Unix systems
Rotate tokens periodicallyRegenerate in Cloudflare dashboardLimits exposure window if token is compromised
Use separate tokens per environmentCreate distinct tunnels for dev/staging/prodLimits blast radius of token compromise

Sources: .env.sample1 .gitignore1

Validation and Troubleshooting

Token validation:

  • Token is validated when cloudflared attempts to connect to Cloudflare
  • Invalid tokens result in authentication failures logged in container output
  • No local validation occurs before container startup

Common issues:

IssueSymptomResolution
Token not setdocker-compose warning about undefined variableCreate .env file with CLOUDFLARE_TUNNEL_TOKEN=<value>
Token invalidcloudflared logs authentication errorsRegenerate token in Cloudflare dashboard
Token expiredTunnel disconnects after previously workingCheck Cloudflare dashboard for token status
Wrong tokenTunnel connects to different configurationVerify token matches intended tunnel in dashboard

Sources: docker-compose.yml:14-17 .env.sample1


sequenceDiagram
    participant DC as docker-compose
    participant Env as .env file
    participant DCFile as docker-compose.yml
    participant MConf as mosquitto.conf
    participant MosqC as mosquitto container
    participant CFC as cloudflared container
    
    Note over DC,CFC: Configuration Loading Phase
    
    DC->>Env: Read CLOUDFLARE_TUNNEL_TOKEN
    DC->>DCFile: Parse service definitions
    
    Note over DCFile: services.mosquitto (lines 4-9)
    Note over DCFile: services.cloudflared (lines 11-17)
    
    DC->>MosqC: Create container from eclipse-mosquitto:latest
    DC->>MosqC: Mount ./mosquitto.conf to /mosquitto/config/mosquitto.conf
    
    DC->>CFC: Create container from cloudflare/cloudflared:latest
    DC->>CFC: Set environment variable CLOUDFLARE_TUNNEL_TOKEN
    DC->>CFC: Set command with --token flag
    
    Note over MosqC,CFC: Container Startup Phase
    
    MosqC->>MConf: Read configuration file
    Note over MConf: listener 1883 (line 1)
    Note over MConf: allow_anonymous true (line 2)
    Note over MConf: listener 9001 (line 4)
    Note over MConf: protocol websockets (line 5)
    
    MosqC->>MosqC: Initialize listeners 1883 and 9001
    
    CFC->>CFC: Execute tunnel run with token
    CFC->>CFC: Establish connection to Cloudflare

Configuration Loading Sequence

The following diagram shows the order in which configuration is loaded and applied during system startup:

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

Service Configuration Matrix

The following table maps configuration sources to their effects on each service:

Configuration AspectSource FileLine(s)Applies ToEffect
MQTT TCP listenermosquitto.conf1mosquitto serviceOpens port 1883 for MQTT TCP connections
Anonymous accessmosquitto.conf2mosquitto serviceAllows connections without authentication
WebSocket listenermosquitto.conf4-5mosquitto serviceOpens port 9001 for WebSocket MQTT connections
Mosquitto imagedocker-compose.yml5mosquitto serviceUses eclipse-mosquitto:latest
Mosquitto container namedocker-compose.yml6mosquitto serviceContainer named mosquitto
Configuration mountdocker-compose.yml8mosquitto serviceMounts mosquitto.conf to /mosquitto/config/mosquitto.conf
Mosquitto restart policydocker-compose.yml9mosquitto serviceRestarts unless explicitly stopped
Cloudflared imagedocker-compose.yml12cloudflared serviceUses cloudflare/cloudflared:latest
Cloudflared container namedocker-compose.yml13cloudflared serviceContainer named cloudflared
Tunnel commanddocker-compose.yml14cloudflared serviceRuns tunnel --no-autoupdate run --token
Cloudflared restart policydocker-compose.yml15cloudflared serviceRestarts unless explicitly stopped
Tunnel token.env1cloudflared serviceAuthenticates tunnel with Cloudflare

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

graph TB
    Root["docker-compose.yml root"]
Version["version: '3.8'"]
Services["services:] MosqService[mosquitto:] MosqProps[Properties:\n- image\n- container_name\n- volumes\n- restart"]
CFService["cloudflared:] CFProps[Properties:\n- image\n- container_name\n- command\n- restart\n- environment"]
Root --> Version
 
   Root --> Services
 
   Services --> MosqService
 
   Services --> CFService
 
   MosqService --> MosqProps
 
   CFService --> CFProps

Configuration File Syntax

docker-compose.yml Syntax

The docker-compose.yml file follows Docker Compose version 3.8 specification. Key structural elements:

Sources: docker-compose.yml:1-18

graph LR
    Conf["mosquitto.conf"]
Block1["Listener Block 1:\nlistener 1883\nallow_anonymous true"]
Block2["Listener Block 2:\nlistener 9001\nprotocol websockets"]
Conf --> Block1
 
   Conf --> Block2
    
 
   Block1 --> Port1["Port: 1883"]
Block1 --> Anon["Anonymous: true"]
Block2 --> Port2["Port: 9001"]
Block2 --> Proto["Protocol: websockets"]

mosquitto.conf Syntax

The mosquitto.conf file uses the Mosquitto broker configuration format. Each directive appears on its own line:

Sources: mosquitto.conf:1-6

.env File Syntax

The .env file uses simple KEY=value syntax, one variable per line:

CLOUDFLARE_TUNNEL_TOKEN=your_token_here

Sources: .env.sample:1-3

Configuration Validation

The system validates configuration at multiple stages:

Validation StageComponentWhat Is ValidatedFailure Behavior
Compose file parsedocker-compose CLIYAML syntax of docker-compose.ymlExit with parse error
Environment variable resolutiondocker-compose CLIPresence of ${CLOUDFLARE_TUNNEL_TOKEN} in .envWarning or substitution with empty string
Mosquitto config parsemosquitto processSyntax of mosquitto.conf directivesContainer logs error and may exit
Tunnel authenticationcloudflared processValidity of CLOUDFLARE_TUNNEL_TOKENConnection fails, logged in container output
Port bindingDocker EngineAvailability of specified portsContainer fails to start if ports in use

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

Configuration Override Hierarchy

When configuration values can be specified in multiple locations, the following precedence applies:

  1. Command-line arguments to docker-compose (highest precedence)
  2. Environment variables in the shell running docker-compose
  3. .env file in the project directory
  4. Default values in docker-compose.yml
  5. Container defaults from images (lowest precedence)

For the mosquitto service, the configuration file mosquitto.conf:1-6 is mounted as a volume and overrides all default Mosquitto configurations.

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

Cross-Reference Index

The following table provides a quick reference for locating configuration settings:

Setting NameConfiguration FileLine Number(s)
versiondocker-compose.yml1
services.mosquitto.imagedocker-compose.yml5
services.mosquitto.container_namedocker-compose.yml6
services.mosquitto.volumesdocker-compose.yml7-8
services.mosquitto.restartdocker-compose.yml9
services.cloudflared.imagedocker-compose.yml12
services.cloudflared.container_namedocker-compose.yml13
services.cloudflared.commanddocker-compose.yml14
services.cloudflared.restartdocker-compose.yml15
services.cloudflared.environmentdocker-compose.yml16-17
listener (port 1883)mosquitto.conf1
allow_anonymousmosquitto.conf2
listener (port 9001)mosquitto.conf4
protocolmosquitto.conf5
CLOUDFLARE_TUNNEL_TOKEN.env.sample (template)1

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

Dismiss

Refresh this wiki

Enter email to refresh