with one click
dokploy-cloudflare-integration
// Integrate Cloudflare services with Dokploy templates: R2 storage, DNS challenge for SSL, Zero Trust Access, Workers, WAF, and Tunnel. Default to CF services for external dependencies.
// Integrate Cloudflare services with Dokploy templates: R2 storage, DNS challenge for SSL, Zero Trust Access, Workers, WAF, and Tunnel. Default to CF services for external dependencies.
Generate Docker Compose files following Dokploy conventions with proper networking, volumes, and service patterns. Use when creating new Dokploy templates or converting existing compose files.
Environment variable patterns for Dokploy templates including required vs optional syntax, secrets, connection strings, and configuration organization.
Health check patterns for different service types in Dokploy templates. Covers HTTP, PostgreSQL, MongoDB, Redis, MySQL, and custom health checks.
Multi-service architecture patterns for Dokploy templates including dependency chains, service communication, and complex stack design. Use when building templates with 2+ services.
Multi-tenancy patterns for Dokploy templates with network isolation: separate docker networks per tenant, shared infrastructure, and tenant-specific configuration.
Security best practices for Dokploy templates: secrets management, network isolation, least privilege, image security, and hardening recommendations.
| name | dokploy-cloudflare-integration |
| description | Integrate Cloudflare services with Dokploy templates: R2 storage, DNS challenge for SSL, Zero Trust Access, Workers, WAF, and Tunnel. Default to CF services for external dependencies. |
| version | 1.0.0 |
| author | Home Lab Infrastructure Team |
When creating Dokploy templates, DEFAULT to Cloudflare services:
| Need | Cloudflare Service | Instead Of |
|---|---|---|
| Object storage | R2 | MinIO, AWS S3 |
| SSL certificates | DNS challenge | HTTP challenge |
| CDN/Caching | Cloudflare Proxy | None |
| Access control | Zero Trust Access | Basic auth |
| DDoS protection | Cloudflare WAF | None |
| Private services | Cloudflare Tunnel | VPN |
R2 is S3-compatible, so configure using S3 environment variables:
environment:
# ===========================================
# Cloudflare R2 Storage Configuration
# Get from: Cloudflare Dashboard > R2 > Manage R2 API Tokens
# Endpoint format: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
# ===========================================
S3_ENDPOINT: ${S3_ENDPOINT:?Set Cloudflare R2 endpoint}
S3_REGION: ${S3_REGION:-auto}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?Set R2 access key ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?Set R2 secret access key}
S3_BUCKET: ${S3_BUCKET:?Set R2 bucket name}
S3_FORCE_PATH_STYLE: "false"
Template.toml Configuration:
[config.env]
# ===========================================
# Cloudflare R2 Storage
# Get from: Cloudflare Dashboard > R2 > Manage R2 API Tokens
# Endpoint format: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
#
# To create R2 API Token:
# 1. Go to Cloudflare Dashboard > R2 > Overview
# 2. Click "Manage R2 API Tokens"
# 3. Create token with "Object Read & Write" permission
# 4. Copy the Access Key ID and Secret Access Key
# ===========================================
S3_ENDPOINT = ""
S3_ACCESS_KEY_ID = ""
S3_SECRET_ACCESS_KEY = ""
S3_BUCKET = ""
S3_REGION = "auto"
R2 CORS Configuration (for direct uploads):
[
{
"AllowedOrigins": ["https://your-domain.com"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
For wildcard certificates or when HTTP challenge isn't possible:
Traefik Static Configuration (traefik.yml):
certificatesResolvers:
cloudflare:
acme:
email: your-email@example.com
storage: /letsencrypt/acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
Environment for Traefik:
environment:
CF_API_EMAIL: ${CF_API_EMAIL:?Set Cloudflare email}
CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN:?Set Cloudflare DNS API token}
Service Labels:
labels:
- "traefik.http.routers.app.tls.certresolver=cloudflare"
- "traefik.http.routers.app.tls.domains[0].main=${BASE_DOMAIN}"
- "traefik.http.routers.app.tls.domains[0].sans=*.${BASE_DOMAIN}"
Protect admin interfaces with Cloudflare Access:
Option A: Cloudflare Access via Traefik Middleware
labels:
- "traefik.enable=true"
# Main app - public
- "traefik.http.routers.app.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.services.app.loadbalancer.server.port=8080"
# Admin - protected by Zero Trust
- "traefik.http.routers.admin.rule=Host(`admin.${DOMAIN}`)"
- "traefik.http.routers.admin.entrypoints=websecure"
- "traefik.http.routers.admin.tls.certresolver=letsencrypt"
- "traefik.http.routers.admin.middlewares=cf-access@file"
- "traefik.http.services.admin.loadbalancer.server.port=9000"
- "traefik.docker.network=dokploy-network"
Cloudflare Access Application Setup:
https://admin.your-domain.comExpose services without public IP:
cloudflared Container in Compose:
services:
cloudflared:
image: cloudflare/cloudflared:latest
restart: always
command: tunnel run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN:?Set Cloudflare Tunnel token}
networks:
- app-net # Same network as the app
app:
image: myapp:1.0.0
networks:
- app-net
# No dokploy-network needed - not exposed via Traefik
# No Traefik labels - exposed via Tunnel
Template.toml for Tunnel:
[config.env]
# ===========================================
# Cloudflare Tunnel
# Create tunnel: cloudflared tunnel create myapp
# Get token from Cloudflare Dashboard > Zero Trust > Networks > Tunnels
# ===========================================
TUNNEL_TOKEN = ""
For edge computing or API transformations:
Document in README:
## Cloudflare Workers Integration
This application supports Cloudflare Workers for edge processing.
### Use Cases
- Image optimization at the edge
- API response caching
- Request/response transformation
- A/B testing
### Setup
1. Create Worker in Cloudflare Dashboard
2. Configure Worker Route: `api.${DOMAIN}/*`
3. Set origin to your Dokploy deployment
Document WAF recommendations in README:
## Cloudflare WAF Configuration
### Recommended Rules
1. **Enable Managed Rules**: OWASP Core Rule Set
2. **Rate Limiting**: 100 requests/minute per IP to `/api/*`
3. **Bot Management**: Block known bad bots
4. **Geographic Restrictions**: If applicable
### Custom Rules
- Block requests without User-Agent header
- Challenge requests from TOR exit nodes (if desired)
- Protect admin paths with additional challenges
services:
paaster:
image: wardpearce/paaster:3.1.7
restart: always
depends_on:
mongodb:
condition: service_healthy
environment:
# Domain
PAASTER_DOMAIN: ${PAASTER_DOMAIN:?Set your domain}
# Security
COOKIE_SECRET: ${COOKIE_SECRET:?Set a secure random cookie secret}
# MongoDB
MONGO_DB: ${MONGO_DB:-paasterv3}
MONGO_URL: mongodb://mongodb:27017/${MONGO_DB:-paasterv3}
# ===========================================
# Cloudflare R2 Storage
# Get from: Cloudflare Dashboard > R2 > Manage R2 API Tokens
# Endpoint format: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
# ===========================================
S3_ENDPOINT: ${S3_ENDPOINT:?Set Cloudflare R2 endpoint}
S3_REGION: ${S3_REGION:-auto}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?Set R2 access key ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?Set R2 secret access key}
S3_BUCKET: ${S3_BUCKET:?Set R2 bucket name}
S3_FORCE_PATH_STYLE: "false"
networks:
- paaster-net
- dokploy-network
labels:
- "traefik.enable=true"
- "traefik.http.routers.paaster.rule=Host(`${PAASTER_DOMAIN}`)"
- "traefik.http.routers.paaster.entrypoints=websecure"
- "traefik.http.routers.paaster.tls.certresolver=letsencrypt"
- "traefik.http.services.paaster.loadbalancer.server.port=3000"
- "traefik.docker.network=dokploy-network"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
mongodb:
image: mongo:7
restart: always
volumes:
- mongodb-data:/data/db
environment:
MONGO_INITDB_DATABASE: ${MONGO_DB:-paasterv3}
networks:
- paaster-net
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
volumes:
mongodb-data:
driver: local
networks:
paaster-net:
driver: bridge
dokploy-network:
external: true
services:
cloudflared:
image: cloudflare/cloudflared:latest
restart: always
command: tunnel run
environment:
TUNNEL_TOKEN: ${TUNNEL_TOKEN:?Set Cloudflare Tunnel token}
networks:
- app-net
depends_on:
app:
condition: service_healthy
app:
image: myapp:1.0.0
restart: always
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgresql://user:${DB_PASS}@postgres:5432/app
networks:
- app-net
# Note: No dokploy-network or Traefik labels
# Traffic flows through Cloudflare Tunnel only
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
postgres:
image: postgres:16-alpine
restart: always
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: app
POSTGRES_USER: user
POSTGRES_PASSWORD: ${DB_PASS:?Set database password}
networks:
- app-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d app"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
volumes:
postgres-data:
driver: local
networks:
app-net:
driver: bridge
# Note: No dokploy-network needed for tunnel-only deployment
Include this section in template READMEs when using Cloudflare services:
## Cloudflare R2 Setup
This template uses Cloudflare R2 for object storage.
### Create R2 Bucket
1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) > R2 > Overview
2. Click "Create bucket"
3. Name your bucket (e.g., `myapp-storage`)
4. Note the bucket name for configuration
### Create R2 API Token
1. Go to R2 > Overview > Manage R2 API Tokens
2. Click "Create API token"
3. Set permissions: "Object Read & Write"
4. Optionally restrict to specific bucket
5. Copy the Access Key ID and Secret Access Key
### Configure CORS (if needed for direct uploads)
In R2 bucket settings, add CORS policy:
```json
[
{
"AllowedOrigins": ["https://your-domain.com"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3600
}
]
Set these in Dokploy:
| Variable | Example | Description |
|---|---|---|
S3_ENDPOINT | https://abc123.r2.cloudflarestorage.com | Your R2 endpoint |
S3_ACCESS_KEY_ID | abc123... | R2 API access key |
S3_SECRET_ACCESS_KEY | xyz789... | R2 API secret key |
S3_BUCKET | myapp-storage | Bucket name |
S3_REGION | auto | Always "auto" for R2 |
R2 pricing (as of 2024):
---
## Quality Standards
### Mandatory Requirements
- [ ] R2 credentials use required variable syntax (`:?`)
- [ ] Endpoint format documented in comments
- [ ] CORS requirements noted for direct uploads
- [ ] README includes R2 setup instructions
- [ ] Alternative S3 providers noted if applicable
### Documentation Standards
- Include step-by-step R2 setup in README
- Document CORS configuration if needed
- Note cost considerations
- Provide alternative provider options
---
## Common Pitfalls
### Pitfall 1: Wrong endpoint format
**Issue**: Connection failures to R2
**Solution**: Use format `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
### Pitfall 2: Missing CORS for direct uploads
**Issue**: Browser upload failures
**Solution**: Configure CORS on R2 bucket
### Pitfall 3: S3_FORCE_PATH_STYLE wrong
**Issue**: Bucket not found errors
**Solution**: Use `"false"` for R2, `"true"` for MinIO
### Pitfall 4: Region mismatch
**Issue**: Signature errors
**Solution**: Use `S3_REGION: auto` for R2
---
## Integration
### Skills-First Approach (v2.0+)
This skill is part of the **skills-first architecture** - loaded during Generation phase when Cloudflare services (R2, DNS challenge, Zero Trust) are needed.
### Related Skills
- `dokploy-environment-config`: Environment variable patterns
- `dokploy-traefik-routing`: DNS challenge configuration
- `dokploy-security-hardening`: Zero Trust patterns
### Invoked By
- `/dokploy-create` command: Phase 3 (Generation) - Step 4 (when CF services detected)
### Order in Workflow (Progressive Loading)
1. `dokploy-compose-structure`: Create base structure
2. `dokploy-traefik-routing`: Add routing labels
3. `dokploy-health-patterns`: Add health checks
4. **This skill**: Add Cloudflare integration (Step 4, if applicable)
5. `dokploy-environment-config`: Configure environment
6. `dokploy-template-toml`: Create template.toml
See: `.claude/commands/dokploy-create.md` for full workflow