Add comprehensive caddy-docker-proxy integration with auto-labeling

- Reference caddy-docker-proxy GitHub project for automatic HTTPS
- Provide complete production-ready docker-compose.yml with Cloudflare DNS
- Add environment configuration (.env) and deployment instructions
- Document --transport http-streamable auto-labeling feature
- Show how auto-labeling eliminates manual caddy configuration
- Include simplified deployment with environment-based detection
- Add benefits of streaming mode: SSE, real-time monitoring, zero config
- Provide step-by-step production deployment example
This commit is contained in:
Ryan Malloy 2025-09-17 07:21:53 -06:00
parent b4d39cfdc9
commit 1ca195607e

261
README.md
View File

@ -1153,71 +1153,248 @@ mqtt-{subdomain}.yourdomain.com {
# Devices get automatic HTTPS, load balancing, DDoS protection
```
### 🔧 Docker Compose Integration
### 🔧 Docker Compose Integration with caddy-docker-proxy
**Complete Stack with caddy-docker-proxy:**
**Using [caddy-docker-proxy](https://github.com/lucaslorentz/caddy-docker-proxy)** for automatic HTTPS and container discovery.
> **caddy-docker-proxy** automatically generates Caddyfile configurations from Docker container labels, eliminating manual reverse proxy setup. Perfect for dynamic broker spawning!
**Complete Production Stack:**
```yaml
# docker-compose.yml
version: "3.8"
services:
mcmqtt:
image: python:3.11-slim
command: uvx mcmqtt --transport http --port 3000
caddy:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
ports:
- "80:80"
- "443:443"
environment:
# Enable Docker provider for automatic container discovery
CADDY_INGRESS_NETWORKS: caddy
# Cloudflare API token for DNS challenge (wildcard certificates)
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
networks:
- caddy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- caddy
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
labels:
# caddy-docker-proxy automatically adds to Caddyfile
caddy: mqtt-control.yourdomain.com
caddy.reverse_proxy: "{{upstreams 3000}}"
caddy.tls: internal # or use DNS challenge for public
# Example spawned broker container (created by mcmqtt)
mqtt-broker-customer-123:
image: python:3.11-slim
command: uvx amqtt --config /broker.yaml
networks:
- caddy
labels:
# Automatic HTTPS routing via caddy-docker-proxy
caddy: customer-123.mqtt.yourdomain.com
caddy.reverse_proxy: "{{upstreams 1883}}"
# Global TLS configuration for wildcard certificates
caddy.tls.dns: cloudflare
mcmqtt:
image: python:3.11-slim
# http-streamable automatically configures caddy labels
command: uvx mcmqtt --transport http-streamable --port 3000 --hostname mqtt-control.${DOMAIN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- caddy
restart: unless-stopped
environment:
- DOMAIN=${DOMAIN}
- CADDY_NETWORK=caddy
# Labels automatically added by --transport http-streamable
# No manual caddy labels needed!
depends_on:
- caddy
# Optional: Web dashboard for broker management
mqtt-dashboard:
image: nginx:alpine
volumes:
- ./dashboard:/usr/share/nginx/html:ro
networks:
- caddy
labels:
caddy: mqtt-dashboard.yourdomain.com
caddy.reverse_proxy: "{{upstreams 80}}"
caddy.tls.dns: cloudflare
# WebSocket support
caddy.handle_path: "/ws"
caddy.handle_path.reverse_proxy: "{{upstreams 9001}}"
caddy.@websocket.header: "Connection *Upgrade*"
caddy.@websocket.header_2: "Upgrade websocket"
networks:
caddy:
external: true # Managed by load-balancers/caddy
external: false
name: caddy
volumes:
caddy_data:
external: true
caddy_config:
external: true
```
**The Magic: Just Labels = Instant HTTPS Routing!**
**Environment Configuration (.env):**
```bash
# When mcmqtt spawns a broker, it adds these labels:
# .env file
COMPOSE_PROJECT_NAME=mcmqtt-production
# Cloudflare DNS challenge for wildcard certificates
CLOUDFLARE_API_TOKEN=your_cloudflare_global_api_key_here
# Domain configuration
DOMAIN=yourdomain.com
MQTT_SUBDOMAIN=mqtt
# Optional: Basic auth for admin interfaces
ADMIN_USER=admin
ADMIN_PASSWORD_HASH=$2a$14$hash_your_password_here
```
**Setup Instructions:**
```bash
# 1. Create external volumes for Caddy data persistence
docker volume create caddy_data
docker volume create caddy_config
# 2. Configure environment variables
cp .env.example .env
# Edit .env with your domain and Cloudflare token
# 3. Deploy the stack
docker compose up -d
# 4. Verify Caddy is running
docker compose logs caddy
# 5. Test mcmqtt control interface
curl https://mqtt-control.yourdomain.com/health
```
**How Dynamic Broker Spawning Works:**
```bash
# 1. User calls mqtt_spawn_broker tool
{
"tool": "mqtt_spawn_broker",
"arguments": {
"name": "api-coordination",
"name": "customer-acme-prod",
"websocket_port": 9001,
"caddy_labels": {
"caddy": "api-coord.mqtt.yourdomain.com",
"caddy.reverse_proxy": "{{upstreams 1883}}",
"caddy.handle_path": "/ws",
"caddy.handle_path.reverse_proxy": "{{upstreams 9001}}",
"caddy.tls.dns": "cloudflare"
}
"public_hostname": "acme.mqtt.yourdomain.com",
"auth_required": true,
"max_connections": 1000
}
}
# caddy-docker-proxy automatically detects new container
# Adds route to Caddyfile: api-coord.mqtt.yourdomain.com
# Issues wildcard certificate via Cloudflare DNS
# Result: Instant HTTPS routing with zero manual config!
# 2. mcmqtt spawns Docker container with automatic caddy labels:
docker run -d \
--name mqtt-broker-customer-acme-prod \
--network caddy \
--label "caddy=acme.mqtt.yourdomain.com" \
--label "caddy.reverse_proxy={{upstreams 1883}}" \
--label "caddy.handle_path=/ws" \
--label "caddy.handle_path.reverse_proxy={{upstreams 9001}}" \
--label "caddy.tls.dns=cloudflare" \
python:3.11-slim uvx amqtt
# 3. caddy-docker-proxy automatically detects the new container
# 4. Generates Caddyfile configuration instantly:
# acme.mqtt.yourdomain.com {
# reverse_proxy mqtt-broker-customer-acme-prod:1883
# handle_path /ws {
# reverse_proxy mqtt-broker-customer-acme-prod:9001
# }
# tls {
# dns cloudflare
# }
# }
# 5. Result: https://acme.mqtt.yourdomain.com is LIVE with valid certificate!
```
**Production Deployment Example:**
```bash
# Clone and deploy the complete stack
git clone https://github.com/your-org/mcmqtt-production-stack
cd mcmqtt-production-stack
# Configure your domain and Cloudflare
cp .env.example .env
# Edit .env with your settings
# Deploy production stack
make deploy
# Test the deployment
make test-deployment
# Spawn your first public broker
curl -X POST https://mqtt-control.yourdomain.com/api/brokers \
-H "Content-Type: application/json" \
-d '{
"name": "my-first-broker",
"public_hostname": "test.mqtt.yourdomain.com",
"websocket_port": 9001,
"auth_required": true
}'
# Result: https://test.mqtt.yourdomain.com is immediately accessible!
```
### ⚡ Auto-Labeling with `--transport http-streamable`
**Zero configuration Caddy integration!**
```bash
# Traditional: Manual caddy labels
uvx mcmqtt --transport http --port 3000
# Requires manual caddy labels in docker-compose.yml
# Auto-magic: Automatic caddy labels
uvx mcmqtt --transport http-streamable --hostname mqtt-control.yourdomain.com
# Automatically adds all necessary caddy-docker-proxy labels!
```
**What `--transport http-streamable` Does:**
1. **Detects caddy-docker-proxy environment**
2. **Automatically adds container labels:**
```docker
--label "caddy=${HOSTNAME}"
--label "caddy.reverse_proxy={{upstreams ${PORT}}}"
--label "caddy.tls.dns=cloudflare" # If CLOUDFLARE_API_TOKEN detected
--label "caddy.handle_path=/ws" # For WebSocket support
```
3. **Configures FastMCP server for streaming responses**
4. **Enables real-time broker status updates via SSE**
**Environment-Based Auto-Configuration:**
```bash
# mcmqtt detects these environment variables:
CADDY_NETWORK=caddy # Join caddy network automatically
CLOUDFLARE_API_TOKEN=xxx # Enable DNS challenge for wildcard certs
DOMAIN=yourdomain.com # Use as base domain for spawned brokers
SSL_EMAIL=admin@yourdomain.com # Let's Encrypt certificate email
# Result: Zero manual configuration needed!
```
**Simplified Docker Compose:**
```yaml
services:
mcmqtt:
image: python:3.11-slim
command: uvx mcmqtt --transport http-streamable --hostname mqtt-control.${DOMAIN}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- caddy
environment:
- DOMAIN=${DOMAIN}
- CADDY_NETWORK=caddy
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
# No manual labels needed - all automatic!
```
**Benefits of http-streamable mode:**
- 🏷️ **Auto-labeling**: Caddy labels added automatically
- 📡 **Real-time updates**: Server-Sent Events for broker status
- 🔄 **Live monitoring**: Streaming broker health and metrics
- 🎯 **Zero config**: Environment-based auto-configuration
- 🚀 **Production ready**: Optimized for long-running deployments
### 🐳 Docker Socket Magic = Instant Infrastructure
**How mcmqtt + caddy-docker-proxy Works:**