Skip to main content

Configuration Cloudflare terraform

Ensemble de configurations Terraform pour la gestion de domaines, dns, cache et firewall rules sur Cloudflare

Vars

variable "zone_name" {}
variable "zone_id" {}
variable "bing_verify" {
  default     = "unset"
  description = "TXT record DNS content for Bing Verify"
}
variable "brotli" {
  default     = "on"
  description = "Enable or not brotli compression"
}
variable "minify_css" {
  default     = "off"
  description = "Minify or not CSS for zone settings"
}
variable "minify_html" {
  default     = "off"
  description = "Minify or not HTML for zone settings"
}
variable "minify_js" {
  default     = "off"
  description = "Minify or not JS for zone settings"
}
variable "always_online" {
  default     = "on"
  description = "Enable or not Always Online"
}
variable "devmode" {
  default     = "off"
  description = "Enable or disable Dev Mode on cloudflare"
}
variable "additional_spf" {
  default     = ""
  description = "Additional spf configuration for TXT DNS record"
}
variable "reject_spf" {
  default     = "~"
  description = "SPF reject mode for TXT DNS Record"
}
variable "additional_dmarc" {
  default     = ""
  description = "Additional dmarc configuration for TXT DNS record"
}
variable "root_record" {
  default     = ""
  description = "DNS root record IP address"
}
variable "root_ipv4" {
  default     = ""
  description = ""
}
variable "alias_domain" {
  default     = ""
  description = "Secondary alias domain"
}
variable "main_domain" {
  default     = ""
  description = "Principal domain name"
}

Zone settings

resource "cloudflare_zone_settings_override" "settings" {
  zone_id = var.zone_id
  settings {
    always_online            = "on"
    always_use_https         = "off"
    automatic_https_rewrites = "off"
    brotli                   = "on"
    cache_level              = "basic"
    development_mode         = var.devmode
    email_obfuscation        = "off"
    http3                    = "on"
    browser_cache_ttl        = 0
    early_hints              = "off"
    ip_geolocation           = "on"
    ipv6                     = "on"
    max_upload               = 100
    min_tls_version          = "1.2"
    pseudo_ipv4              = "off"
    rocket_loader            = "off"
    ssl                      = "strict"
    minify {
      css  = var.minify_css
      js   = var.minify_js
      html = var.minify_html
    }
  }
}

Firewall rules

resource "cloudflare_ruleset" "bwa_custom_restrictions" {
  zone_id     = var.zone_id
  name        = "Restrict WP Cron"
  description = "Restrict WP Cron"
  kind        = "zone"
  phase       = "http_request_firewall_custom"

  # rules {
  #   description = "Allow some safe places"
  #   action = "skip"
  #   action_parameters {
  #     ruleset = "current"
  #   }
  #   expression = "(ip.src eq 86.253.64.29) or (http.request.uri.query contains \"wc_vivawallet\") or (http.user_agent contains \"mj12bot\") or (http.request.uri.query contains \"trustindex_reviews_hook_google\") or (http.request.uri.path contains \".ico\") or (http.user_agent contains \"bitlybot\") or (http.user_agent eq \"Better Uptime Bot Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\") or (http.user_agent contains \"updown.io daemon 2.8\") or (http.request.uri.path contains \"favicon\") or (http.user_agent contains \"DuckDuckGo\") or (http.user_agent contains \"Pingdom\") or (http.user_agent contains \"PetalBot\") or (http.user_agent contains \"NIXStatsbot\") or (http.user_agent contains \"CFNetwork\") or (http.user_agent contains \"qwant.com\") or (http.user_agent contains \"bingbot\") or (http.user_agent contains \"updown.io daemon 2.6\") or (http.user_agent contains \"Stripe/1.0\") or (ip.src eq 3.18.12.63) or (ip.src eq 3.130.192.231) or (ip.src eq 13.235.14.237) or (ip.src eq 13.235.122.149) or (ip.src eq 109.234.160.247) or (ip.src eq 18.211.135.69) or (ip.src eq 35.154.171.200) or (ip.src eq 52.15.183.38) or (ip.src eq 54.88.130.119) or (ip.src eq 54.88.130.237) or (ip.src eq 54.187.174.169) or (ip.src eq 54.187.205.235) or (ip.src eq 54.187.216.72) or (ip.src eq 109.234.161.131) or (ip.src eq 109.234.161.208) or (ip.src eq 109.234.161.202) or (ip.src eq 109.234.164.29) or (ip.src eq 163.172.33.112)"
  #   enabled = true
  # }
  rules {
    description = "Restrict WP-Cron"
    action      = "block"
    expression  = "(http.request.uri.path eq \"/wp-cron.php\" and ip.src ne 163.172.51.134) or (http.request.uri.path eq \"/wp-cron.php\" and ip.src ne 163.172.53.51) or (http.request.uri.path eq \"/wp-cron.php\" and ip.src ne 82.66.241.38) or (http.request.uri.path eq \"/wp-cron.php\" and ip.src ne 163.172.33.112) or (http.request.uri.path eq \"/wp-config.php\")"
    enabled     = true
  }
  rules {
    description = "Challenge wp-admin out of France"
    action      = "managed_challenge"
    enabled     = true
    expression  = "(http.request.uri.path contains \"/wp-login.php\" and  ip.geoip.country ne \"FR\") or (http.request.uri.query contains \"action=lostpassword\" and http.referer ne \"${var.zone_name}\")"
  }
  rules {
    description = "Restrict some WP Path and countries"
    action      = "managed_challenge"
    expression  = "(http.request.uri eq \"/xmlrpc.php\") or (http.request.uri contains \"/wp-comments-post.php\" and http.request.method eq \"POST\" and not http.referer contains \"${var.zone_name}\") or (ip.geoip.country eq \"RU\" or ip.geoip.country eq \"BR\")"
    enabled     = true
  }
  rules {
    description = "Block bad bots"
    action      = "block"
    expression  = "(http.user_agent contains \"muckrack\") or (http.user_agent contains \"Sogou\") or (http.user_agent contains \"BUbiNG\") or (http.user_agent contains \"knowledge\") or (http.user_agent contains \"CFNetwork\") or (http.user_agent contains \"Scrapy\") or (http.user_agent contains \"SemrushBot\") or (http.user_agent contains \"AhrefsBot\") or (http.user_agent contains \"Baiduspider\") or (http.user_agent contains \"python-requests\") or (http.user_agent contains \"crawl\" and not cf.client.bot) or (http.user_agent contains \"Crawl\" and not cf.client.bot) or (http.user_agent contains \"bot\" and not http.user_agent contains \"bingbot\" and not http.user_agent contains \"Google\" and not http.user_agent contains \"Twitter\" and not cf.client.bot) or (http.user_agent contains \"Bot\" and not http.user_agent contains \"Google\" and not cf.client.bot) or (http.user_agent contains \"Spider\" and not cf.client.bot) or (http.user_agent contains \"spider\" and not cf.client.bot)"
    enabled     = true
  }
}

Wordpress cache rules

resource "cloudflare_ruleset" "custom_bwa_cache_ruleset" {
  zone_id = var.zone_id
  kind    = "zone"
  name    = "default"
  phase   = "http_request_cache_settings"
  rules {
    action = "set_cache_settings"
    action_parameters {
      browser_ttl {
        mode = "respect_origin"
      }
      cache = false
    }
    description = "Skip admin pages"
    enabled     = true
    expression  = "(http.request.uri.path contains \"wp-admin\") or (http.request.uri.path contains \"wp-login\") or (http.request.uri.path contains \"bwa35-login\")"
  }
  rules {
    action      = "set_cache_settings"
    description = "Cache static assets"
    enabled     = true
    expression  = "(http.request.uri.path contains \".webp\") or (http.request.uri.path contains \".avif\") or (http.request.uri.path contains \".woff\") or (http.request.uri.path contains \".woff2\") or (http.request.uri.path contains \".png\") or (http.request.uri.path contains \".svg\") or (http.request.uri.path contains \".jpeg\") or (http.request.uri.path contains \".jpg\") or (http.request.uri.path contains \".js\") or (http.request.uri.path contains \".css\")"
    action_parameters {
      browser_ttl {
        mode = "respect_origin"
      }
      cache = true
      cache_key {
        cache_deception_armor = false
        custom_key {
          query_string {
            exclude = ["*"]
          }
        }
        ignore_query_strings_order = true
      }
      edge_ttl {
        default = 2678400
        mode    = "override_origin"
      }
      origin_error_page_passthru = true
      serve_stale {
        disable_stale_while_updating = true
      }
    }
  }
  rules {
    action = "set_cache_settings"
    action_parameters {
      browser_ttl {
        default = 14400
        mode    = "override_origin"
      }
      cache = true
      edge_ttl {
        default = 172800
        mode    = "override_origin"
      }
    }
    description = "Full cache on uploads"
    enabled     = true
    expression  = "(http.request.uri.path contains \"/wp-content/uploads/\")"
  }
}

Redirection vers le domaine principal

resource "cloudflare_ruleset" "redirect_to_main_domain" {
  zone_id     = var.zone_id
  name        = "redirects"
  description = "Redirect to main domain"
  kind        = "zone"
  phase       = "http_request_dynamic_redirect"

  rules {
    action = "redirect"
    action_parameters {
      from_value {
        status_code = 301
        target_url {
          value = "https://${var.main_domain}"
        }
        preserve_query_string = false
      }
    }
    expression  = "(http.host eq \"${var.alias_domain}\")"
    description = "Redirecte to main domain"
    enabled     = true
  }
}