Redpanda Terraform Provider
Use the Redpanda Terraform provider to define, automate, and track changes to your Redpanda Cloud infrastructure as code.
With the Redpanda Terraform provider, you can manage:
Why use Terraform with Redpanda?
-
Simplicity: Manage all your Redpanda Cloud resources in one place.
-
Automation: Create and modify resources without manual intervention.
-
Version control: Track and roll back changes using version control systems, such as GitHub.
-
Scalability: Scale your infrastructure as your needs grow with minimal effort.
Understand Terraform configurations
Terraform configurations are written in HCL (HashiCorp Configuration Language), which is declarative. Here are the main building blocks of a Terraform configuration:
Providers
Providers tell Terraform how to communicate with the services you want to manage. For example, the Redpanda provider connects to the Redpanda Cloud API using client credentials.
provider "redpanda" {
client_id = "<client_id>"
client_secret = "<client_secret>"
}
Resources
Resources define the infrastructure components you want to create, such as networks, clusters, or topics. Each resource block specifies the type of resource and its configuration.
resource "redpanda_network" "example" { (1)
name = "example-network" (2)
cloud_provider = "aws" (3)
region = "us-east-1" (4)
cidr_block = "10.0.0.0/20" (5)
}
| 1 | The resource type (redpanda_network) and internal name (example). Terraform uses the internal name to reference the resource elsewhere in your configuration; for example, redpanda_network.example.id returns the network’s unique ID. The internal name does not appear in Redpanda Cloud. |
| 2 | A user-defined name for the resource as it appears in Redpanda Cloud. This is the user-facing name visible in the Redpanda UI and API. |
| 3 | The cloud provider where the network is deployed, such as AWS or GCP. |
| 4 | The region where the resource is provisioned. |
| 5 | The IP address range for the network. |
Variables
Variables allow you to parameterize your configuration, making it reusable and customizable for different environments. Use variable blocks to define reusable values, like region, which can be overridden when running Terraform.
variable "region" {
default = "us-east-1"
}
resource "redpanda_network" "example" {
name = "example-network"
cloud_provider = "aws"
region = var.region
cidr_block = "10.0.0.0/20"
}
Outputs
Outputs let you extract information about your infrastructure, such as cluster URLs, to use in other configurations or scripts.
This example displays the cluster’s API URL after Terraform provisions the resources:
output "cluster_api_url" {
value = data.redpanda_cluster.example.cluster_api_url
}
Limitations
The following functionality is supported in the Cloud API but not in the Redpanda Terraform provider:
-
Creating or deleting BYOVNet clusters on Azure
-
Secrets
-
Kafka Connect
|
If To prevent this, apply one or both of the following:
|
Prerequisites
|
Redpanda Terraform Provider - Windows Support Notice The Redpanda Terraform provider does not support Windows. To use it on Windows, install Windows Subsystem for Linux 2 (WSL2). To use WSL2 with the Redpanda Terraform provider:
|
-
Install Terraform 1.0.0 or later using the official guide.
-
Create a service account in Redpanda Cloud:
-
Log in to Redpanda Cloud.
-
Navigate to the Organization IAM page and select the Service account tab. Click Create service account and provide a name for the new service account.
-
Save the client ID and client secret for authentication.
-
Set up the provider
-
Add the Redpanda provider to your Terraform configuration:
terraform { required_providers { redpanda = { source = "redpanda-data/redpanda" version = "~> 1.0" } } } -
Initialize Terraform to download the provider:
terraform init -
Add the service account credentials you saved in Prerequisites as environment variables or in your Terraform configuration file:
-
Environment variables
-
Static credentials
REDPANDA_CLIENT_ID=<client_id> REDPANDA_CLIENT_SECRET=<client_secret>provider "redpanda" { client_id = "<client_id>" client_secret = "<client_secret>" } -
Manage sensitive attributes with write-only fields
You can use Terraform 1.11+ write-only attributes to keep sensitive values out of your Terraform state file. By default, Terraform persists sensitive attributes such as passwords to .tfstate when you run terraform apply. When you store state in a remote backend or in CI runner artifacts, this can leak credentials.
|
Write-only attributes require Terraform CLI 1.11 or later and Redpanda Terraform provider v1.6.0 or later. |
How write-only attributes work
For each supported sensitive field, the provider exposes two new attributes alongside the existing one:
-
<field>_wo: A write-only attribute. Terraform sends the value to the provider duringapplybut never persists it to state. -
<field>_wo_version: An integer version. Because Terraform cannot detect changes in a write-only value (there is nothing to compare against in state), you increment this number to signal that the value has changed and to trigger an update on the next apply.
redpanda_pipeline is an exception to this naming convention. The existing client_secret attribute is the write-only attribute (no separate client_secret_wo field), and is paired with secret_version instead of client_secret_wo_version.
|
The provider retains the original plaintext attributes for backward compatibility. You can migrate to the write-only variants on your own schedule. Avoid setting both the plaintext attribute and its write-only counterpart on the same resource. If both are set, the provider uses the write-only value.
Supported attributes
| Resource | Plaintext attribute (deprecated) | Write-only attribute | Version attribute |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Set a write-only attribute
Inject the sensitive value through a sensitive Terraform variable, an environment variable, or your secrets manager. The following example uses a TF_VAR_ environment variable to populate var.schema_password:
variable "schema_password" {
description = "Password for the Schema Registry user"
sensitive = true
}
resource "redpanda_user" "schema_user" {
name = "schema-user"
password_wo = var.schema_password
password_wo_version = 1
mechanism = "scram-sha-256"
cluster_api_url = data.redpanda_cluster.byoc.cluster_api_url
allow_deletion = true
}
Set the variable before running Terraform:
export TF_VAR_schema_password="your-secret-password"
terraform apply
Terraform sends the value to Redpanda Cloud during apply but never writes it to .tfstate.
Rotate a write-only attribute
Because Terraform cannot detect a change in the write-only value itself, increment the corresponding _wo_version to trigger an update:
resource "redpanda_user" "schema_user" {
name = "schema-user"
password_wo = var.schema_password # Set TF_VAR_schema_password to the new value
password_wo_version = 2 # Increment from 1 to trigger update
mechanism = "scram-sha-256"
cluster_api_url = data.redpanda_cluster.byoc.cluster_api_url
allow_deletion = true
}
After running terraform apply, the provider sends the new password to Redpanda Cloud. Neither the old nor the new value is written to state.
Examples
The following examples use the Redpanda Terraform provider to create and manage clusters. For descriptions of resources and data sources, see the Redpanda Terraform Provider documentation.
For more information on the different cluster types mentioned in these examples, see Redpanda Cloud cluster types.
| See the full list of zones and tiers available with each cloud provider in the Control Plane API reference. |
Create a BYOC cluster
A BYOC (Bring Your Own Cloud) cluster runs in your own cloud account. This example creates one on AWS with a custom network, resource group, and cluster.
terraform {
required_providers {
redpanda = {
source = "redpanda-data/redpanda"
version = "~> 1.0"
}
}
}
# Variables to parameterize the configuration
variable "resource_group_name" {
description = "Name of the Redpanda resource group"
default = "testname"
}
variable "network_name" {
description = "Name of the Redpanda network"
default = "testname"
}
variable "cluster_name" {
description = "Name of the Redpanda BYOC cluster"
default = "test-cluster"
}
variable "region" {
description = "Region for the Redpanda network and cluster"
default = "us-east-2"
}
variable "cloud_provider" {
description = "Cloud provider for the Redpanda network"
default = "aws"
}
variable "zones" {
description = "List of availability zones for the cluster"
type = list(string)
default = ["use2-az1", "use2-az2", "use2-az3"]
}
variable "cidr_block" {
description = "CIDR block for the Redpanda network"
default = "10.0.0.0/20"
}
variable "throughput_tier" {
description = "Throughput tier for the cluster"
default = "tier-1-aws-v2-x86"
}
# Redpanda provider configuration
provider "redpanda" {}
# Create a Redpanda resource group
resource "redpanda_resource_group" "test" {
name = var.resource_group_name
}
# Create a Redpanda network
resource "redpanda_network" "test" {
name = var.network_name
resource_group_id = redpanda_resource_group.test.id
cloud_provider = var.cloud_provider
region = var.region
cluster_type = "byoc" # Specify BYOC cluster type
cidr_block = var.cidr_block
}
# Create a Redpanda BYOC cluster
resource "redpanda_cluster" "test" {
name = var.cluster_name
resource_group_id = redpanda_resource_group.test.id
network_id = redpanda_network.test.id
cloud_provider = var.cloud_provider
region = var.region
cluster_type = "byoc"
connection_type = "public" # Publicly accessible cluster
throughput_tier = var.throughput_tier
zones = var.zones
allow_deletion = true # Allow the cluster to be deleted
tags = { # Add metadata tags
"environment" = "dev"
}
}
Create a Dedicated cluster
Redpanda fully manages Dedicated clusters for consistent performance. This example creates one on AWS with specific zones and a usage tier.
terraform {
required_providers {
redpanda = {
source = "redpanda-data/redpanda"
version = "~> 1.0"
}
}
}
# Variables for configuration
variable "resource_group_name" {
description = "Name of the Redpanda resource group"
default = "test-dedicated-group"
}
variable "network_name" {
description = "Name of the Redpanda network"
default = "dedicated-network"
}
variable "cluster_name" {
description = "Name of the Redpanda dedicated cluster"
default = "dedicated-cluster"
}
variable "region" {
description = "Region for the Redpanda network and cluster"
default = "us-west-1"
}
variable "cloud_provider" {
description = "Cloud provider for the Redpanda network"
default = "aws"
}
variable "zones" {
description = "List of availability zones for the cluster"
type = list(string)
default = ["usw1-az1", "usw1-az2", "usw1-az3"]
}
variable "cidr_block" {
description = "CIDR block for the Redpanda network"
default = "10.1.0.0/20"
}
variable "throughput_tier" {
description = "Throughput tier for the dedicated cluster"
default = "tier-1-aws-v2-arm"
}
# Redpanda provider configuration
provider "redpanda" {}
# Create a Redpanda resource group
resource "redpanda_resource_group" "test" {
name = var.resource_group_name
}
# Create a Redpanda network
resource "redpanda_network" "test" {
name = var.network_name
resource_group_id = redpanda_resource_group.test.id
cloud_provider = var.cloud_provider
region = var.region
cluster_type = "dedicated" # Specify Dedicated cluster type
cidr_block = var.cidr_block
}
# Create a Redpanda dedicated cluster
resource "redpanda_cluster" "test" {
name = var.cluster_name
resource_group_id = redpanda_resource_group.test.id
network_id = redpanda_network.test.id
cloud_provider = var.cloud_provider
region = var.region
cluster_type = "dedicated"
connection_type = "public"
throughput_tier = var.throughput_tier
zones = var.zones
allow_deletion = true
aws_private_link = { # Configure AWS PrivateLink for dedicated clusters
enabled = true
connect_console = true
allowed_principals = ["arn:aws:iam::123456789024:root"]
supported_regions = ["us-east-1", "us-west-2"] # Optional: Enable cross-region PrivateLink
}
tags = {
"environment" = "dev"
}
}
Create a Serverless cluster
A Serverless cluster is cost-effective and scales automatically based on usage. This example creates a cluster in the us-east-1 region with minimal configuration.
terraform {
required_providers {
redpanda = {
source = "redpanda-data/redpanda"
version = "~> 1.0"
}
}
}
# Redpanda provider configuration
provider "redpanda" {}
# Define a resource group for the Serverless cluster
resource "redpanda_resource_group" "test" {
name = var.resource_group_name # Name of the resource group
}
# Create a Serverless cluster
resource "redpanda_serverless_cluster" "test" {
name = var.cluster_name # Name of the Serverless cluster
resource_group_id = redpanda_resource_group.test.id # Link to the resource group
serverless_region = var.region # Specify the region for the cluster
}
# Variables for parameterizing the configuration
variable "resource_group_name" {
description = "Name of the Redpanda resource group"
default = "testgroup" # Default name for the resource group
}
variable "cluster_name" {
description = "Name of the Redpanda Serverless cluster"
default = "testname" # Default name for the Serverless cluster
}
variable "region" {
description = "Region for the Serverless cluster"
default = "us-east-1" # Default region for the cluster
}
Manage an existing cluster
To manage resources in an existing cluster, reference it by cluster ID using a data source. The data source exposes a cluster_api_url attribute that other resources (such as redpanda_topic) reference to connect to the cluster.
data "redpanda_cluster" "byoc" {
id = "byoc-cluster-id"
}
resource "redpanda_topic" "example" {
name = "example-topic"
partition_count = 3
replication_factor = 3
cluster_api_url = data.redpanda_cluster.byoc.cluster_api_url
}
Manage Schema Registry and Schema Registry ACLs
You can also use Terraform to manage data plane resources, such as schemas and access controls, through the Redpanda Schema Registry.
Use the Redpanda Terraform provider to create, update, and delete schemas and manage fine-grained access control for Schema Registry resources.
You can use the following Terraform resources:
-
redpanda_schema: Defines and manages schemas in the Schema Registry. -
redpanda_schema_registry_acl: Defines access control policies for Schema Registry subjects or registry-wide operations.
Create a schema
The redpanda_schema resource registers a schema. Each schema belongs to a subject, a logical name used for schema versioning. When you create or update a schema, Redpanda validates its compatibility level.
data "redpanda_cluster" "byoc" {
id = "byoc-cluster-id"
}
resource "redpanda_user" "schema_user" {
name = "schema-user"
password_wo = var.schema_password
password_wo_version = 1
mechanism = "scram-sha-256"
cluster_api_url = data.redpanda_cluster.byoc.cluster_api_url
allow_deletion = true
}
resource "redpanda_schema" "user_events" {
cluster_id = data.redpanda_cluster.byoc.id
subject = "user_events-value"
schema_type = "AVRO"
schema = jsonencode({
type = "record"
name = "UserEvent"
fields = [
{ name = "user_id", type = "string" },
{ name = "event_type", type = "string" },
{ name = "timestamp", type = "long" }
]
})
username = redpanda_user.schema_user.name
password_wo = var.schema_password
password_wo_version = 1
}
In this example:
-
cluster_ididentifies the Redpanda cluster where the schema is stored. -
subjectdefines the logical name under which schema versions are registered. -
schema_typespecifies the serialization type (AVRO,JSON, orPROTOBUF). -
schemaprovides the full schema definition, encoded withjsonencode(). -
usernameidentifies the Schema Registry user. Setpassword_woto the password value, and incrementpassword_wo_versionto trigger updates. For details, see Manage sensitive attributes with write-only fields.
Store credentials securely
Use Terraform 1.11+ write-only attributes (such as password_wo) to keep Schema Registry credentials out of your .tfstate file. For details, see Manage sensitive attributes with write-only fields.
For short-lived credentials or CI/CD usage, you can also export the Schema Registry credentials as provider-level environment variables. The provider reads them automatically:
export REDPANDA_SR_USERNAME=schema-user
export REDPANDA_SR_PASSWORD="schema-registry-password"
If you must use the deprecated plaintext password attribute (for example, on Terraform versions earlier than 1.11), declare a sensitive Terraform variable and inject the value at runtime to avoid committing secrets to source control:
variable "schema_password" {
description = "Password for the Schema Registry user"
sensitive = true
}
export TF_VAR_schema_password="schema-registry-password"
Manage Schema Registry ACLs
The redpanda_schema_registry_acl resource configures fine-grained access control for Schema Registry subjects or registry-wide operations. Each ACL specifies which principal can perform which operations on a subject or the registry.
resource "redpanda_schema_registry_acl" "allow_user_read" {
cluster_id = data.redpanda_cluster.byoc.id
principal = "User:${redpanda_user.schema_user.name}"
resource_type = "SUBJECT" # SUBJECT or REGISTRY
resource_name = "user_events-value"
pattern_type = "LITERAL" # LITERAL or PREFIXED
host = "*"
operation = "READ" # READ, WRITE, DELETE, DESCRIBE, etc.
permission = "ALLOW" # ALLOW or DENY
username = redpanda_user.schema_user.name
password_wo = var.schema_password
password_wo_version = 1
}
In this example:
-
cluster_ididentifies the cluster that hosts the Schema Registry. -
principalspecifies the user or service account (for example,User:alice). -
resource_typedetermines whether the ACL applies to a specificSUBJECTor the entireREGISTRY. -
resource_namedefines the subject name (use*for wildcard). -
pattern_typecontrols how the resource name is matched (LITERALorPREFIXED). -
operationdefines the permitted action (READ,WRITE,DELETE, and others). -
permissiondefines whether the operation is allowed or denied. -
hostspecifies the host filter (typically"*"for all hosts). -
usernameidentifies the Schema Registry principal. Setpassword_woto the password value, and incrementpassword_wo_versionto trigger updates. For details, see Manage sensitive attributes with write-only fields.
To manage Schema Registry ACLs, the user must have cluster-level ALTER permissions. This is typically granted through a Kafka ACL with ALTER on the CLUSTER resource.
|
Combine schema and ACLs
You can define both the schema and its ACLs in a single configuration to automate schema registration and access setup.
data "redpanda_cluster" "byoc" {
id = "byoc-cluster-id"
}
resource "redpanda_user" "schema_user" {
name = "schema-user"
password_wo = var.schema_password
password_wo_version = 1
mechanism = "scram-sha-256"
cluster_api_url = data.redpanda_cluster.byoc.cluster_api_url
allow_deletion = true
}
resource "redpanda_schema" "user_events" {
cluster_id = data.redpanda_cluster.byoc.id
subject = "user_events-value"
schema_type = "AVRO"
schema = jsonencode({
type = "record"
name = "UserEvent"
fields = [
{ name = "user_id", type = "string" },
{ name = "event_type", type = "string" },
{ name = "timestamp", type = "long" }
]
})
username = redpanda_user.schema_user.name
password_wo = var.schema_password
password_wo_version = 1
}
resource "redpanda_schema_registry_acl" "user_events_acl" {
cluster_id = data.redpanda_cluster.byoc.id
principal = "User:${redpanda_user.schema_user.name}"
resource_type = "SUBJECT"
resource_name = redpanda_schema.user_events.subject
pattern_type = "LITERAL"
host = "*"
operation = "READ"
permission = "ALLOW"
username = redpanda_user.schema_user.name
password_wo = var.schema_password
password_wo_version = 1
}
This configuration registers an Avro schema for the user_events subject and grants a service account permission to read it from the Schema Registry.
Delete resources
The terraform destroy command deletes all resources defined in your configuration.
| Terraform deletes dependent resources in the correct order. For example, Terraform removes a cluster that depends on a network before it deletes the network. |
Delete all resources
-
Navigate to the directory containing your Terraform configuration.
-
Run the following command:
terraform destroy -
Review the destruction plan Terraform generates. It lists all the resources to be deleted.
-
Confirm by typing
yeswhen prompted. -
Wait for the process to complete. Terraform deletes the resources and displays a summary.