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 definitionsmosquitto.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:
| File | Purpose | Version Controlled | Contains Secrets | Format |
|---|---|---|---|---|
docker-compose.yml | Service orchestration and container definitions | Yes | No | YAML (Compose v3.8) |
mosquitto.conf | MQTT broker configuration (listeners, protocols, access control) | Yes | No | Mosquitto INI-style |
.env | Runtime secrets and environment variables | No (.gitignore) | Yes | KEY=VALUE pairs |
.env.sample | Template for .env file | Yes | No | KEY=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
| Directive | Value | Line | Description |
|---|---|---|---|
image | eclipse-mosquitto:latest | 5 | Docker Hub image for Eclipse Mosquitto broker. Uses the latest tag, which tracks the most recent stable release. |
container_name | mosquitto | 6 | Static container name. Used by cloudflared service for DNS resolution via Docker’s internal DNS server. |
volumes | ./mosquitto.conf:/mosquitto/config/mosquitto.conf | 7-8 | Bind mount that injects custom configuration. Host path is relative to docker-compose.yml location. Container path is the default Mosquitto config location. |
restart | unless-stopped | 9 | Restart 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 containingdocker-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
| Directive | Value | Line | Description |
|---|---|---|---|
image | cloudflare/cloudflared:latest | 12 | Official Cloudflare tunnel connector image. The latest tag should be pinned to specific versions in production. |
container_name | cloudflared | 13 | Static container name for identification and logging. |
command | tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN} | 14 | Overrides the default container entrypoint. Runs the tunnel in persistent mode with auto-update disabled. The ${CLOUDFLARE_TUNNEL_TOKEN} is substituted from the environment. |
restart | unless-stopped | 15 | Matches the restart policy of the mosquitto service for consistency. |
environment | CLOUDFLARE_TUNNEL_TOKEN | 16-17 | Declares 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
mosquittoservice is resolvable via DNS at hostnamemosquitto - The
cloudflaredservice references this hostname when configured in the Cloudflare dashboard - No explicit
networkssection is required; services communicate on the default bridge network
Port Exposure:
- Neither service exposes ports to the host (
portsdirective 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)
| Directive | Value | Line | Description |
|---|---|---|---|
listener | 1883 | 1 | Defines a listener on port 1883 (standard MQTT port). Binds to all interfaces (0.0.0.0) by default. |
allow_anonymous | true | 2 | Permits 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)
| Directive | Value | Line | Description |
|---|---|---|---|
listener | 9001 | 4 | Defines a listener on port 9001. This port is referenced by the Cloudflare Tunnel configuration. |
protocol | websockets | 5 | Enables 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:
- Global directives apply to all listeners
- Per-listener directives override global settings
- 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 Property | Status | Implication |
|---|---|---|
| Username/password authentication | Disabled | Any client can connect without credentials |
| Access control lists (ACLs) | Not configured | All topics are readable and writable by all clients |
| TLS/SSL at broker level | Not configured | Plaintext 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:
- Environment variable declaration at docker-compose.yml:16-17:
This instructs Docker Compose to pass the variable from the host environment to the container.
- 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
| Practice | Implementation | Purpose |
|---|---|---|
| Never commit to version control | .gitignore contains .env at line 1 | Prevents accidental token exposure in Git history |
Use .env.sample as template | Contains placeholder your_token | Provides documentation without exposing real credentials |
| Restrict file permissions | chmod 600 .env (not enforced by repository) | Limits token access to file owner on Unix systems |
| Rotate tokens periodically | Regenerate in Cloudflare dashboard | Limits exposure window if token is compromised |
| Use separate tokens per environment | Create distinct tunnels for dev/staging/prod | Limits blast radius of token compromise |
Sources: .env.sample1 .gitignore1
Validation and Troubleshooting
Token validation:
- Token is validated when
cloudflaredattempts to connect to Cloudflare - Invalid tokens result in authentication failures logged in container output
- No local validation occurs before container startup
Common issues:
| Issue | Symptom | Resolution |
|---|---|---|
| Token not set | docker-compose warning about undefined variable | Create .env file with CLOUDFLARE_TUNNEL_TOKEN=<value> |
| Token invalid | cloudflared logs authentication errors | Regenerate token in Cloudflare dashboard |
| Token expired | Tunnel disconnects after previously working | Check Cloudflare dashboard for token status |
| Wrong token | Tunnel connects to different configuration | Verify 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 Aspect | Source File | Line(s) | Applies To | Effect |
|---|---|---|---|---|
| MQTT TCP listener | mosquitto.conf | 1 | mosquitto service | Opens port 1883 for MQTT TCP connections |
| Anonymous access | mosquitto.conf | 2 | mosquitto service | Allows connections without authentication |
| WebSocket listener | mosquitto.conf | 4-5 | mosquitto service | Opens port 9001 for WebSocket MQTT connections |
| Mosquitto image | docker-compose.yml | 5 | mosquitto service | Uses eclipse-mosquitto:latest |
| Mosquitto container name | docker-compose.yml | 6 | mosquitto service | Container named mosquitto |
| Configuration mount | docker-compose.yml | 8 | mosquitto service | Mounts mosquitto.conf to /mosquitto/config/mosquitto.conf |
| Mosquitto restart policy | docker-compose.yml | 9 | mosquitto service | Restarts unless explicitly stopped |
| Cloudflared image | docker-compose.yml | 12 | cloudflared service | Uses cloudflare/cloudflared:latest |
| Cloudflared container name | docker-compose.yml | 13 | cloudflared service | Container named cloudflared |
| Tunnel command | docker-compose.yml | 14 | cloudflared service | Runs tunnel --no-autoupdate run --token |
| Cloudflared restart policy | docker-compose.yml | 15 | cloudflared service | Restarts unless explicitly stopped |
| Tunnel token | .env | 1 | cloudflared service | Authenticates 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 Stage | Component | What Is Validated | Failure Behavior |
|---|---|---|---|
| Compose file parse | docker-compose CLI | YAML syntax of docker-compose.yml | Exit with parse error |
| Environment variable resolution | docker-compose CLI | Presence of ${CLOUDFLARE_TUNNEL_TOKEN} in .env | Warning or substitution with empty string |
| Mosquitto config parse | mosquitto process | Syntax of mosquitto.conf directives | Container logs error and may exit |
| Tunnel authentication | cloudflared process | Validity of CLOUDFLARE_TUNNEL_TOKEN | Connection fails, logged in container output |
| Port binding | Docker Engine | Availability of specified ports | Container 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:
- Command-line arguments to
docker-compose(highest precedence) - Environment variables in the shell running
docker-compose .envfile in the project directory- Default values in
docker-compose.yml - 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 Name | Configuration File | Line Number(s) |
|---|---|---|
version | docker-compose.yml | 1 |
services.mosquitto.image | docker-compose.yml | 5 |
services.mosquitto.container_name | docker-compose.yml | 6 |
services.mosquitto.volumes | docker-compose.yml | 7-8 |
services.mosquitto.restart | docker-compose.yml | 9 |
services.cloudflared.image | docker-compose.yml | 12 |
services.cloudflared.container_name | docker-compose.yml | 13 |
services.cloudflared.command | docker-compose.yml | 14 |
services.cloudflared.restart | docker-compose.yml | 15 |
services.cloudflared.environment | docker-compose.yml | 16-17 |
listener (port 1883) | mosquitto.conf | 1 |
allow_anonymous | mosquitto.conf | 2 |
listener (port 9001) | mosquitto.conf | 4 |
protocol | mosquitto.conf | 5 |
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