INTEGRITY Cloudflare Docs

Rate limiting rules configuration using Terraform

This page provides examples of creating rate limiting rules in a zone or account using Terraform.

If you are using the Cloudflare API, refer to the following resources:

Before you start

Obtain the necessary account or zone IDs

The Terraform configurations provided in this page need the zone ID (or account ID) of the zone/account where you will deploy rulesets.

Import or delete existing rulesets

Terraform assumes that it has complete control over account and zone rulesets. If you already have rulesets configured in your account or zone, do one of the following:


Create a rate limiting rule at the zone level

This example creates a rate limiting rule in zone with ID <ZONE_ID> blocking traffic that exceeds the configured rate:

Required API token permissions

At least one of the following token permissions is required:

  • Zone WAF Write

Configure the cloudflare_ruleset resource:

resource "cloudflare_ruleset" "zone_rl" {
  zone_id     = var.cloudflare_zone_id
  name        = "Rate limiting for my zone"
  description = ""
  kind        = "zone"
  phase       = "http_ratelimit"

  rules = [{
    ref         = "rate_limit_api_requests_ip"
    description = "Rate limit API requests by IP"
    expression  = "(http.request.uri.path matches \"^/api/\")"
    action      = "block"
    ratelimit = {
      characteristics     = ["cf.colo.id", "ip.src"]
      period              = 60
      requests_per_period = 100
      mitigation_timeout  = 600
    }
  }]
}
resource "cloudflare_ruleset" "zone_rl" {
  zone_id     = "<ZONE_ID>"
  name        = "Rate limiting for my zone"
  description = ""
  kind        = "zone"
  phase       = "http_ratelimit"

  rules {
    ref         = "rate_limit_api_requests_ip"
    description = "Rate limit API requests by IP"
    expression  = "(http.request.uri.path matches \"^/api/\")"
    action      = "block"
    ratelimit {
      characteristics = ["cf.colo.id", "ip.src"]
      period = 60
      requests_per_period = 100
      mitigation_timeout = 600
    }
  }
}

To create another rate limiting rule, add a new rules object to the same cloudflare_ruleset resource.


Create a rate limiting rule at the account level

This example defines a custom ruleset with a single rate limiting rule in account with ID <ACCOUNT_ID> that blocks traffic for the /api/ path exceeding the configured rate. The second cloudflare_ruleset resource defines an execute rule that deploys the custom ruleset for traffic addressed at example.com.

Required API token permissions

All of the following token permissions are required:

  • Account WAF Write
  • Account Rulesets Write

Configure the cloudflare_ruleset resource:

resource "cloudflare_ruleset" "account_rl" {
  account_id  = var.cloudflare_account_id
  name        = "Rate limiting rules for APIs"
  description = ""
  kind        = "custom"
  phase       = "http_ratelimit"

  rules = [{
    ref         = "rate_limit_api_ip"
    description = "Rate limit API requests by IP"
    expression  = "http.request.uri.path contains \"/api/\""
    action      = "block"
    ratelimit = {
      characteristics     = ["cf.colo.id", "ip.src"]
      period              = 60
      requests_per_period = 100
      mitigation_timeout  = 600
    }
  }]
}

# Account-level entry point ruleset for the 'http_ratelimit' phase
resource "cloudflare_ruleset" "account_rl_entrypoint" {
  account_id  = var.cloudflare_account_id
  name        = "Account-level rate limiting"
  description = ""
  kind        = "root"
  phase       = "http_ratelimit"

  depends_on = [cloudflare_ruleset.account_rl]

  rules = [{
    # Deploy the previously defined custom ruleset containing a rate limiting rule
    ref         = "deploy_rate_limit_example_com"
    description = "Deploy custom ruleset with RL rule"
    expression  = "cf.zone.name eq \"example.com\" and cf.zone.plan eq \"ENT\""
    action      = "execute"
    action_parameters = {
      id = cloudflare_ruleset.account_rl.id
    }
  }]
}
resource "cloudflare_ruleset" "account_rl" {
  account_id  = "<ACCOUNT_ID>"
  name        = "Rate limiting rules for APIs"
  description = ""
  kind        = "custom"
  phase       = "http_ratelimit"

  rules {
    ref         = "rate_limit_api_ip"
    description = "Rate limit API requests by IP"
    expression  = "http.request.uri.path contains \"/api/\""
    action      = "block"
    ratelimit {
      characteristics     = ["cf.colo.id", "ip.src"]
      period              = 60
      requests_per_period = 100
      mitigation_timeout  = 600
    }
  }
}

# Account-level entry point ruleset for the 'http_ratelimit' phase
resource "cloudflare_ruleset" "account_rl_entrypoint" {
  account_id  = "<ACCOUNT_ID>"
  name        = "Account-level rate limiting"
  description = ""
  kind        = "root"
  phase       = "http_ratelimit"

  depends_on = [cloudflare_ruleset.account_rl]

  rules {
    # Deploy the previously defined custom ruleset containing a rate limiting rule
    ref         = "deploy_rate_limit_example_com"
    description = "Deploy custom ruleset with RL rule"
    expression  = "cf.zone.name eq \"example.com\" and cf.zone.plan eq \"ENT\""
    action      = "execute"
    action_parameters {
      id = cloudflare_ruleset.account_rl.id
    }
  }
}

To create another rate limiting rule, add a new rules object to the same cloudflare_ruleset resource.


Create an advanced rate limiting rule

This example creates a rate limiting rule in zone with ID <ZONE_ID> with:

Required API token permissions

At least one of the following token permissions is required:

  • Zone WAF Write

Configure the cloudflare_ruleset resource:

resource "cloudflare_ruleset" "zone_rl_custom_response" {
  zone_id     = var.cloudflare_zone_id
  name        = "Advanced rate limiting rule for my zone"
  description = ""
  kind        = "zone"
  phase       = "http_ratelimit"

  rules = [{
    ref         = "rate_limit_example_com_status_404"
    description = "Rate limit requests to www.example.com when exceeding the threshold of 404 responses on /status/"
    expression  = "http.host eq \"www.example.com\" and (http.request.uri.path matches \"^/status/\")"
    action      = "block"
    action_parameters = {
      response = {
        status_code  = 429
        content      = "{\"response\": \"block\"}"
        content_type = "application/json"
      }
    }
    ratelimit = {
      characteristics     = ["ip.src", "cf.colo.id"]
      period              = 10
      requests_per_period = 5
      mitigation_timeout  = 30
      counting_expression = "(http.host eq \"www.example.com\") and (http.request.uri.path matches \"^/status/\") and (http.response.code eq 404)"
    }
  }]
}
resource "cloudflare_ruleset" "zone_rl_custom_response" {
  zone_id     = "<ZONE_ID>"
  name        = "Advanced rate limiting rule for my zone"
  description = ""
  kind        = "zone"
  phase       = "http_ratelimit"

  rules {
    ref         = "rate_limit_example_com_status_404"
    description = "Rate limit requests to www.example.com when exceeding the threshold of 404 responses on /status/"
    expression  = "http.host eq \"www.example.com\" and (http.request.uri.path matches \"^/status/\")"
    action      = "block"
    action_parameters {
      response {
        status_code  = 429
        content      = "{\"response\": \"block\"}"
        content_type = "application/json"
      }
    }
    ratelimit {
      characteristics     = ["ip.src", "cf.colo.id"]
      period              = 10
      requests_per_period = 5
      mitigation_timeout  = 30
      counting_expression = "(http.host eq \"www.example.com\") and (http.request.uri.path matches \"^/status/\") and (http.response.code eq 404)"
    }
  }
}

To create another rate limiting rule, add a new rules object to the same cloudflare_ruleset resource.