IaC Bazaar
CloudflarePlan-validated

Cloudflare DNS & WAF

Zone DNS records, security settings, and managed WAF rulesets for a Cloudflare zone — provider v5 ready.

terraformEdge & DNS#cloudflare

Compare DNS & Traffic Management across clouds →

cloudflare-dnsterraform v1.7

Verification

Plan-validated

Passed: module logic verified on a mocked plan — inputs, validation rules, conditional creation and outputs resolve (no real provider, no cloud).

Conformance

  • Static validation (fmt · validate · tflint)
  • No applicable security policies for this provider
  • Plan tests (mocked: validation rules · outputs)

Provenance

  • SHA-256 checksum
  • Signature (pending)

Functional

  • Live test pending (no cloud run yet)

Last verified 2026-06-28 · how we verify

Documentation

cloudflare-dns

Zone DNS records, security settings, and managed WAF rulesets for a Cloudflare zone — provider v5 ready. Built directly against the auto-generated v5 schema (cloudflare_dns_record, cloudflare_zone_setting, cloudflare_ruleset), not the v4 resource names (cloudflare_record, cloudflare_zone_settings_override) that break on upgrade. Works with Terraform and OpenTofu (>= 1.6), Cloudflare provider >= 5.0, < 6.0.

Secure defaults:

  • A/AAAA/CNAME records are proxied (orange-cloud) unless you opt out, so origin IPs stay hidden; proxied records get TTL 1 (automatic) as Cloudflare requires.
  • HTTPS posture enforced via zone settings: always_use_https, automatic_https_rewrites, TLS 1.2 minimum, TLS 1.3 enabled.
  • Cloudflare Managed Ruleset + OWASP Core Ruleset deployed and enabled by default (OWASP blocks at the medium anomaly threshold, 40).

Usage

module "zone" {
  source  = "./cloudflare-dns"
  zone_id = "0da42c8d2132a9ddaf714f9e7c920711"

  records = {
    apex = { name = "example.com", type = "A", content = "192.0.2.10" }
    www  = { name = "www.example.com", type = "CNAME", content = "example.com" }
  }

  custom_firewall_rules = [{
    description = "Challenge empty user agents"
    expression  = "(http.user_agent eq \"\")"
    action      = "managed_challenge"
  }]
}

Inputs

NameTypeDefaultDescription
zone_idstringCloudflare zone ID (32-hex, required)
recordsmap(object){}DNS records keyed by a stable logical name; content for simple records, data for structured (SRV/CAA/TLSA/...)
zone_settingsmap(string)HTTPS/TLS hardening setZone settings keyed by setting ID
enable_managed_wafbooltrueExecute the Cloudflare Managed Ruleset (Pro+ plan)
enable_owasp_corebooltrueExecute the OWASP Core Ruleset (Pro+ plan)
owasp_score_thresholdnumber40OWASP anomaly threshold (60 low / 40 medium / 25 high)
owasp_actionstring"block"Action when the OWASP threshold is exceeded
custom_firewall_ruleslist(object)[]Custom WAF rules (description, expression, action, enabled)

Outputs

NameDescription
record_idsMap of record key => DNS record ID
record_hostnamesMap of record key => FQDN
managed_waf_ruleset_idManaged-WAF ruleset ID (null when disabled)
custom_firewall_ruleset_idCustom firewall ruleset ID (null when unused)
zone_settings_appliedZone setting IDs managed by this module

Requirements & notes

  • Terraform or OpenTofu >= 1.6; cloudflare/cloudflare >= 5.0, < 6.0.
  • This module owns the zone's http_request_firewall_managed and http_request_firewall_custom ruleset phases (Cloudflare allows exactly one zone ruleset per phase) — do not manage those phases elsewhere.
  • Managed WAF rulesets require a paid (Pro or higher) zone plan; on Free zones set enable_managed_waf = false and enable_owasp_core = false.
  • Per-record tags are a Cloudflare Enterprise feature; leave unset otherwise.
  • Record name should be the fully-qualified hostname (e.g. www.example.com).

Verification

Static-validated (fmt, validate, tflint). Live apply/destroy testing pending cloud sandbox availability — see catalog status.

License

Commercial — IaC Bazaar EULA. © IaC Bazaar. Original work (not derived from a third-party module).