This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Troubleshooting
Loading…
Troubleshooting
Relevant source files
Purpose and Scope
This page provides diagnostic procedures and solutions for common issues encountered when deploying and operating the Docker MQTT Mosquitto with Cloudflare Tunnel system. It covers container startup failures, connection problems, configuration errors, and debugging techniques.
For information about the CI/CD automated health checks, see Continuous Integration. For production monitoring strategies, see Monitoring and Health Checks. For initial setup procedures, see Getting Started.
Diagnostic Decision Tree
The following flowchart provides a systematic approach to diagnosing system issues:
Sources : README.md:74-84 docker-compose.yml:1-18 mosquitto.conf:1-6
flowchart TD
Start["Issue Reported"] --> CheckContainers{"docker compose ps\nAll containers running?"}
CheckContainers -->|No| IdentifyDown{"Which container\nis down?"}
CheckContainers -->|Yes| CheckTunnel["Check tunnel connectivity"]
IdentifyDown -->|mosquitto| MosquittoDown["Check mosquitto logs:\ndocker compose logs mosquitto"]
IdentifyDown -->|cloudflared| CloudflaredDown["Check cloudflared logs:\ndocker compose logs cloudflared"]
IdentifyDown -->|Both| BothDown["Check docker-compose.yml\nand .env configuration"]
MosquittoDown --> MosquittoErrors{"Error type?"}
MosquittoErrors -->|Config syntax| CheckMosquittoConf["Validate mosquitto.conf:1-5\nlistener directives"]
MosquittoErrors -->|Port binding| CheckPortConflict["Check port 1883/9001\nconflicts on host"]
MosquittoErrors -->|Volume mount| CheckVolumeMount["Verify ./mosquitto.conf\nfile exists and readable"]
CloudflaredDown --> CloudflaredErrors{"Error type?"}
CloudflaredErrors -->|Authentication failed| CheckToken["Verify CLOUDFLARE_TUNNEL_TOKEN\nin .env file"]
CloudflaredErrors -->|Tunnel not found| RecreateToken["Generate new token\nin Cloudflare dashboard"]
CloudflaredErrors -->|Connection refused| CheckNetwork["Verify internet connectivity\nand firewall rules"]
BothDown --> CheckDockerCompose["Validate docker-compose.yml\nsyntax and structure"]
CheckTunnel --> TunnelTest{"Can connect via\npublic hostname?"}
TunnelTest -->|No| CheckHostname["Verify hostname in\nCloudflare dashboard\npoints to mosquitto:9001"]
TunnelTest -->|Yes| CheckMQTT["Test MQTT connection\non port 443"]
CheckMQTT --> MQTTTest{"MQTT publish/\nsubscribe works?"}
MQTTTest -->|No| CheckProtocol["Verify protocol:\nWebSockets required\nfor tunnel connection"]
MQTTTest -->|Yes| Resolved["Issue resolved"]
CheckMosquittoConf --> Restart["docker compose restart mosquitto"]
CheckPortConflict --> StopConflicting["Stop conflicting service\nor change port mapping"]
CheckVolumeMount --> FixMount["Create/fix mosquitto.conf\nand verify path"]
CheckToken --> UpdateEnv["Update .env and\ndocker compose restart cloudflared"]
RecreateToken --> UpdateEnv
CheckNetwork --> FixNetwork["Check DNS/firewall/proxy"]
CheckDockerCompose --> FixCompose["Fix syntax errors\nand docker compose up"]
CheckHostname --> UpdateHostname["Update hostname config\nin Cloudflare dashboard"]
CheckProtocol --> UseWebSockets["Use wss:// protocol\non port 443"]
Restart --> Resolved
StopConflicting --> Resolved
FixMount --> Resolved
UpdateEnv --> Resolved
FixNetwork --> Resolved
FixCompose --> Resolved
UpdateHostname --> Resolved
UseWebSockets --> Resolved
Common Issues and Solutions
Container Startup Failures
| Issue | Symptoms | Diagnosis | Solution |
|---|---|---|---|
| Missing tunnel token | cloudflared container exits immediately | docker compose logs cloudflared shows authentication error | Create .env file from .env.sample template and populate CLOUDFLARE_TUNNEL_TOKEN |
| Invalid token | cloudflared shows “tunnel credentials invalid” | Token rejected by Cloudflare API | Generate new token in Cloudflare Zero Trust dashboard and update .env |
| Configuration syntax error | mosquitto container crashes on startup | docker compose logs mosquitto shows parse error | Validate mosquitto.conf:1-6 syntax, ensure listener directives are properly formatted |
| Port conflict | mosquitto fails to bind ports | Error: “Address already in use” | Identify conflicting service with sudo lsof -i :1883 and sudo lsof -i :9001, then stop conflicting service |
| Volume mount failure | mosquitto cannot read configuration | Permission denied or file not found error | Verify ./mosquitto.conf exists and has read permissions: ls -l mosquitto.conf |
| Image pull failure | Container fails to start with image error | Cannot pull eclipse-mosquitto:latest or cloudflare/cloudflared:latest | Check Docker Hub connectivity, verify registry access, or use explicit image versions |
Sources : docker-compose.yml:4-17 mosquitto.conf:1-6 .env.sample1
Connection and Tunnel Issues
The following diagram illustrates the connection verification process:
Connection Troubleshooting Table :
| Failure Point | Test Command | Expected Result | Fix |
|---|---|---|---|
| Tunnel not established | `docker compose logs cloudflared | grep “Connection established”` | Should see “Connection established” message |
| Mosquitto not listening | docker compose exec mosquitto netstat -tlnp | Should show :1883 and :9001 listeners | Check mosquitto.conf:1-5 configuration, restart container |
| DNS resolution failure | docker compose exec cloudflared nslookup mosquitto | Should resolve to container IP | Verify container_name: mosquitto in docker-compose.yml6 |
| Public hostname misconfigured | Check Cloudflare dashboard tunnel configuration | URL should point to mosquitto:9001 with HTTP service type | Update hostname configuration in Cloudflare dashboard |
| WebSocket protocol mismatch | Client connection logs show protocol error | Client must use wss:// protocol on port 443 | Update client to use WebSockets over SSL/TLS |
Sources : docker-compose.yml:11-17 mosquitto.conf:4-5 README.md:63-67
Health Check Verification
The CI pipeline implements a health check strategy that can be replicated for manual troubleshooting:
Manual Health Check Procedure :
sequenceDiagram
participant User as "User/CI System"
participant Docker as "docker-compose"
participant MosqContainer as "mosquitto container"
participant HealthCheck as "Health Check Loop"
User->>Docker: docker-compose up -d mosquitto
Docker->>MosqContainer: Start container
MosqContainer->>MosqContainer: Load /mosquitto/config/mosquitto.conf
MosqContainer->>MosqContainer: Bind listener 1883
MosqContainer->>MosqContainer: Bind listener 9001
User->>HealthCheck: Start health check loop
Note over HealthCheck: Max 10 attempts, 10 second intervals
loop Until healthy or max attempts
HealthCheck->>Docker: docker-compose ps --format json
Docker-->>HealthCheck: Container status JSON
HealthCheck->>HealthCheck: Parse 'State' field
alt State == "running"
HealthCheck-->>User: ✓ Service healthy
else State != "running"
HealthCheck->>HealthCheck: Sleep 10 seconds
HealthCheck->>HealthCheck: Increment attempt counter
end
end
alt Max attempts exceeded
HealthCheck-->>User: ✗ Health check failed after 100s
User->>Docker: docker-compose logs mosquitto
Docker-->>User: Error logs
end
Sources : .github/workflows/ci.yml:17-37 docker-compose.yml:4-9 mosquitto.conf:1-6
Configuration Validation
Validating docker-compose.yml
The following elements must be correctly configured in docker-compose.yml:1-18:
Validation Commands :
Sources : docker-compose.yml:1-18 mosquitto.conf:1-6 .env.sample1
Validating mosquitto.conf
The mosquitto.conf:1-6 file has a simple structure but specific syntax requirements:
| Line | Directive | Purpose | Common Errors |
|---|---|---|---|
| 1 | listener 1883 | Native MQTT protocol port | Missing port number, invalid port range (1-65535) |
| 2 | allow_anonymous true | Authentication setting | Typo in allow_anonymous, missing boolean value |
| 3 | (blank) | Separator | N/A |
| 4 | listener 9001 | WebSocket protocol port | Duplicate port number, port conflict with line 1 |
| 5 | protocol websockets | Protocol specification for listener | Typo in websockets, missing protocol directive |
Validation Procedure :
Sources : mosquitto.conf:1-6
Environment Variable Issues
Missing or Invalid CLOUDFLARE_TUNNEL_TOKEN
The CLOUDFLARE_TUNNEL_TOKEN environment variable is the critical authentication credential for establishing the tunnel connection.
Common Token Issues :
| Problem | Symptom | Root Cause | Solution |
|---|---|---|---|
| Token not set | cloudflared exits with “missing token” error | .env file not created or empty | Copy .env.sample1 to .env and populate token |
| Token syntax error | Authentication fails immediately | Token contains extra spaces, newlines, or quotes | Ensure token is on single line with no surrounding quotes: CLOUDFLARE_TUNNEL_TOKEN=eyJh... |
| Token expired/revoked | “unauthorized” or “tunnel not found” error | Token regenerated in Cloudflare dashboard or tunnel deleted | Generate new token from Cloudflare dashboard and update .env |
| Wrong token | Tunnel connects but routes to wrong service | Token from different tunnel configuration | Verify token matches the tunnel name in Cloudflare dashboard |
| .env not loaded | Variable shows as empty in container | .env file not in correct directory or not named exactly .env | Verify .env is in same directory as docker-compose.yml |
Debugging Environment Variables :
Sources : docker-compose.yml:16-17 .env.sample1 README.md53
flowchart TB
ViewLogs["View Container Logs"]
ViewLogs --> MosqLogs["docker compose logs mosquitto"]
ViewLogs --> CFDLogs["docker compose logs cloudflared"]
ViewLogs --> AllLogs["docker compose logs"]
MosqLogs --> MosqSuccess["Success Indicators"]
MosqLogs --> MosqErrors["Error Indicators"]
MosqSuccess --> MS1["'Opening ipv4 listen socket on port 1883'"]
MosqSuccess --> MS2["'Opening websockets listen socket on port 9001'"]
MosqSuccess --> MS3["'mosquitto version X.X.X running'"]
MosqErrors --> ME1["'Error: Unable to open config file'\n→ Volume mount issue"]
MosqErrors --> ME2["'Error: Invalid bridge parameter'\n→ Config syntax error"]
MosqErrors --> ME3["'Error: Address already in use'\n→ Port conflict"]
CFDLogs --> CFDSuccess["Success Indicators"]
CFDLogs --> CFDErrors["Error Indicators"]
CFDSuccess --> CS1["'Connection established'"]
CFDSuccess --> CS2["'Registered tunnel connection'"]
CFDSuccess --> CS3["'Serving tunnel'"]
CFDErrors --> CE1["'authentication failed'\n→ Invalid token"]
CFDErrors --> CE2["'tunnel not found'\n→ Token/tunnel mismatch"]
CFDErrors --> CE3["'connection refused'\n→ Network issue"]
Log Analysis
Reading Container Logs
Both containers produce diagnostic output that can be analyzed for troubleshooting:
Log Analysis Commands :
Sources : docker-compose.yml:4-17
Network Diagnostics
Docker Network Verification
Both containers must be on the same Docker network for internal DNS resolution to function:
Sources : docker-compose.yml:1-18 README.md64
Cloudflare Dashboard Verification
Issues may originate from misconfiguration in the Cloudflare Zero Trust dashboard:
| Configuration Item | Location | Expected Value | Common Mistakes |
|---|---|---|---|
| Tunnel type | Networks → Tunnels → Tunnel details | Cloudflared | Wrong tunnel type selected |
| Tunnel status | Networks → Tunnels → Tunnel list | “HEALTHY” with green indicator | Shows as “DOWN” if container not running or token invalid |
| Public hostname | Networks → Tunnels → Public Hostnames tab | Subdomain and domain configured | Missing or incorrect hostname |
| Service type | Public hostname configuration | HTTP | HTTPS selected (creates double encryption issue) |
| Service URL | Public hostname configuration | mosquitto:9001 | Incorrect hostname (e.g., localhost, IP address) or wrong port |
Verification Steps :
- Navigate to Cloudflare Zero Trust dashboard
- Go to Networks → Tunnels
- Locate your tunnel and verify status shows “HEALTHY”
- Click tunnel name to view details
- Check Public Hostname tab for correct configuration:
- Service: HTTP (not HTTPS)
- URL:
mosquitto:9001(matches docker-compose.yml6 container name and mosquitto.conf4 listener port)
Sources : README.md:29-72 docker-compose.yml6 mosquitto.conf:4-5
Client Connection Issues
Protocol and Port Requirements
External clients must use WebSockets over SSL/TLS on port 443:
| Client Protocol | Port | Result |
|---|---|---|
wss://subdomain.domain | 443 | ✓ Correct - WebSockets over SSL through tunnel |
mqtt://subdomain.domain | 443 | ✗ Wrong protocol - Native MQTT not supported through tunnel |
ws://subdomain.domain | 443 | ✗ Wrong protocol - Non-SSL WebSocket rejected |
wss://subdomain.domain | 1883 | ✗ Wrong port - Port 1883 not exposed through tunnel |
mqtt://localhost | 1883 | ✓ Works only from Docker host (not through tunnel) |
Client Configuration Example :
Testing Connection :
Sources : README.md:66-82 mosquitto.conf:4-5
Advanced Debugging Techniques
Container Introspection
Resource Constraints
Complete System Reset
Sources : docker-compose.yml:1-18
Related Issues and Resources
- GitHub Issue #25 : Additional troubleshooting information for connection issues (README.md84)
- For protected branch features with ACL restrictions, see Protected Branch Features
- For production monitoring strategies, see Monitoring and Health Checks
- For CI/CD health check implementation details, see Continuous Integration
- For initial setup guidance, see Getting Started
Summary of Common Error Messages
| Error Message | File/Component | Likely Cause | Solution Reference |
|---|---|---|---|
| “Address already in use” | mosquitto | Port 1883 or 9001 conflict | [Container Startup Failures](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Container Startup Failures) |
| “Unable to open config file” | mosquitto | Volume mount issue | [Container Startup Failures](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Container Startup Failures) |
| “authentication failed” | cloudflared | Invalid CLOUDFLARE_TUNNEL_TOKEN | [Environment Variable Issues](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Environment Variable Issues) |
| “tunnel not found” | cloudflared | Token/tunnel mismatch | [Environment Variable Issues](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Environment Variable Issues) |
| “connection refused” | cloudflared | Network/firewall issue | [Network Diagnostics](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Network Diagnostics) |
| “protocol error” | Client | Using mqtt:// instead of wss:// | [Client Connection Issues](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Client Connection Issues) |
| “DNS resolution failed” | cloudflared | Container name mismatch | [Network Diagnostics](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Network Diagnostics) |
| “Invalid bridge parameter” | mosquitto | Config syntax error in mosquitto.conf | [Configuration Validation](https://github.com/jzombie/docker-mqtt-mosquitto-cloudflare-tunnel/blob/59f1274c/Configuration Validation) |
Sources : docker-compose.yml:1-18 mosquitto.conf:1-6 .env.sample1 README.md:1-93
Dismiss
Refresh this wiki
Enter email to refresh