cf2tf: converting CloudFormation templates into Terraform HCL
Convert Cloudformation templates to Terraform.
At a glance
- What is it?
- cf2tf is a Python CLI that reads a CloudFormation template and emits Terraform resources, either to stdout or split into one file per resource type. The project is explicit that the conversion is an attempt rather than a guarantee, because CloudFormation Maps have no exact HCL equivalent.
- Who is it for?
- Adopt cf2tf when you have a CloudFormation template that needs to become Terraform and you want the bulk of the resource mapping done for you, with the expectation that Maps and intrinsic functions need hand editing. Do not adopt it as a one-click migration for a stack you intend to apply unchanged.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A converter that admits it is only an attempt
The About The Project section is unusually honest for a conversion tool, and the reason it gives is specific. cf2tf is a CLI tool that attempts to convert Cloudformation to Terraform, and the word attempt is explained: it is not really possible to make the conversion with 100% accuracy currently, because of several reasons mostly around converting a Map value in Cloudformation to the correct value in HCL.
That last part is the technical heart of the problem, and it is worth understanding before you reach for the tool. A CloudFormation Map is a nested structure of arbitrary key and value pairs with no schema. Terraform's HCL has types: a map of strings is not the same thing as an object with a fixed set of attributes, and a list is not a tuple. When the converter meets a CloudFormation Map it has to guess which Terraform shape the target resource expects, and there is often no way to know from the template alone.
So the project sets expectations correctly, which is rare and useful. You are getting a starting point, and the amount of hand editing depends on how much of your template uses Maps.
The project is a Python package named cf2tf with a click-based command line entry point, licensed GPL-3.0-only, and the default branch is master. The recent releases are v0.9.2 on 2026-03-08, v0.9.1 on 2025-02-13 and v0.9.0 on 2024-11-18.
Installing from pip or Homebrew, and the Python version
The installation section is short because the distribution is a normal Python package.
pip install cf2tfAnd for Homebrew users there is a formula.
$ brew install cf2tfThe prerequisites line says Cloudformation 2 Terraform requires python >= 3.8. There is a small inconsistency worth flagging, because the packaging metadata is more specific: requires-python is >=3.10, and the project classifiers and the contributing instructions point at Python 3.12 for development. The older figure in the prose is the one a reader will hit first, so check the metadata rather than assuming 3.8 is enough.
The dependency list explains a good deal about the design. cfn-flip at 1.3.0 or newer does the YAML to Python dict conversion, so cf2tf does not parse CloudFormation itself. PyYAML is the underlying parser. click provides the command line interface, and click-log does the logging. GitPython is there, which tells you the tool works with a local Git repository rather than only a single file. requests and thefuzz with the speedup extra are there for a fuzzy lookup, most likely matching CloudFormation resource types to Terraform resource types by name.
The build system is poetry-core 2.0 or newer, and the package exposes a single console script named cf2tf.
Three output shapes, from stdout to a split directory
The usage section documents three ways to run the converter, and the choice is really about how much you want to review afterwards.
The simplest invocation converts a template and dumps all the terraform resources to stdout.
cf2tf my_template.yamlIf you want to keep the result, you redirect it into a file.
cf2tf my_template.yaml > main.tfAnd if you prefer each resource in its own file, you pass an output directory.
cf2tf my_template.yaml -o some_dirIf some_dir does not exist, it will be created for you, and then each resource type will be saved to a specific file, with variables.tf and outputs.tf named as examples.
That third mode is the one that matters in practice, and it is worth understanding why. A single main.tf holding a large stack is a file nobody can review, and reviewing the output is the whole point of a conversion tool, because the converter's guesses are exactly what a human needs to check. Splitting by resource type gives you one file per service or per resource family, so you can see at a glance which parts of the stack converted cleanly and which need attention.
The pipeline behind the CLI is the same in both cases. The template is read, the CloudFormation resources are mapped to Terraform resources, and the HCL is emitted. The README does not document intermediate output or a dry-run mode, so the review happens on the generated files rather than during the conversion.
The roadmap names the failure modes you will hit
The roadmap section is short and it is the most useful part of the documentation for anyone about to run the tool, because it is a list of the conversions that are not done yet.
The first item is better conversion of Cloudformation Maps to Terraform, covering Maps, Block and json. That is the same problem the About section names, and having it at the top of the roadmap tells you it is the dominant source of imperfect output rather than an edge case.
The second is to allow overrides for specific resources. This is a direct answer to the accuracy problem: instead of the tool guessing correctly for every resource, you tell it what to do for the ones it gets wrong. Until that lands, a workaround is to convert, then edit the offending resource by hand, since the output is plain HCL in files you control.
The third is handling more advanced Cloudformation parameter types like SSM and Secrets Manager. Parameters that resolve to a value fetched at deploy time are a genuinely different shape from a literal, and a converter that only understands literals will produce something that reads correctly and deploys incorrectly.
The fourth is better handling of Resources and Properties that failed conversion. Read that next to the About section: failed conversions are a known outcome, and the tool's own roadmap says the reporting of them needs work. That is the honest expectation to set before you start, and it is also a good reason to read the generated output rather than trusting it.
The last roadmap item is the one with a number attached: only download files needed, not entire terraform source code, currently 200MB. That tells you the tool currently fetches a large body of Terraform source, which is slow and wasteful, and that the maintainer is aware of it.
The development setup, and what it says about the project
The contributing section documents a conventional Python project workflow, and one detail stands out.
The project uses poetry to manage dependencies and pre-commit to run formatting, linting and tests, and you will need to have both installed to your system as well as python 3.12. If you are not using devcontainers then you will need to have python installed, and to install the poetry, nox, nox_poetry and pre-commit packages, then run poetry install and pre-commit install.
The devcontainer route is the better one, because the project uses a vscode devcontainer to provide a completely configured development environment, and the most of the steps can be found in the Dockerfile under .devcontainer/Dockerfile.
The repository tree backs this up. There is a .devcontainer/ directory, a .flake8 configuration, a .pre-commit-config.yaml, a .python-versions file, a .scripts/ directory, a .vscode/ directory, a mypy.ini and a noxfile.py, plus src/ and tests/ directories. The presence of both a noxfile and a poetry setup suggests the test matrix is run through nox with poetry as the environment manager, and mypy.ini means there is a separate type checking configuration rather than type hints only being checked incidentally.
There is a renovate.json at the root, which means the dependency updates are automated, and the dev dependency group lists black, flake8, flake8-black, coverage with toml, pytest, pytest-cov and mypy. The formatting tooling is black, the isort profile is set to black, and the coverage configuration measures the cf2tf package with branch coverage enabled and show_missing on.
One thing the repository does not do is document a rollback or a compatibility policy, so an upgrade of the tool is something you assess by running it against your own template and diffing the output.
Where cf2tf is the wrong tool
Three situations make this the wrong choice.
The first is a template whose resources lean heavily on CloudFormation Maps and on parameter types resolved at deploy time. If your stack pulls values from SSM or Secrets Manager, the converter will not represent that faithfully, and the roadmap confirms the gap is still open. The output will need a rewrite by hand, and at that point the value of the tool is thin.
The second is anything where you need the conversion to be complete and correct without review. There is no mode that guarantees that, and the project's own framing says 100% accuracy is not currently possible. If your plan is to run the generated HCL through terraform apply and watch a stack come up, that plan is built on a false premise.
The third is that the tool is a converter, not a migration. It does not move state, it does not know your existing resources, and it does not handle the ordering of creation and destruction, the parts of a real migration that are the hard part. It gives you a starting HCL file.
The realistic alternative is a different kind of project. There are tools that read a deployed cloud account and generate Terraform from what is actually there, which is a different approach with a different failure profile: they describe reality rather than interpreting a template. The other alternative is doing the conversion by hand for a small stack, which for a handful of resources is often faster and produces something you fully understand. cf2tf earns its place on a large template with mostly simple resources, where the mechanical mapping saves the most time and the remaining awkward resources are few enough to edit by hand.
Editorial conclusion
Adopt cf2tf when you have a CloudFormation template that needs to become Terraform and you want the bulk of the resource mapping done for you, with the expectation that Maps and intrinsic functions need hand editing. Do not adopt it as a one-click migration for a stack you intend to apply unchanged. Before you run it, check the version of the template features you rely on, since the roadmap still lists better handling of Resources and Properties that failed conversion, and note the last push was on 2026-10-22 with release v0.9.2 on 2026-03-08.
Frequently asked questions
How do I install cf2tf?
It is a pip package, so pip install cf2tf, and Homebrew users can run brew install cf2tf. The packaging metadata requires Python 3.10 or newer even though the prose in the README says python >= 3.8, and the contributing instructions ask for Python 3.12.
How do I convert a CloudFormation template to Terraform with cf2tf?
Run cf2tf my_template.yaml to write the resources to stdout, redirect it to a file with cf2tf my_template.yaml > main.tf, or pass a directory with cf2tf my_template.yaml -o some_dir to get one file per resource type, with variables.tf and outputs.tf among them.
Will cf2tf produce an accurate Terraform conversion?
Not always. The project describes itself as attempting the conversion and explains that 100% accuracy is not currently possible, mostly because of converting a Map value in Cloudformation to the correct value in HCL. The roadmap still lists better Map conversion and better handling of resources that failed conversion.
Which CloudFormation features does cf2tf not handle yet?
The roadmap lists better conversion of Cloudformation Maps, Block and json, overrides for specific resources, handling of more advanced parameter types like SSM and Secrets manager, and better handling of Resources and Properties that failed conversion.
What does cf2tf use to parse the template and what does it use for mapping?
The dependency list shows cfn-flip at 1.3.0 or newer for converting the template from yml to a Python dict, with PyYAML as the underlying parser, and thefuzz with the speedup extra for fuzzy matching, which is how resource types are matched to their Terraform counterparts. GitPython is also a dependency.
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/dontshavetheyak-cf2tf)Was this useful?