Infrastructure as Code (IaC)

To ensure our Cloudflare configurations are version-controlled, repeatable, and manageable, we use an Infrastructure as Code (IaC) approach. Our chosen tool for this is Terraform.

Why IaC?

  • Version Control: All infrastructure configuration is stored in Git. We can see who changed what and when.
  • Repeatability: We can easily create identical environments (e.g., staging, production) from the same code.
  • Automation: Reduces the need for manual configuration in the Cloudflare dashboard, which can be error-prone.
  • Disaster Recovery: We can quickly rebuild our entire infrastructure from code in the event of a disaster.

What We Manage with Terraform

We use Terraform to manage Cloudflare resources that are not directly handled by the Cloudflare Pages Git integration. This includes:

  • DNS Records: A, CNAME, MX, TXT records.
  • Cloudflare Workers: For standalone functions that are not part of a Pages project.
  • D1 Databases: Our serverless SQL databases.
  • R2 Storage Buckets: Our S3-compatible object storage.
  • KV Namespaces: Key-value storage.
  • Firewall Rules and WAF settings.
  • Page Rules and Redirects.
  • Cloudflare Tunnels and Access policies.

Getting Started with Terraform for Cloudflare

  1. Installation:

    • Install Terraform from the official website.
    • We recommend using a version manager like tfenv.
  2. Provider Configuration:

    • Create a file named main.tf (or similar) to configure the Cloudflare provider.
    • You will need a Cloudflare API token with appropriate permissions. This token should be stored as a secret, not hardcoded.
    terraform {
      required_providers {
        cloudflare = {
          source  = "cloudflare/cloudflare"
          version = "~> 4"
        }
      }
    }
     
    # Configure the Cloudflare Provider
    # The API token can be set via an environment variable (CF_API_TOKEN)
    provider "cloudflare" {}
     
    # Example: Define a DNS record
    resource "cloudflare_record" "example" {
      zone_id = var.cloudflare_zone_id
      name    = "example"
      value   = "192.0.2.1"
      type    = "A"
      proxied = true
    }

State Management

  • Terraform State: Terraform keeps track of the resources it manages in a state file.
  • Remote State: It is crucial that we use a remote backend to store the state file, not the local filesystem. This allows multiple team members to work on the same infrastructure and prevents state file loss.
  • Backend: We use Cloudflare R2 as our remote backend for Terraform state.

Example Backend Configuration:

terraform {
  backend "s3" {
    endpoint = "YOUR_CLOUDFLARE_ACCOUNT_ID.r2.cloudflarestorage.com"
    bucket   = "terraform-state-bucket"
    key      = "project-name/terraform.tfstate"
    region   = "auto"
    # Credentials should be configured via environment variables
  }
}

Workflow

  1. Setup: A dedicated Git repository is created for the Terraform configuration of each project.
  2. Plan: Before making any changes, run terraform plan.
    • This command shows you what changes Terraform will make to your infrastructure.
    • It is a dry run and is safe to run at any time.
  3. Apply: If the plan looks correct, run terraform apply.
    • This command will execute the plan and create, update, or delete resources in your Cloudflare account.
  4. Pull Requests: All changes to the Terraform code must go through our standard Pull Request and code review process.
    • The PR should include the output of the terraform plan command so the reviewer can see the proposed changes.
  5. CI/CD: We use a CI/CD pipeline (e.g., GitHub Actions) to automate the plan and apply steps.
    • The pipeline runs terraform plan on every PR.
    • When a PR is merged to main, the pipeline automatically runs terraform apply.

By strictly adhering to this IaC workflow, we maintain a stable, secure, and well-documented infrastructure.