manage your cloudflare configuration with - opentofu

October 24, 2026

opentofu

is a terraform fork that manages infrastructure as code. I used my cloudflare configuration to play around.

install

install tools (opentofu, sops and age)
  winget install --exact --id OpenTofu.Tofu
  winget install --exact --id SecretsOPerationS.SOPS
  winget install --exact --id FiloSottile.age

usage

main.tf opentofu file
terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 5.0"
    }
  }
}

provider "cloudflare" {}

variable "domain" {
  type    = string
  default = "(my.domain.name.here)"
}

# lookup zone
data "cloudflare_zone" "main" {
  filter = {
    name = var.domain
  }
}

# read dns of zone
data "cloudflare_dns_records" "alle" {
  zone_id = data.cloudflare_zone.main.id
}

# show dns records in output
output "dns_eintraege" {
  value = [
    for r in data.cloudflare_dns_records.alle.result :
    format("%-6s %-40s -> %s", r.type, r.name, r.content)
  ]
}
dns configuration
locals {
  zone_id = data.cloudflare_zone.main.id

  dns_records = {
    root_a = {
      name    = "mydomain.com"
      type    = "A"
      content = "200.100.0.200"
      proxied = true
    }
    dmarc = {
      name    = "_dmarc.mydomain.com"
      type    = "TXT"
      content = "\"v=DMARC1; p=reject; rua=mailto:..; ruf=mailto:..;\""
      comment = "no mails on this domain"
    }
    dkim_null = {
      name    = "*._domainkey.mydomain.com"
      type    = "TXT"
      content = "\"v=DKIM1; p=\""
      comment = "no mails on this domain"
    }
    spf = {
      name    = "mydomain.com"
      type    = "TXT"
      content = "\"v=spf1 -all\""
      comment = "no mails on this domain"
    }

    hint = {
      name    = "hint.mydomain.com"
      type    = "TXT"
      content = "\"domain managed bei opentofu\""
    }
  }
}

resource "cloudflare_dns_record" "this" {
  for_each = local.dns_records

  zone_id = local.zone_id
  name    = each.value.name
  type    = each.value.type
  content = each.value.content
  ttl     = try(each.value.ttl, 1)
  proxied = try(each.value.proxied, false)
}

run with

sops exec-env .\secrets.enc.env powershell
tofu plan
tofu apply