cf-terraforming: Import Existing Cloudflare Resources into Terraform
A command line utility to facilitate terraforming your existing Cloudflare resources.
At a glance
- What is it?
- cf-terraforming is a Go command line utility that queries Cloudflare and generates Terraform configuration or import commands for existing resources. It is aimed at one-time Terraform adoption work, not continuous automation in CI.
- Who is it for?
- cf-terraforming suits teams with existing Cloudflare resources that need reviewed Terraform definitions before exclusive management. It is a poor fit for CI, Terraform versions below 0.12.x, or users who already have complete configuration.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why cf-terraforming exists
Cloudflare accounts often accumulate zones, DNS records, load balancers, Spectrum applications, and other resources before the organization adopts infrastructure as code. Describing that existing estate by hand is repetitive, and incomplete definitions can misrepresent settings that are already active. cf-terraforming addresses that initial transition by retrieving selected objects from the Cloudflare API and converting them into configuration understood by the Terraform Cloudflare provider.
The intended audience is a Cloudflare user who already has resources and wants to begin managing a chosen subset through Terraform. The README describes the workflow as a one-time generation of HCL for resources that will then be managed exclusively through Terraform. That boundary matters. cf-terraforming is a bootstrap tool, not a general-purpose Terraform executor and not a long-term source of Cloudflare state. The generated definitions still need review, and the user must decide how imports should enter Terraform state.
Access is selective. Commands can target a zone with `--zone` or an account with `--account`, while `--resource-type` limits generation to named resource types. Some resource types also need `--resource-id` to identify a particular item. This makes the tool more useful than blindly exporting an entire account when the goal is a controlled adoption of specific resources. However, the README does not provide a single catalog of every supported resource type or explain which resource relationships require manual reconciliation, so generated scope should be checked before execution.
Cloudflare API to HCL generation
The data flow starts with credentials. cf-terraforming supports API Token authentication and API Key authentication with an email address. The API Token is the recommended option because its access is limited to the resources and permissions granted to it. The key-based method can reach everything available to the corresponding user profile, which makes scope control more dependent on careful account administration.
After the command identifies a zone or account and a resource type, the utility contacts the Cloudflare API and transforms the response into Terraform configuration. The README shows a generated `cloudflare_record` block containing properties such as `name`, `proxied`, `ttl`, `type`, `value`, and `zone_id`. The generated resource name in that example is `terraform_managed_resource`. Users should treat generated HCL as a starting representation for review, not as proof that every setting or dependency has been captured.
There are two import paths. By default, generation can produce `terraform import` compatible CLI commands. With `--modern-import-block`, it generates Terraform `import` blocks, but this mode requires Terraform 1.5 or later. The latter keeps the import declaration with generated configuration. The README says `generate` must already have been run before the import workflow is used.
Some Terraform binary management is built around the generation path. `--terraform-install-path` identifies an initialized Terraform working directory, while `--terraform-binary-path` tells cf-terraforming to reuse an existing binary. Without an existing binary path, the flag documentation says one will be downloaded. This provider-aware behavior explains why an initialized directory and installed provider are prerequisites.
Installing cf-terraforming and generating DNS records
The first prerequisite is an initialized Terraform directory. The project documentation requires `terraform init` to have run and the Cloudflare provider to be installed. The account must also contain resources that can be read with the selected credentials. Installation can use Homebrew on supported systems. Older Homebrew installations may need removal because the project documents a changed installation and signing process.
The following commands install the current Homebrew package:
brew tap cloudflare/cloudflare
brew install cloudflare/cloudflare/cf-terraformingFor a Go installation, the repository declares Go 1.25.8 in `go.mod`. The documented installation command installs the command package from the latest module version:
go install github.com/cloudflare/cf-terraforming/cmd/cf-terraforming@latestUsers on other operating systems can download a release from GitHub Releases or build the Go source, according to the README. The repository also provides a `build` target in the `Makefile`, but the README does not give separate build instructions, so the Go installation command is the clearest documented path.
For the first generation, prefer an API Token stored in an environment variable. This example uses placeholder values rather than real credentials. The zone variable is the value that the command targets.
export CLOUDFLARE_API_TOKEN='your-token'
export CLOUDFLARE_ZONE_ID='81b06ss3228f488fh84e5e993c2dc17'The documented generation command requests all `cloudflare_record` resources in the selected zone:
cf-terraforming generate \
--zone $CLOUDFLARE_ZONE_ID \
--resource-type "cloudflare_record"The command should produce valid Terraform configuration representing the requested records. Review the generated `cloudflare_record` blocks before adding an import step. The README also supports an API Token passed through `CLOUDFLARE_API_TOKEN`, while the zone ID is used explicitly through `--zone`.
Resource IDs and Terraform import output
A plain resource type is not enough for every Cloudflare resource. The README identifies `cloudflare_hostname_tls_setting` as an example that needs an ID. Its documented command associates the resource type with `ciphers`:
cf-terraforming generate \
--zone $CLOUDFLARE_ZONE_ID \
--resource-type "cloudflare_hostname_tls_setting" \
--resource-id "cloudflare_hostname_tls_setting=ciphers"This `key=value` mapping explains why broad bulk generation can require more preparation. cf-terraforming can return Terraform configuration where enough API information is available, an import-compatible command, or both, depending on the resource. The project documentation warns that some resources require an ID for either HCL or import output. It does not claim that all Cloudflare resources are supported.
For an existing Terraform installation, reusing its binary can avoid fetching another Terraform binary. The exact documented flag is:
cf-terraforming generate \
--zone $CLOUDFLARE_ZONE_ID \
--resource-type "cloudflare_record" \
--terraform-binary-path /path/to/terraformThe path above is a placeholder because the README does not prescribe a machine-specific location. In practice, the reader must replace it with an existing Terraform binary. This option is relevant when the automatically selected or downloaded binary does not match the local Terraform workflow.
Terraform 1.5 and later users can request native import blocks:
cf-terraforming generate \
--zone $CLOUDFLARE_ZONE_ID \
--resource-type "cloudflare_record" \
--modern-import-blockWithout that flag, the project can generate `terraform import` compatible CLI commands. Either path still requires the user to incorporate the output into the intended Terraform workflow. The README excerpt does not document automatic rollback, complete state verification, or conflict handling, so those points cannot be assumed.
Authentication exposure, CI restrictions, and maintenance
The README contains an explicit warning that cf-terraforming is not intended for CI use. That sharply narrows its operational role. It is meant to produce HCL or import output from live Cloudflare configuration, and the documentation does not define a CI-safe execution model for it. A deployment pipeline that repeatedly runs such generation could also produce definitions against changing remote state, although the project does not state that behavior as an outcome.
Credentials can come from environment variables or `~/.cf-terraforming.yaml`. Supported environment names are `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_EMAIL`, and `CLOUDFLARE_API_KEY`. The YAML config uses `email`, `key`, or `token`, and the command's `--config` flag selects the file path. Because this utility reads broad resource data and can emit identifiers for Terraform imports, the token should grant only the permissions needed for the selected account or zone.
The repository is not archived, and its last push was on 2026-10-04. Recent releases include v0.29.0 on 2026-09-02, v0.28.0 on 2026-07-20, and v0.27.0 on 2026-05-26. These dates indicate recent project changes, but the README still carries a version boundary: Terraform versions below 0.12.x require an older release. The `go.mod` also names Terraform 1.5 as the minimum for modern import blocks.
The source is licensed under MPL-2.0. The repository includes `LICENSE`, `CHANGELOG.md`, and separate v5 Terraform validation scripts. This is relevant when modifying or redistributing covered source files. This review does not interpret the license or provide legal advice.
Handwritten Terraform as the alternative
The direct alternative is to define Cloudflare resources manually with the Terraform Cloudflare provider, then import those resources into state using Terraform's normal import workflow. That approach does not require cf-terraforming to query and translate the entire selected API response. It costs more initial authoring effort, but it gives the engineer direct control over resource boundaries, required arguments, naming, dependencies, and sensitive values.
cf-terraforming is different because it begins with an existing Cloudflare configuration. It uses API credentials to retrieve that configuration and emits Terraform-facing HCL. This is particularly useful when the goal is to bootstrap Terraform from resources that already exist. Handwritten Terraform reverses the workflow: the engineer first decides the desired abstraction and then translates existing objects to match it.
The practical trade-off is speed versus control. Generated HCL can reduce repetitive discovery work, but it still has to be checked against the current provider schema and the intended state boundaries. A handwritten setup is less attractive for a large migration with many comparable objects, yet it may be easier to reason about for a small number of sensitive resources. cf-terraforming also cannot replace Terraform itself. It does not run a deployment or replace provider validation, and the README requires an initialized Terraform directory before generation.
Editorial conclusion
cf-terraforming suits teams with existing Cloudflare resources that need reviewed Terraform definitions before exclusive management. It is a poor fit for CI, Terraform versions below 0.12.x, or users who already have complete configuration. Verify credential permissions, the targeted resource types, generated HCL against current provider schemas, and state changes through a plan before applying. The project was last pushed on 2026-10-04, and the source is covered by MPL-2.0.
Frequently asked questions
How do I install cf-terraforming?
Homebrew users can run `brew tap cloudflare/cloudflare` followed by `brew install cloudflare/cloudflare/cf-terraforming`. Go users can install it with `go install github.com/cloudflare/cf-terraforming/cmd/cf-terraforming@latest`, while other operating systems can use GitHub Releases or build the Go source.
Which Cloudflare authentication method should cf-terraforming use?
The README recommends an API Token because it is limited to the resources and permissions assigned to that token. cf-terraforming also supports an API Key with an email address, and that method can access everything available to the corresponding user profile.
Can cf-terraforming generate Terraform import blocks?
Yes. The `--modern-import-block` flag generates Terraform import blocks, but this option requires Terraform 1.5 or later. Without that flag, the tool can produce `terraform import` compatible CLI commands.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cloudflare-cf-terraforming)