---
title: "Terraform and OpenTofu"
description: "Manage Frazer resources as code with the frazer-ai/frazer provider for Terraform and OpenTofu, with authentication, imports, secrets kept out of state, and plans that show quota, policy and cost."
url: https://frazer.ai/docs/terraform
index: https://frazer.ai/docs/api/llms.txt
tokens: 2824
---

> For agents: this page is indexed at https://frazer.ai/docs/api/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# Terraform and OpenTofu

The Frazer provider, `frazer-ai/frazer`, manages Frazer resources from Terraform and OpenTofu. It is published in both registries and generated from the same API contracts as the [CLI](https://frazer.ai/docs/cli) and the [MCP server](https://frazer.ai/docs/mcp), so every declarative resource has a provider resource. What sets it apart: `terraform plan` asks Frazer to plan each change, so you see quota impact, policy violations and estimated cost before you apply. See [Integrations](https://frazer.ai/integrations) for everything Frazer connects to.

## How it works

-   **Generated.** Each declarative resource of the API is a provider resource, and each one has a data source, plus a plural data source per collection that takes an AIP-160 `filter`. The provider’s schema is the schema of `frazer apply -f` YAML, so you can move between the two.
-   **Names** are `frazer_<service>_<type>`, for example `frazer_kubernetes_cluster`, `frazer_kubernetes_node_pool`, `frazer_network_address` or `frazer_dns_managed_zone`. When the service ID is the plural of its main type, the type is not repeated: `frazer_secret`.
-   **One configuration, both tools.** The provider uses plugin protocol 6 and only the features both tools support, so the same configuration runs with `terraform` and `tofu`. Its acceptance tests run against Frazer every night with both.

Key behaviors:

-   **Long-running changes** are polled until done; set limits with a `timeouts` block.
-   **Etags** guard every update and delete: if someone changed the resource since your last refresh, the apply fails instead of overwriting their change.
-   **Request IDs**: each create carries one UUID, kept in state, so a retried apply never creates a resource twice.
-   **Soft delete and `deletion_protection`** behave as in the API: deleting a resource keeps it restorable until its purge time, and `deletion_protection` refuses the delete.
-   **Custom actions are fields.** An action such as attaching an address is a field of the resource, so a plan can converge on it.
-   **No false drift.** Fields Frazer sets, such as a cluster’s current version, never show as drift.
-   **IAM** comes as resources for single bindings and an authoritative resource for a whole policy; they do not fight over the same policy.

## Install the provider

1.  Add the provider to your configuration:
    
    ```hcl title="versions.tf"
    terraform {
      required_providers {
        frazer = {
          source = "frazer-ai/frazer"
        }
      }
    }
    
    
    provider "frazer" {}
    ```
    
2.  Initialize the working directory. With OpenTofu, run `tofu init` instead:
    
    ```sh
    terraform init
    ```
    

Provider versions follow semantic versioning, and the major version follows the API’s major version. Ephemeral resources need Terraform 1.10 or later, or OpenTofu 1.11 or later.

## Authenticate

The provider takes the first credential it finds, in this order:

1.  **`FRAZER_TOKEN`**: a [personal access token](https://frazer.ai/docs/api#personal-access-tokens) in the environment.
2.  **Your CLI sign-in**: run `frazer login` once, then plan and apply from the same machine.
3.  **Workload identity federation** from GitHub Actions or GitLab: the CI job’s own OIDC token becomes a 15-minute Frazer token, and a condition on its claims (repository, branch) decides which jobs may. Nothing secret is stored in CI. See [Identity and access](https://frazer.ai/docs/iam).

> **Tip:**
> 
> In CI, prefer workload identity federation to a token: there is nothing to rotate and nothing to leak.

## Example: a DNS zone and a record

```hcl title="dns.tf"
resource "frazer_dns_managed_zone" "apps" {
  project  = "acme-production"
  name     = "apps"
  dns_name = "apps.acme.example."
  dnssec { state = "ON" }
}

resource "frazer_dns_record_set" "www" {
  managed_zone = frazer_dns_managed_zone.apps.id
  name         = "www"
  type         = "A"
  ttl_seconds  = 300
  rrdatas      = ["203.0.113.10"]
}
```

```sh
terraform plan
terraform apply
```

`terraform plan` shows the record changes, the zone’s lint findings and the quota impact. The arguments of every resource are on its product’s page; see [DNS and certificates](https://frazer.ai/docs/dns) for zones and records.

## Plans: Terraform’s and Frazer’s

`terraform plan` compares your configuration with state. For every resource it would change, the provider also asks Frazer for a plan of that change (the API’s `validate_only`), so the plan shows:

-   **Quota impact**: a warning when a counter would be at 80 % or more of its limit. A change over a limit fails at plan time with `QUOTA_EXCEEDED`, not halfway through an apply.
-   **Organization policy violations**: what the change would break.
-   **Estimated cost** of the change.

For IAM changes, Frazer’s plan also says whether access grows, shrinks or stays the same (`MORE_PERMISSIVE`, `LESS_PERMISSIVE`, `EQUIVALENT` or `INCOMPARABLE`), so a CI job can fail a pull request that would grant new access.

Frazer holds no direct change by a person or a pipeline unless a rule says so, so the pull request review stays your approval for infrastructure as code. A change that a rule does hold answers `APPROVAL_REQUIRED`; see [Errors](https://frazer.ai/docs/errors).

## Import existing resources

Import a resource by its full resource name, with an `import` block:

```hcl title="import.tf"
import {
  to = frazer_dns_managed_zone.apps
  id = "//dns.frazer.ai/projects/acme-production/managedZones/apps"
}
```

To bring many resources under code at once, `frazer export --format=hcl` writes HCL for existing resources from the same generator as the provider.

## Secrets stay out of state

The provider never needs a secret in your state or plan files:

-   **Write-only attributes.** Secret versions, connection credentials and webhook secrets take their value in `value_wo`. Frazer stores it, Terraform never records it, and you change `value_wo_version` to send a new value.
-   **Ephemeral resources** produce short-lived values that exist only during a run. The products that offer them list them on their pages:

| Ephemeral resource for | Gives you |
| --- | --- |
| Cluster credentials | A short-lived token for a cluster, to configure the `kubernetes` and `helm` providers |
| Access tokens | A short-lived Frazer access token |
| Secret versions | A secret’s value, for another provider that needs it |

## Provider functions

| Function | Does |
| --- | --- |
| `provider::frazer::resource_name()` | Builds a resource name from its parts |
| `provider::frazer::parse_resource_name()` | Splits a resource name into its parts |
| `provider::frazer::location_of()` | Returns the location in a resource name |

## Resources

Every product’s resources and data sources, from that product’s page. Each heading links to the product’s guide with the arguments and examples.

### [Servers and pools](https://frazer.ai/docs/servers)

| Resource | What it manages |
| --- | --- |
| `frazer_servers_server_pool` | A server pool in a host project, with its share settings. |

### [Kubernetes](https://frazer.ai/docs/kubernetes)

| Resource | What it manages |
| --- | --- |
| `frazer_kubernetes_cluster` | A Kubernetes cluster in a project, with its release channel, maintenance policy and upgrade settings. |
| `frazer_kubernetes_node_pool` | A node pool of a cluster, placed on a server pool of the project or one shared with it. |
| `frazer_maintenance_policy` | A project's maintenance window, exclusions, order and notices, attached to clusters and node pools. |
| `frazer_cluster_credentials` | Ephemeral. A short-lived kubeconfig token for the kubernetes and helm providers. |

### [In-memory store](https://frazer.ai/docs/memory)

| Resource | What it manages |
| --- | --- |
| `frazer_keyvalue_instance` | An In-memory store instance in a project. |

### [Secrets](https://frazer.ai/docs/secrets)

| Resource | What it manages |
| --- | --- |
| `frazer_secret` | A secret's metadata, folder, aliases and rotation; never its value. |
| `frazer_secret_version` | A secret version with a write-only value; as an ephemeral resource it reads a value without storing it in state. |

### [VPC and firewall](https://frazer.ai/docs/network)

| Resource | What it manages |
| --- | --- |
| `frazer_network_subnet` | A subnet of a network at one site, with its stack type and external IPv6 range. |
| `frazer_network_address` | A reserved internal or external address. |

### [Load balancers](https://frazer.ai/docs/load-balancers)

| Resource | What it manages |
| --- | --- |
| `frazer_network_load_balancer` | A load balancer with its frontends, address families, backends, health check and security policy. |
| `frazer_network_security_policy` | A Frazer Shield security policy and its rules. |

### [DNS and certificates](https://frazer.ai/docs/dns)

| Resource | What it manages |
| --- | --- |
| `frazer_dns_managed_zone` | A public or private zone, with its DNSSEC settings. |
| `frazer_dns_record_set` | A record set in a zone. |
| `frazer_dns_verified_domain` | A domain your organization has proved it owns. |
| `frazer_dns_server_policy` | Resolver options for networks, such as inbound forwarding. |
| `frazer_dns_response_policy` | A response policy bound to networks. |
| `frazer_dns_response_policy_rule` | A rule of a response policy. |
| `frazer_dns_tsig_key` | A TSIG key for zone transfers; the secret is write-only. |
| `frazer_network_health_check` | A health check used by DNS routing policies and load balancers. |

### [Identity and access](https://frazer.ai/docs/iam)

| Resource | What it manages |
| --- | --- |
| `frazer_iam_service_account` | A service account in a project. |

### [Billing and budgets](https://frazer.ai/docs/billing)

| Resource | What it manages |
| --- | --- |
| `frazer_billing_budget` | A budget with thresholds and an optional cap on a billing account. |
| `frazer_quota_preference` | A requested limit for a quota on a project or an organization. |

### [Integrations](https://frazer.ai/docs/integrations)

| Resource | What it manages |
| --- | --- |
| `frazer_integrations_connection` | A connection to an outside service; credentials are write-only attributes. |
| `frazer_integrations_connection_grant` | Who may use a connection, for which capabilities and resources. |

### [Webhooks and events](https://frazer.ai/docs/webhooks)

| Resource | What it manages |
| --- | --- |
| `frazer_integrations_webhook_endpoint` | A webhook endpoint; its signing secret is a write-only attribute. |

## Related

-   [API](https://frazer.ai/docs/api): the resources, names and plans behind the provider
-   [CLI](https://frazer.ai/docs/cli): `frazer export` and `frazer apply -f`
-   [Identity and access](https://frazer.ai/docs/iam): tokens and workload identity federation
-   [Environments and GitOps](https://frazer.ai/docs/gitops): what runs inside your clusters, from Git
-   [Errors](https://frazer.ai/docs/errors): every reason with its fix

## Pages in Connect

- [Integrations](https://frazer.ai/docs/integrations.md)
- [Webhooks and events](https://frazer.ai/docs/webhooks.md)
- [Terraform and OpenTofu](https://frazer.ai/docs/terraform.md) (this page)
- [API, CLI and MCP](https://frazer.ai/docs/api.md)
