Skip to content

How to Use the Peakhour Terraform Provider

This guide shows you how to manage Peakhour domains, CDN settings, and edge security configuration using Terraform.

Before you begin: Create a Peakhour API key and install Terraform (v1.5+ recommended for import blocks and config generation).

Install the provider

Add the provider to your Terraform configuration:

terraform {
  required_providers {
    peakhour = {
      source = "peakhour-io/peakhour"
      # version = "x.y.z"
    }
  }
}

Authentication

The provider authenticates with a Peakhour API key.

Recommended: set the API key via environment variable:

export PEAKHOUR_API_KEY="your-api-key"

Or configure it directly:

provider "peakhour" {
  api_key = var.peakhour_api_key
}

API base URL (optional)

By default, the provider talks to https://console.peakhour.io.

To point at a different environment (staging, proxy, etc.):

export PEAKHOUR_BASE_URL="https://console.staging.peakhour.io"

Or in Terraform:

provider "peakhour" {
  base_url = "https://console.staging.peakhour.io"
}
Beta / private installs (filesystem mirror)

If you are installing a Peakhour-provided binary (not via the public Terraform Registry), configure a local filesystem mirror:

  1. Extract the provider bundle to a shared location (example):

    sudo mkdir -p /opt/peakhour/terraform-providers
    sudo tar -xzf peakhour-provider_0.1.0.tar.gz -C /opt/peakhour/terraform-providers
    

  2. Point Terraform at the mirror via ~/.terraformrc (or /etc/terraformrc):

    provider_installation {
      filesystem_mirror {
        path    = "/opt/peakhour/terraform-providers"
        include = ["peakhour-io/peakhour"]
      }
      direct {}
    }
    

Quickstart: onboard a new domain

This example creates a domain, assigns a plan, enables the reverse proxy service, and configures an origin pool.

provider "peakhour" {}

resource "peakhour_domain" "example" {
  name = "example.com"
}

resource "peakhour_domain_plan" "example" {
  domain = peakhour_domain.example.name
  code   = "basic"
}

resource "peakhour_reverse_proxy_service" "example" {
  domain     = peakhour_domain.example.name
  depends_on = [peakhour_domain_plan.example]
}

resource "peakhour_origin_pool" "backend" {
  domain = peakhour_domain.example.name
  tag    = "production"

  address = [
    {
      address = "192.0.2.10:443"
      weight  = 100
    }
  ]

  load_balancing_mode = "round_robin"
  depends_on          = [peakhour_reverse_proxy_service.example]
}

What you can manage with this provider

The provider supports managing Peakhour configuration across CDN, security, and performance features.

Domains and plans

  • peakhour_domain: Create and manage domains.
  • peakhour_domain_plan: Assign a subscription plan to a domain.

Reverse proxy (CDN) and origins

  • peakhour_reverse_proxy_service: Enable/disable the reverse proxy service.
  • peakhour_reverse_proxy_config: Configure gzip/brotli, WebSockets, aliases, and redirects.
  • peakhour_rp_settings: Manage RP settings like notification emails and quickstart mode.
  • peakhour_origin_pool: Configure origin pools and load balancing.
  • peakhour_rp_origin_config: Control RP origin behavior (SSL mode, origin request headers).
  • peakhour_rp_cdn_cache: Manage caching defaults.

TLS

  • peakhour_acme_settings: Configure ACME hostnames/SANs.
  • peakhour_acme_certificate: Read certificate status and optionally trigger issuance (async).
  • peakhour_rp_ssl_config: Manage cipher profile (e.g. modern, intermediate).
  • peakhour_rp_ssl_certificate: Upload a custom certificate and private key.

Firewall, WAF, and threat controls

  • peakhour_rule: Manage rules in phases (firewall, headers, caching, rate limiting, rewrites, load balancing, bulk redirects).
  • peakhour_rule_phase_order: Control rule evaluation order for a phase.
  • peakhour_rule_list: Manage IP/string/integer lists and reference them in filters with $list_name.
  • peakhour_rate_limit_settings: Enable/disable rate limiting modes for a domain.
  • peakhour_rate_limit_zone: Manage named rate limit zones (referenced by rules).
  • peakhour_rate_limit_global: Configure global rate limiting settings.
  • peakhour_rp_waf_options: Enable/disable WAF and select a ruleset.
  • peakhour_rp_waf_owasp_settings: Configure OWASP settings (JSON).
  • peakhour_rp_waf_custom_rule: Create custom WAF rules (JSON expressions/actions).
  • peakhour_rp_waf_rule_group: Enable/disable WAF rule groups within a ruleset.
  • peakhour_rp_bots: Configure verified-bot settings.
  • peakhour_rp_threat_access_list_rule: Manage threat access list rules.
  • peakhour_rp_threat_block_list: Manage enabled threat blocklists.
  • peakhour_rp_firewall_settings: Configure firewall settings (e.g. challenge cookie key).
  • peakhour_rp_firewall_error_page: Upload a custom firewall error page.
  • peakhour_rp_lua_options: Manage Lua options (enable/disable).

Redirects, transforms, and cache operations

  • peakhour_bulk_redirect_list / peakhour_bulk_redirect_entry: Manage bulk redirect lists and entries.
  • peakhour_transform_settings: Manage HTML/image transform settings.
  • peakhour_image_transform: Manage named image transforms (presets).
  • peakhour_image_transform_commit: Commit staged image transform changes.
  • peakhour_rp_cdn_purge_resources / peakhour_rp_cdn_purge_wildcard / peakhour_rp_cdn_purge_tags: Trigger cache purges (action resources).

Data sources

  • peakhour_domain: Look up an existing domain (useful for importing and for multi-workspace setups).

Common patterns and examples

Manage rules safely

  • Use Wirefilter for filter_str.
  • Use jsonencode(...) for JSON fields like actions_json to avoid formatting diffs.
Example: block a path
resource "peakhour_rule" "block_admin" {
  domain     = "example.com"
  phase      = "firewall"
  name       = "Block /admin"
  filter_str = "http.request.uri.path matches \"^/admin/\""
  enabled    = true

  actions_json = jsonencode({
    firewall = [{
      type   = "firewall"
      action = "deny"
      reason = "admin blocked"
    }]
  })
}

Use rate limit zones in rules

Example: per-IP API rate limiting
resource "peakhour_rate_limit_zone" "api" {
  domain                = "example.com"
  name                  = "api"
  requests_max          = 100
  requests_interval_sec = 60
  block_duration_sec    = 300
}

resource "peakhour_rule" "api_ratelimit" {
  domain     = "example.com"
  phase      = "rate_limit_request"
  name       = "API rate limit"
  filter_str = "http.request.uri.path matches \"^/api/\""
  enabled    = true

  actions_json = jsonencode({
    rate_limit_request = [{
      type                          = "rate_limit_request"
      check_zone                    = "api"
      check_zone_action             = "block"
      check_zone_action_status_code = 429
      zone_key                      = ["ip"]
    }]
  })

  depends_on = [peakhour_rate_limit_zone.api]
}

Commit image transform presets

Image transform presets are staged until committed. Use peakhour_image_transform_commit to deploy changes.

Example: create and commit a preset
resource "peakhour_image_transform" "thumbnail" {
  domain = "example.com"
  name   = "thumbnail"
  config_json = jsonencode({
    w   = 300
    h   = 300
    fit = "crop"
    fm  = "WEBP"
    q   = 80
  })
}

resource "peakhour_image_transform_commit" "commit" {
  domain = "example.com"
  triggers = {
    thumbnail = peakhour_image_transform.thumbnail.id
  }
}

The config uses a flat structure where all parameters are at the top level, matching the URL query parameter format used by the Image Optimization API.

For image transformation options, see the Image Optimisation API and the image optimisation reference.

Trigger cache purges with Terraform

Purge resources are actions, not stable desired state. To run another purge, change run_id (or taint the resource).

For purge concepts, see How to Purge the Cache.

Importing existing configuration

You can bring existing Peakhour configuration under Terraform management using terraform import (or import blocks in Terraform v1.5+).

Import ID formats (common)

Resource Import ID format
peakhour_domain example.com
peakhour_domain_plan example.com
Most domain-level resources (RP config, TLS settings, WAF options, etc.) example.com
peakhour_origin_pool example.com/origins/<tag>
peakhour_rule example.com/<phase>/<uuid>
peakhour_rule_list example.com/<uuid>
peakhour_rate_limit_zone example.com/<name>
peakhour_bulk_redirect_list example.com/bulk_redirects/<uuid>
peakhour_bulk_redirect_entry example.com/bulk_redirects/<uuid>/entries/<entry_id>
peakhour_rp_waf_custom_rule example.com/customrule/<uuid>
peakhour_rp_waf_rule_group example.com/ruleset/<ruleset>/rulegroup/<file_name>
peakhour_rp_threat_access_list_rule example.com/access_list/<uuid>
Example: import a rule list
terraform import peakhour_rule_list.blocked_ips "example.com/6b4f1a3d-...."
Bulk onboarding (many domains)

For onboarding a large existing account, the provider repo includes an onboarding helper that generates per-domain imports.tf scaffolding and works with Terraform config generation (terraform plan -generate-config-out=...).

If you have access to the provider repository and helper binaries, see peakhour-terraform/docs/onboarding-existing-config.md in that repo for a step-by-step workflow.

Known limitations and gotchas

  • peakhour_rp_ssl_certificate: the API does not return the uploaded private key (or certificate PEM), so Terraform cannot automatically detect drift for those values.
  • peakhour_rp_firewall_error_page: the API does not return the configured HTML content, so Terraform cannot detect drift of content.
  • peakhour_rule_phase_order: deleting the resource does not revert ordering.
  • Purge resources and peakhour_image_transform_commit are action/trigger resources; use inputs like run_id or triggers to control when they execute.

Troubleshooting

401 Unauthorized

  • Verify PEAKHOUR_API_KEY is set and valid.
  • Ensure the API key belongs to the account that owns the domain.

404 Not Found

  • Check that the domain exists in Peakhour.
  • Many resources require the reverse proxy service to be enabled first (peakhour_reverse_proxy_service).

Provider installation issues (private/beta)

  • Confirm your provider_installation block points at the correct filesystem mirror path.
  • Run terraform init -upgrade after changing provider installation settings.