Claude-skill-registry cloudflare-coder
This skill guides provisioning Cloudflare infrastructure with OpenTofu/Terraform. Use when managing zones, DNS records, WAF rules, SSL settings, Page Rules, or cache configuration.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cloudflare-coder" ~/.claude/skills/majiayu000-claude-skill-registry-cloudflare-coder && rm -rf "$T"
skills/data/cloudflare-coder/SKILL.mdCloudflare Coder
Overview
Cloudflare provides CDN, DNS, security, and edge computing services. This skill covers OpenTofu/Terraform patterns for Cloudflare resources.
Provider Setup
terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" version = "~> 4.0" } } } provider "cloudflare" { # API Token from environment: CLOUDFLARE_API_TOKEN # Or explicitly (not recommended): # api_token = var.cloudflare_api_token }
Authentication
# Preferred: API Token (scoped permissions) export CLOUDFLARE_API_TOKEN="your-api-token" # Or with 1Password CLOUDFLARE_API_TOKEN=op://Infrastructure/Cloudflare/api_token # Legacy: Global API Key (full access - avoid if possible) export CLOUDFLARE_API_KEY="your-global-api-key" export CLOUDFLARE_EMAIL="your-email@example.com"
API Token Permissions (minimum required):
| Resource | Permission | Use Case |
|---|---|---|
| Zone | Read | List zones, read settings |
| Zone | Edit | Modify zone settings |
| DNS | Edit | Manage DNS records |
| Firewall | Edit | WAF, firewall rules |
| SSL | Edit | Certificate management |
| Cache | Purge | Cache invalidation |
Data Sources
Get Zone by Name
data "cloudflare_zone" "main" { name = "example.com" } # Use in resources resource "cloudflare_record" "www" { zone_id = data.cloudflare_zone.main.id # ... }
Get Account ID
data "cloudflare_accounts" "main" { name = "My Account" } output "account_id" { value = data.cloudflare_accounts.main.accounts[0].id }
DNS Records
Basic Records
# A Record resource "cloudflare_record" "root" { zone_id = data.cloudflare_zone.main.id name = "@" type = "A" content = var.server_ip ttl = 1 # 1 = automatic proxied = true } # CNAME Record resource "cloudflare_record" "www" { zone_id = data.cloudflare_zone.main.id name = "www" type = "CNAME" content = "@" ttl = 1 proxied = true } # MX Records resource "cloudflare_record" "mx_primary" { zone_id = data.cloudflare_zone.main.id name = "@" type = "MX" content = "mail.example.com" ttl = 3600 priority = 10 proxied = false # MX cannot be proxied } # TXT Record (SPF) resource "cloudflare_record" "spf" { zone_id = data.cloudflare_zone.main.id name = "@" type = "TXT" content = "v=spf1 include:_spf.google.com ~all" ttl = 3600 }
DNS Records with for_each
locals { dns_records = { api = { type = "A" content = var.api_server_ip proxied = true } staging = { type = "A" content = var.staging_server_ip proxied = true } mail = { type = "A" content = var.mail_server_ip proxied = false } } } resource "cloudflare_record" "subdomain" { for_each = local.dns_records zone_id = data.cloudflare_zone.main.id name = each.key type = each.value.type content = each.value.content ttl = 1 proxied = each.value.proxied }
SSL/TLS Settings
Zone SSL Settings
resource "cloudflare_zone_settings_override" "ssl" { zone_id = data.cloudflare_zone.main.id settings { # SSL mode: off, flexible, full, strict (recommended) ssl = "strict" # Minimum TLS version min_tls_version = "1.2" # Always use HTTPS always_use_https = "on" # Automatic HTTPS Rewrites automatic_https_rewrites = "on" # HTTP Strict Transport Security security_header { enabled = true max_age = 31536000 # 1 year include_subdomains = true preload = true nosniff = true } # TLS 1.3 tls_1_3 = "on" # Opportunistic Encryption opportunistic_encryption = "on" } }
Origin Certificates
resource "cloudflare_origin_ca_certificate" "origin" { csr = tls_cert_request.origin.cert_request_pem hostnames = ["example.com", "*.example.com"] request_type = "origin-rsa" requested_validity = 5475 # 15 years (max) } # Generate private key and CSR resource "tls_private_key" "origin" { algorithm = "RSA" rsa_bits = 2048 } resource "tls_cert_request" "origin" { private_key_pem = tls_private_key.origin.private_key_pem subject { common_name = "example.com" organization = "Example Inc" } } output "origin_certificate" { value = cloudflare_origin_ca_certificate.origin.certificate sensitive = true }
Firewall & WAF
See resources/waf.md for IP access rules, WAF custom rules with rate limiting, and managed rulesets (Cloudflare + OWASP).
Cache Rules
Modern Cache Rules (Rulesets)
resource "cloudflare_ruleset" "cache" { zone_id = data.cloudflare_zone.main.id name = "Cache Rules" description = "Caching configuration" kind = "zone" phase = "http_request_cache_settings" # Cache static assets aggressively rules { action = "set_cache_settings" action_parameters { cache = true edge_ttl { mode = "override_origin" default = 2592000 # 30 days } browser_ttl { mode = "override_origin" default = 86400 # 1 day } } expression = "(http.request.uri.path.extension in {\"css\" \"js\" \"jpg\" \"jpeg\" \"png\" \"gif\" \"svg\" \"woff\" \"woff2\"})" description = "Cache static assets" enabled = true } # Bypass cache for API rules { action = "set_cache_settings" action_parameters { cache = false } expression = "(starts_with(http.request.uri.path, \"/api/\"))" description = "Bypass cache for API" enabled = true } # Bypass cache for admin rules { action = "set_cache_settings" action_parameters { cache = false } expression = "(starts_with(http.request.uri.path, \"/admin\"))" description = "Bypass cache for admin" enabled = true } }
Legacy Page Rules
# Cache everything for static paths resource "cloudflare_page_rule" "cache_static" { zone_id = data.cloudflare_zone.main.id target = "example.com/assets/*" priority = 1 actions { cache_level = "cache_everything" edge_cache_ttl = 2592000 # 30 days } } # Bypass cache for API resource "cloudflare_page_rule" "bypass_api" { zone_id = data.cloudflare_zone.main.id target = "example.com/api/*" priority = 2 actions { cache_level = "bypass" } } # Force HTTPS resource "cloudflare_page_rule" "force_https" { zone_id = data.cloudflare_zone.main.id target = "http://example.com/*" priority = 3 actions { always_use_https = true } }
Redirect Rules
resource "cloudflare_ruleset" "redirects" { zone_id = data.cloudflare_zone.main.id name = "Redirects" description = "URL redirects" kind = "zone" phase = "http_request_dynamic_redirect" # www to apex redirect rules { action = "redirect" action_parameters { from_value { status_code = 301 target_url { expression = "concat(\"https://example.com\", http.request.uri.path)" } preserve_query_string = true } } expression = "(http.host eq \"www.example.com\")" description = "Redirect www to apex" enabled = true } # Old URL to new URL rules { action = "redirect" action_parameters { from_value { status_code = 301 target_url { value = "https://example.com/new-page" } } } expression = "(http.request.uri.path eq \"/old-page\")" description = "Redirect old page to new" enabled = true } }
Zone Settings
Performance Settings
resource "cloudflare_zone_settings_override" "performance" { zone_id = data.cloudflare_zone.main.id settings { # Compression brotli = "on" # Speed optimizations minify { css = "on" html = "on" js = "on" } # Early Hints early_hints = "on" # HTTP/2 and HTTP/3 http2 = "on" http3 = "on" # 0-RTT zero_rtt = "on" # Rocket Loader (async JS loading) rocket_loader = "on" # Image optimization (requires Pro+) # polish = "lossless" # mirage = "on" # Mobile redirect (if needed) # mobile_redirect { # mobile_subdomain = "m" # status = "on" # strip_uri = false # } } }
Security Settings
resource "cloudflare_zone_settings_override" "security" { zone_id = data.cloudflare_zone.main.id settings { # Security level: off, essentially_off, low, medium, high, under_attack security_level = "medium" # Challenge Passage TTL challenge_ttl = 1800 # Browser Integrity Check browser_check = "on" # Email Obfuscation email_obfuscation = "on" # Server Side Excludes server_side_exclude = "on" # Hotlink Protection hotlink_protection = "on" # IP Geolocation ip_geolocation = "on" } }
Argo & Load Balancing
See resources/load-balancer.md for Argo Smart Routing and Load Balancer configuration with origin pools, health checks, and session affinity.
Workers Routes
# Deploy Worker via Terraform (see wrangler-coder for full Worker management) resource "cloudflare_worker_route" "api" { zone_id = data.cloudflare_zone.main.id pattern = "example.com/api/*" script_name = cloudflare_worker_script.api.name } resource "cloudflare_worker_script" "api" { account_id = var.cloudflare_account_id name = "api-worker" content = file("${path.module}/workers/api.js") module = true plain_text_binding { name = "ENVIRONMENT" text = var.environment } secret_text_binding { name = "API_KEY" text = var.api_key } }
Complete Production Zone
See resources/production-zone.md for a complete Terraform configuration with DNS, SSL/TLS, WAF, caching, redirects, and variables template.
Best Practices
- Use API Tokens - Scoped permissions over global API key
- Enable Strict SSL - Always use Full (Strict) mode with valid origin certs
- Use Rulesets - Modern rulesets over legacy Page Rules
- Cache Strategically - Static assets cached, dynamic bypassed
- Rate Limit APIs - Protect endpoints from abuse
- Enable WAF - Deploy managed rulesets as baseline
- HSTS Preload - Add to browser preload list for max security
- Terraform State - Store state securely, not in version control