In this guide, I'll show how I used cf-terraforming to import Cloudflare resources into Terraform code.


Important note: In the current iteration, I use Terraform primarily as a backup storage mechanism for Cloudflare resources. Management and modifications will continue to be performed manually via the Cloudflare Dashboard, as this approach is generally faster and more efficient.


Setting up access to Cloudflare

Before using Terraform with Cloudflare, users need to configure the appropriate environment variables.


Using an API key

If authenticating through an API Key, export the following environment variables:

export CLOUDFLARE_API_KEY=<EXAMPLE_KEY>
export CLOUDFLARE_EMAIL=<EXAMPLE_EMAIL>


Using an API token

Alternatively, authentication can be done with an API Token by exporting only this variable:

export CLOUDFLARE_API_TOKEN=<EXAMPLE_TOKEN>


Cloudflare's API Token authentication is flexible but requires complex configuration. To simplify the process, we recommend using an API Key associated with a user account. However, use it with caution, as the API Key grants full access to all Cloudflare actions.

To find the Global API Key or to create an API Token, visit Cloudflare API Tokens.


Using cf-terraforming

Cloudflare provides an official tool, cf-terraforming, which can generate Terraform configuration and state from existing resources. This is the recommended approach for automating the import process.



Step-by-step guide: Importing with cf-terraforming cf-terraforming


1. Initialize the Terraform provider:

To use this tool, initialize the provider. Create a temporary file, e.g., providers.tf, with the following configuration:

terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "4.43.0"
    }
  }
}

provider "cloudflare" {}


Then, initialize Terraform:

terraform init


2. Install cf-terraforming:

brew install cloudflare/cloudflare/cf-terraforming

Or download the release from the GitHub repository.


3. Generate Terraform resource configuration (e.g., for a DNS record):

cf-terraforming generate --resource-type cloudflare_record --zone <ZONE_ID> > generate.tf


Example output:

resource "cloudflare_record" "terraform_managed_resource_<RESOURCE_ID>" {
  content = "EXAMPLE_CONTENT"
  name    = "EXAMPLE_NAME"
  proxied = false
  ttl     = 1
  type    = "TXT"
  zone_id = "<ZONE_ID>"
}


4. Generate Terraform import configuration:

cf-terraforming import --resource-type cloudflare_record --zone <ZONE_ID> --modern-import-block > import.tf


Example output:

import {
  to = cloudflare_record.terraform_managed_resource_<RESOURCE_ID>
  id = "<ZONE_ID>/<RESOURCE_ID>"
}


5 Apply Terraform configuration:

terraform apply


Key considerations


A crucial aspect of using cf-terraforming is distinguishing between account-level and zone-level resources. Before using cf-terraforming, refer to the supported resources documentation to understand the resource scope.

To streamline the import process, automate cf-terraforming by using a loop to process multiple ZONE_ID values at once.


Important notes



By following this approach, you can efficiently back up Cloudflare resources while maintaining a clear and manageable Terraform state.