This skill guides provisioning Cloudflare infrastructure with OpenTofu/Terraform. Use when managing zones, DNS records, WAF rules, SSL settings, Page Rules, or cache configuration.
Resources
1Install
npx skillscat add majesticlabs-dev/majestic-marketplace/cloudflare-coder Install via the SkillsCat registry.
About this skill
The skill provides instructions for provisioning Cloudflare infrastructure using OpenTofu or Terraform, enabling management of zones, DNS records, WAF rules, SSL settings, page rules, and cache configuration. It solves the need to automate and version‑control cloud networking and security settings. Use it when setting up or updating a Cloudflare‑protected domain through code.
SKILL.md
Provider Setup
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
provider "cloudflare" {
# Uses CLOUDFLARE_API_TOKEN env var
}Authentication
export CLOUDFLARE_API_TOKEN="your-api-token"
# Or with 1Password
CLOUDFLARE_API_TOKEN=op://Infrastructure/Cloudflare/api_tokenSee references/cloudflare-api-permissions.md for token permissions and legacy API key setup.
Data Sources
Get Zone by Name
data "cloudflare_zone" "main" {
name = "example.com"
}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
resource "cloudflare_record" "root" {
zone_id = data.cloudflare_zone.main.id
name = "@"
type = "A"
content = var.server_ip
ttl = 1 # 1 = automatic
proxied = true
}
resource "cloudflare_record" "www" {
zone_id = data.cloudflare_zone.main.id
name = "www"
type = "CNAME"
content = "@"
ttl = 1
proxied = true
}
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
}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 = "strict"
min_tls_version = "1.2"
always_use_https = "on"
automatic_https_rewrites = "on"
tls_1_3 = "on"
opportunistic_encryption = "on"
security_header {
enabled = true
max_age = 31536000
include_subdomains = true
preload = true
nosniff = true
}
}
}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)
}
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
}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"
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
}
rules {
action = "set_cache_settings"
action_parameters {
cache = false
}
expression = "(starts_with(http.request.uri.path, \"/api/\"))"
description = "Bypass cache for API"
enabled = 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"
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
}
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 {
brotli = "on"
early_hints = "on"
http2 = "on"
http3 = "on"
zero_rtt = "on"
rocket_loader = "on"
minify {
css = "on"
html = "on"
js = "on"
}
}
}Security Settings
resource "cloudflare_zone_settings_override" "security" {
zone_id = data.cloudflare_zone.main.id
settings {
security_level = "medium" # off, essentially_off, low, medium, high, under_attack
challenge_ttl = 1800
browser_check = "on"
email_obfuscation = "on"
server_side_exclude = "on"
hotlink_protection = "on"
ip_geolocation = "on"
}
}Workers Routes
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
}
}References
- references/cloudflare-api-permissions.md - Token permissions and auth setup
- references/waf.md - IP access rules, WAF custom rules, managed rulesets
- references/load-balancer.md - Argo Smart Routing, load balancer config
- references/production-zone.md - Complete production Terraform configuration