Skip to content
DECLARE OR DRIFT

Terraform on Cloudflare

Terraform on Cloudflare

Cloudflare is a good place to practice Terraform because the resources are concrete, the API is direct, and the effects are easy to inspect.

The problem

Cloudflare is a useful second platform because the resources are small and the feedback loop is short. DNS records, Access policies, Pages projects, Workers bindings, KV namespaces, R2 buckets, and D1 databases are easy to inspect.

Small does not mean harmless. A single DNS or Access change can affect every user of a domain.

  • Small config can still have a large production effect.
  • DNS and Access are production control planes.
  • Terraform should own durable platform shape, not every code artifact.

Vocabulary

Cloudflare has account-level resources and zone-level resources. Account resources belong to your Cloudflare account. Zone resources belong to a domain. That distinction matters because an API token that can edit one zone should not necessarily edit every zone.

The Terraform provider can manage DNS records, Pages projects, Workers routes, KV namespaces, R2 buckets, D1 databases, Access applications, Access policies, rulesets, and settings. Decide what Terraform owns before you start.

  • Zone: a domain such as example.com.
  • Account: the Cloudflare account container.
  • DNS record: traffic direction.
  • Access policy: who can reach an app.
  • KV/R2/D1: data services that app code may bind to.

How the loop works

A practical Cloudflare root often starts with variables for account ID and zone ID, then manages DNS records, Access apps, storage namespaces, and deployment project settings. Worker code is usually deployed by Wrangler or CI, while Terraform manages bindings, routes, and durable infrastructure.

This split matters. Terraform is good at declaring that a KV namespace exists and that a Worker can bind to it. Wrangler or CI is usually a better fit for frequent application code deploys.

  • Use scoped API tokens.
  • Keep zone IDs and account IDs explicit.
  • Review proxied DNS changes carefully.
  • Separate infrastructure shape from app bundle deployment.

Common mistakes

Cloudflare changes can feel safe because they are quick. A bad DNS record, Access policy, redirect rule, or WAF rule can break users immediately. Review these changes the same way you would review compute changes.

Another mistake is mixing ownership. If the dashboard, Wrangler, and Terraform all manage the same setting, plans become hard to trust. Pick the owner for each surface.

  • Do not share broad API tokens with CI.
  • Do not let dashboard edits become invisible permanent changes.
  • Do not manage generated or frequently changing deployment artifacts in Terraform unless you have a strong reason.

Working pattern

Use Terraform for the stable control plane: DNS, Access, project declarations, storage resources, and bindings. Use Wrangler or your framework deployment for code. Keep environment-specific records obvious and review every DNS or Access change like a production firewall change.

Cloudflare makes a good confidence-building platform because the resources are easy to inspect. After apply, verify the DNS record, Access app, Pages project, or storage namespace directly, then compare what you see with the Terraform state and next plan.

  • One root per zone or product boundary.
  • One token per automation path.
  • One owner per setting.
  • One no-op plan after import or dashboard cleanup.

The Review

  • Can you tell which resources are account-level versus zone-level?
  • Does Terraform own platform shape while deployment tooling owns code artifacts?
  • Are API tokens scoped to the narrowest account and zone permissions?
  • Can rollback happen without editing DNS by hand?
cloudflare dns edge readonly
resource "cloudflare_record" "www" {
  zone_id = var.zone_id
  name    = "www"
  type    = "CNAME"
  content = cloudflare_pages_project.web.subdomain
  proxied = true
}