OpenTofu
The open-source Terraform fork - why it exists, how it stays compatible, its divergent features (client-side state encryption, early variable evaluation), and how to migrate
OpenTofu
OpenTofu is an open-source fork of Terraform, stewarded by the Linux Foundation. For most code it is a drop-in replacement; the tofu CLI reads the same HCL, uses the same providers, and operates on the same state files.
Why It Exists
In August 2023, HashiCorp relicensed Terraform from the MPL 2.0 (a permissive open-source license) to the BUSL (Business Source License), which restricts commercial use that competes with HashiCorp. The community forked the last MPL-licensed version; that fork became OpenTofu, reaching GA as 1.6 in January 2024 under the MPL 2.0.
The practical upshot: if you want a genuinely open-source IaC tool with the Terraform workflow and ecosystem — no license risk, community-governed — OpenTofu is it.
Compatibility
| Aspect | Status |
|---|---|
| HCL syntax | Identical |
| Providers | Same provider binaries, via registry.opentofu.org (a mirror) |
| Modules | Same; public registry mirrored, plus the Terraform Registry usable |
| State files | Reads and writes the same .tfstate format (for matching versions) |
| CLI | tofu instead of terraform; same commands and flags |
| File extensions | .tf works; .tofu files are also recognized for fork-specific overrides |
OpenTofu 1.6 lines up with Terraform 1.6. After that the two diverge — each adds features the other doesn't — so a state written by a newer OpenTofu may not be readable by Terraform, and vice versa.
Features OpenTofu Has That Terraform Doesn't
The fork is not just "Terraform with a different license" anymore. The notable additions:
Client-Side State Encryption
OpenTofu can encrypt state and plan files end-to-end, before they ever reach the backend — closing the long-standing "secrets sit in plaintext in tfstate" gap at the tool level (not just at the backend's at-rest encryption).
terraform {
encryption {
key_provider "pbkdf2" "passphrase" {
passphrase = var.state_passphrase # or pull from a real KMS
}
method "aes_gcm" "default" {
keys = key_provider.pbkdf2.passphrase
}
state {
method = method.aes_gcm.default
}
plan {
method = method.aes_gcm.default
}
}
}Key providers include PBKDF2 (passphrase) and cloud KMS (AWS/GCP/Azure) for production key management.
Early / Static Variable Evaluation
OpenTofu lets you use variables and locals in places Terraform forbids them — most usefully in module source and version, and in backend configuration:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = var.vpc_module_version # not allowed in Terraform
}This removes a class of copy-paste that Terraform forces, where the module version has to be hard-coded per call.
Other Divergences
-excludeflag — the inverse of-target: apply everything except the named resources.- Provider iteration with
for_eachfor some configurations, and continued investment in built-in testing/mocking.
These are moving targets — both tools ship every few months. Treat the list as "the kinds of things that differ," and check the current OpenTofu changelog for what's landed in the version you run.
Migrating From Terraform
For a project still on Terraform 1.6-compatible features, migration is usually painless:
# Install the tofu CLI (brew, apt, or the install script), then:
cd my-terraform-project
tofu init # reads your existing backend + state
tofu plan # should show no changesNotes and caveats:
- Version alignment. Migrate from a Terraform version at or below your target OpenTofu's compatibility line (1.6). Coming from a much newer Terraform that used post-fork features, expect to adjust.
- One-way, in practice. Once OpenTofu writes a newer state format or you adopt fork-only features (state encryption, early eval), you can't cleanly go back to Terraform.
- The
cloud {}block targets HCP Terraform, a HashiCorp service — it isn't the OpenTofu path. Use a standard remote backend (S3/GCS/azurerm) or a platform like Spacelift/Scalr that supports OpenTofu (see HCP Terraform & Automation Platforms). - Provider addresses. Providers resolve through OpenTofu's registry; in rare cases of legacy addresses you may need
state replace-provider(see Refactoring & State Evolution). - CI. Swap
hashicorp/setup-terraformforopentofu/setup-opentofu, andterraforminvocations fortofu.
Terraform or OpenTofu?
| Choose Terraform when | Choose OpenTofu when |
|---|---|
| You want HCP Terraform / Terraform Enterprise as your platform | You want a fully open-source (MPL 2.0) tool |
| You rely on the latest HashiCorp-only features | You want client-side state encryption built in |
| Your org has standardized on it already | License terms (BUSL) are a concern for your use case |
| You want first-party Sentinel policy | You're happy with OPA and community governance |
Either way, everything else in this section — modules, state, refactoring, testing, expert patterns — applies unchanged. The two tools share the same mental model.
What's Next
You've now seen Terraform end to end: the language, state, modules, the advanced and expert features, refactoring, testing, platforms, and the open-source fork. Tie it together with the production playbook → Best Practices.