Automating Cloudflare DNS Management with Terraform

Automating Cloudflare DNS Management with Terraform
Automating Cloudflare DNS Management with Terraform

Why use terraform for managing DNS records?

If you're responsible for managing DNS records on Cloudflare across multiple domains, you know how repetetive it can be to keep updating DNS records all the time. You log into the Cloudflare dashboard, go to the DNS settings, and manually change each record, making sure to double-check every entry.

Manual DNS management is not slow. Small typo can result in service interruptions, and without version control, tracking changes or reverting updates can take time. Also, once the DNS entries get propagated - it for sure will lead to a downtime for minutes if not hours.

At KubeNine, we use Cloudflare heavily for us and our customers. We manage multiple domains on Cloudflare and have a need to update DNS records fairly frequently. To make this process smoother - we started using Terraform to manage our DNS records on cloudflare. Instead of relying on manual updates, Terraform lets you define DNS records in code—bringing automation, version control, and consistency to your workflow.


How Terraform Improves DNS Management

  • Automation – Define DNS configurations once and apply them consistently. Developers can create a pull request to add a new DNS record.
  • Version Control – Track changes using Git.
  • Security - No need to give everyone access to your cloudflare account - you can configure your cicd pipelines to run terraform code so that the modifications can be made only from your cicd pipeline. 

Now, let’s set up Terraform for Cloudflare step by step.

Step 1: Finding your cloudflare zone ID

Before configuring Terraform, you need your Cloudflare Zone ID.

Method 1: Cloudflare Dashboard

  1. Log in to Cloudflare Dashboard.
  2. Select your domain.
  3. The Zone ID is displayed on the overview page.

Method 2: Using Cloudflare CLI

If you prefer automation, you can use Cloudflare’s CLI tool.

  1. Install flarectl from Cloudflare-Go.
  2. Run the following command.
flarectl zone list

Step 2: Using cloudflare CLI for quick DNS management

Cloudflare CLI (flarectl) allows quick modifications without using the dashboard.

Listing all DNS records

flarectl dns list --zone yourdomain.com

This retrieves and displays all DNS records for your domain.

Creating a Terraform directory

mkdir cloudflare-terraform && cd cloudflare-terraform

This creates a new folder and navigates into it, where all Terraform configuration files will be stored.

Defining the Cloudflare provider

Create a file called main.tf and add the following:

provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

This tells Terraform to use the Cloudflare provider and authenticate using the API token.

Creating A record

resource "cloudflare_record" "example_dns_record" {
  zone_id = var.cloudflare_zone_id
  name    = "example.yourdomain.com"
  type    = "A"
  content = "192.168.1.1"
  ttl     = 3600
  proxied = true
}

This creates an A record for example.yourdomain.com, pointing to 192.168.1.1, with a TTL of 3600 seconds. The proxied = true setting enables Cloudflare's proxy for this record.

Step 4: Managing multiple DNS records dynamically

Instead of defining each record manually, a dynamic configuration makes things more efficient.

Using variables for multiple records

Create a variables.tf file:

variable "dns_records" {
  type = list(object({
    name    = string
    type    = string
    content = string
    ttl     = number
  }))
}

resource "cloudflare_record" "bulk_records" {
  count   = length(var.dns_records)
  zone_id = var.cloudflare_zone_id
  name    = var.dns_records[count.index].name
  type    = var.dns_records[count.index].type
  content = var.dns_records[count.index].content
  ttl     = var.dns_records[count.index].ttl
}

This configuration allows you to define multiple DNS records in a list instead of creating separate blocks for each.

Example record definitions

In terraform.tfvars, define multiple records:

dns_records = [
  { name = "app.yourdomain.com", type = "A", content = "192.168.1.1", ttl = 3600 },
  { name = "api.yourdomain.com", type = "CNAME", content = "example.com", ttl = 300 }
]

Step 5: Applying Terraform changes

Initializing terraform

terraform init

Previewing changes

terraform plan

This displays the planned changes before applying them.

Applying changes

terraform apply -auto-approve

This applies the changes and creates the DNS records in Cloudflare.

Edit main.tf and re-run:

terraform apply -auto-approve

This updates existing DNS records.

There are times when you might need to delete all DNS records managed by Terraform. This could be for reasons such as testing, removing outdated records, or shutting down a setup that you no longer require.

terraform destroy -auto-approve

This will remove all DNS records created by terraform, insuring a complete rollback.


Bonus: Configure PR workflow

Here’s a screenshot of how we have configured terraform report on PR creation. This helps us manage all the DNS records from a single place with version control

Step 6: Troubleshooting and best practices

Common issues and solutions

Issue

Cause

Solution

Authentication error

Incorrect API token

Verify terraform.tfvars

DNS record not updating

Conflict with manual changes

Delete conflicting record from Cloudflare

API rate limit reached

Too many requests at once

Use

-parellelism=1

Security best practices

  1. Do not hardcode API tokens
  • Use environment variables:
export CLOUDFLARE_API_TOKEN="your-token"
  1. Use terraform modules:
  • Organise configurations for different environments (dev, prod).

Conclusion

In a production environment you should consider managing DNS records with version control. With cloudflare support terraform - there’s no better option than that for managing DNS records.

We can easily configure a cicd pipeline to manage the entire workflow. This allows developers to manage the DNS records from a single place.

Would like to get this configured for your organisation? KubeNine can help, reach out to us!