Documentation Index
Fetch the complete documentation index at: https://docs.monk.io/llms.txt
Use this file to discover all available pages before exploring further.
What is this integration?
Cloudflare provides globally distributed DNS, CDN, and edge services.
What Monk manages
- DNS Zone and DNS Record
- Cloudflare Tunnel
- Cloudflare Tunnel Application
Credentials
cloudflare-api-token: Cloudflare API token with account/tunnel and DNS edit permissions
cloudflare-account-id: Account tag/UUID from the dashboard URL (/accounts/\<ACCOUNT_ID>)
cloudflare-tunnel-token: Tunnel token created by cloudflare/cloudflare-tunnel on first run (distinct from API token)
Links
Templates
DNS record template
Save as example-record.yaml (see src/cloudflare/example-record.yaml):
namespace: cloudflare-examples
nginx:
defines: runnable
inherits: nginx/node-proxy
example-record:
defines: cloudflare/cloudflare-dns-record
zone_name: example.com
name: www
record_type: CNAME
content: <- connection-domain-name("nginx")
ttl: 1
proxied: true
services:
data:
protocol: custom
connections:
nginx:
runnable: cloudflare-examples/nginx
service: nginx
depends:
wait-for:
runnables:
- cloudflare-examples/nginx
timeout: 60
stack:
defines: group
members:
- cloudflare-examples/nginx
- cloudflare-examples/example-record
Tunnel: single app
Save as example-tunnel.yaml (see src/cloudflare/example-tunnel.yaml):
namespace: cloudflare-tunnel-example
app:
defines: runnable
containers:
app:
image: nginx:latest
services:
http:
container: app
port: 80
protocol: tcp
tunnel:
defines: cloudflare/cloudflare-tunnel
account_id: <- secret("cloudflare-account-id")
name: "example-tunnel"
token_secret_ref: cloudflare-tunnel-token
permitted-secrets:
cloudflare-api-token: true
cloudflare-tunnel-token: true
cloudflare-account-id: true
services:
data:
protocol: custom
# cloudflare-tunnel-token is created by the tunnel entity on first run (distinct from cloudflare-api-token)
tunnel-app:
defines: cloudflare/cloudflare-tunnel-application
account_id: <- secret("cloudflare-account-id")
tunnel_id: <- connection-target("tunnel") entity-state get-member("id")
zone_name: example.com
hostname: app.example.com # use "@" for apex domain
service: <- "http://" connection-ip("app") ":" connection-port("app") concat-all
permitted-secrets:
cloudflare-api-token: true
cloudflare-account-id: true
connections:
tunnel:
runnable: cloudflare-tunnel-example/tunnel
service: data
app:
runnable: cloudflare-tunnel-example/app
service: http
depends:
wait-for:
runnables:
- cloudflare-tunnel-example/tunnel
timeout: 60
cloudflared:
defines: runnable
inherits: cloudflare/cloudflared
connections:
app:
runnable: cloudflare-tunnel-example/app
service: http
depends:
wait-for:
runnables:
- cloudflare-tunnel-example/tunnel
- cloudflare-tunnel-example/app
timeout: 60
stack:
defines: group
members:
- cloudflare-tunnel-example/app
- cloudflare-tunnel-example/tunnel
- cloudflare-tunnel-example/tunnel-app
- cloudflare-tunnel-example/cloudflared
Tunnel: multiple apps through one tunnel
namespace: cloudflare-multi-app
tunnel:
defines: cloudflare/cloudflare-tunnel
account_id: <- secret("cloudflare-account-id")
name: "multi-app-tunnel"
token_secret_ref: cloudflare-tunnel-token
permitted-secrets:
cloudflare-api-token: true
cloudflare-tunnel-token: true
cloudflare-account-id: true
services:
data:
protocol: custom
frontend:
defines: runnable
containers:
app:
image: nginx:latest
services:
http:
container: app
port: 3000
protocol: tcp
frontend-tunnel:
defines: cloudflare/cloudflare-tunnel-application
account_id: <- secret("cloudflare-account-id")
tunnel_id: <- connection-target("tunnel") entity-state get-member("id")
zone_name: example.com
hostname: app.example.com
service: <- "http://" connection-ip("frontend") ":" connection-port("frontend") concat-all
permitted-secrets:
cloudflare-api-token: true
cloudflare-account-id: true
connections:
tunnel:
runnable: cloudflare-multi-app/tunnel
service: data
app:
runnable: cloudflare-multi-app/frontend
service: http
api:
defines: runnable
containers:
app:
image: nginx:latest
services:
http:
container: app
port: 8000
protocol: tcp
api-tunnel:
defines: cloudflare/cloudflare-tunnel-application
account_id: <- secret("cloudflare-account-id")
tunnel_id: <- connection-target("tunnel") entity-state get-member("id")
zone_name: example.com
hostname: api.example.com
service: <- "http://" connection-ip("api") ":" connection-port("api") concat-all
permitted-secrets:
cloudflare-api-token: true
cloudflare-account-id: true
connections:
tunnel:
runnable: cloudflare-multi-app/tunnel
service: data
app:
runnable: cloudflare-multi-app/api
service: http
cloudflared:
defines: runnable
inherits: cloudflare/cloudflared
connections:
frontend:
runnable: cloudflare-multi-app/frontend
service: http
api:
runnable: cloudflare-multi-app/api
service: http
depends:
wait-for:
runnables:
- cloudflare-multi-app/tunnel
timeout: 60
stack:
defines: group
members:
- cloudflare-multi-app/tunnel
- cloudflare-multi-app/frontend
- cloudflare-multi-app/frontend-tunnel
- cloudflare-multi-app/api
- cloudflare-multi-app/api-tunnel
- cloudflare-multi-app/cloudflared
Tunnel: cloudflared only (tunnel connector already exists)
Use this when you already have a tunnel token (in this case it’s in global secret cloudflare-tunnel-token) and just need to run cloudflared. You must create the tunnel and DNS records manually in Cloudflare for the hostname(s) in your ingress. Each hostname should have a CNAME record pointing to \<tunnel-id>.cfargotunnel.com. For a full setup that creates tunnels and DNS records, use the cloudflare/cloudflare-tunnel and cloudflare/cloudflare-tunnel-application entities instead.
namespace: example
app:
defines: runnable
containers:
app:
image: nginx:latest
services:
http:
container: app
protocol: tcp
port: 3000
cloudflare-tunnel:
defines: runnable
inherits: cloudflare/cloudflared
files:
config:
container: cloudflared
path: /etc/cloudflared/config.yml
mode: 0644
contents: |
ingress:
- hostname: mysite.example.com
service: {{ v "app-url" }}
- service: http_status:404
connections:
app:
runnable: example/app
service: http
depends:
wait-for:
runnables:
- example/app
timeout: 60
variables:
token_secret_ref:
type: string
value: cloudflare-tunnel-token
command_options:
type: string
value: --config /etc/cloudflared/config.yml --no-autoupdate # options after "tunnel"
subcommand_options:
type: string
value: "" # options after "run" (e.g., --cred-file)
app-host:
type: string
value: <- connection-ip("app")
app-port:
type: int
value: <- connection-port("app")
app-url:
type: string
value: <- "http://" $app-host ":" $app-port concat-all
permitted-secrets:
cloudflare-tunnel-token: true
stack:
defines: group
members:
- example/app
- example/cloudflare-tunnel
Advanced Configuration Examples
DNS Zone Management
namespace: cloudflare-dns-management
# Create a new DNS zone
my-zone:
defines: cloudflare/cloudflare-dns-zone
zone_name: myapp.com
plan: free # free, pro, business, enterprise
# Add multiple DNS records
www-record:
defines: cloudflare/cloudflare-dns-record
zone_name: myapp.com
name: www
record_type: CNAME
content: myapp.com
ttl: 1
proxied: true
api-record:
defines: cloudflare/cloudflare-dns-record
zone_name: myapp.com
name: api
record_type: A
content: 192.168.1.100
ttl: 1
proxied: false
# MX record for email
mx-record:
defines: cloudflare/cloudflare-dns-record
zone_name: myapp.com
name: "@"
record_type: MX
content: mail.myapp.com
priority: 10
ttl: 1
Page Rules for CDN Optimization
namespace: cloudflare-cdn
# Page rule for caching static assets
static-assets-rule:
defines: cloudflare/cloudflare-page-rule
zone_name: myapp.com
target: "*myapp.com/static/*"
actions:
- id: cache_level
value: cache_everything
- id: browser_cache_ttl
value: 31536000 # 1 year
# Page rule for API endpoints (no caching)
api-rule:
defines: cloudflare/cloudflare-page-rule
zone_name: myapp.com
target: "*myapp.com/api/*"
actions:
- id: cache_level
value: bypass
Firewall Rules
namespace: cloudflare-security
# Block traffic from specific countries
geo-block-rule:
defines: cloudflare/cloudflare-firewall-rule
zone_name: myapp.com
action: block
filter:
expression: "(ip.geoip.country in {\"CN\" \"RU\"})"
# Rate limiting for login endpoints
rate-limit-rule:
defines: cloudflare/cloudflare-firewall-rule
zone_name: myapp.com
action: challenge
filter:
expression: "(http.request.uri.path contains \"/login\")"
rate_limit:
requests_per_period: 10
period: 60
action: challenge
Troubleshooting
Common Issues
API token permission errors:
# Verify token has correct permissions in Cloudflare dashboard
# Ensure token has Zone:DNS:Edit and Zone:Page Rules:Edit permissions
Zone not found errors:
# Check zone name spelling and that it exists in your Cloudflare account
# Verify the API token has access to the specified zone
DNS propagation delays:
- DNS changes can take up to 24 hours to propagate globally
- Use Cloudflare’s development mode for testing to bypass cache
Best Practices
- API Token Security: Use restricted API tokens with minimal required permissions
- Zone Organization: Group related DNS records in logical namespaces
- CDN Optimization: Use page rules to optimize caching for different content types
- Security First: Enable firewall rules and rate limiting for sensitive endpoints
- Monitoring: Enable Cloudflare Analytics to monitor traffic patterns
Integration with Other Services
Cloudflare works seamlessly with:
- Monk Applications: Proxy traffic through Cloudflare’s global network
- Load Balancers: Distribute traffic across multiple origins
- CDNs: Combine with other CDNs for multi-layer caching
- Security Tools: Integrate with WAF and DDoS protection services
- Analytics: Feed traffic data into monitoring dashboards
Support & Resources