OpenTofu and Terraform: revisit the fork before you pick one
Many teams picked Terraform years ago and have not looked at the choice since. In August 2023 its licence changed and a fork appeared. For a while the two tools were almost the same binary with different names. That is no longer true, and moving between them is easy only if you check a few things first.
This post covers the history, the licence in plain words, where the code has diverged, and how to test a migration safely. The facts come from HashiCorp, OpenTofu, Linux Foundation, CNCF and IBM pages and from both projects’ changelogs, checked on 5 October 2026. Nothing here is legal advice.
The short version
- HashiCorp moved Terraform from MPL 2.0 to the Business Source License (BSL) 1.1 on 10 August 2023. Terraform 1.5.7 is the last MPL release.
- OpenTofu is the community fork of the last MPL code. The Linux Foundation announced it on 20 September 2023, version 1.6.0 was the first stable release on 10 January 2024, and CNCF accepted it as a Sandbox project on 23 April 2025.
- IBM completed its acquisition of HashiCorp on 27 February 2025.
- For a company running Terraform on its own infrastructure, HashiCorp’s FAQ says nothing changes. The restriction is on hosting or embedding Terraform in a paid offering that competes with HashiCorp.
- The code has diverged. OpenTofu has state and plan encryption, provider
for_each,-excludeand.tofufiles. Terraform has HCP Terraform integration, Stacks,terraform queryand actions. - OpenTofu documents the move as reversible, provided you keep backups and avoid OpenTofu-only features during the move.
- Latest stable releases, checked on 5 October 2026: OpenTofu v1.13.1 and Terraform v1.16.5.
How the fork happened
Terraform was open-sourced in 2014 under the Mozilla Public License 2.0. On 10 August 2023, HashiCorp co-founder Armon Dadgar announced that the company was changing its licence “from Mozilla Public License v2.0 (MPL 2.0) to the Business Source License (BSL, also known as BUSL) v1.1 on all future releases of HashiCorp products”. HashiCorp APIs, SDKs and almost all other libraries stayed on MPL 2.0.
HashiCorp’s licensing FAQ names Terraform 1.5.7 as the last MPL release. Terraform 1.6.0, released on 4 October 2023, was the first minor release after the change.
A group of companies then published a manifesto, at first under the name OpenTF, asking HashiCorp to return Terraform to an open source licence and saying they would fork it otherwise. The timeline from the project’s own blog and the Linux Foundation:
- 25 August 2023: with no reversal from HashiCorp, the group announced that it had created a fork.
- 5 September 2023: the repository at github.com/opentofu/opentofu became public.
- 20 September 2023: the Linux Foundation announced the formation of OpenTofu, “previously named OpenTF”, backed by companies including Harness, Gruntwork, Spacelift, env0 and Scalr.
- 10 January 2024: OpenTofu 1.6.0, the first stable release, which the project calls a drop-in replacement for Terraform. That is the project’s claim; the rest of this post shows where it needs care.
- 23 April 2025: CNCF accepted OpenTofu at the Sandbox maturity level, according to CNCF’s project page.
On the HashiCorp side, IBM announced an agreement to acquire HashiCorp on 24 April 2024 and announced completion on 27 February 2025. On 5 October 2026, HashiCorp’s licence FAQ still described BSL terms for Terraform.
What the licence means for a working team
HashiCorp says it treats its FAQ answers as binding guidance. In plain words, the FAQ says:
- Non-production use is always allowed. Production use is allowed too, except “hosting or embedding the Licensed Work to compete with HashiCorp’s paid version of the same Licensed Work”.
- A “competitive offering” is a product sold to third parties, including through paid support, that significantly overlaps HashiCorp’s paid version. Products not sold or supported on a paid basis are always allowed.
- Internal hosting is fine. One division can host Terraform for another division of the same organisation.
- Consultants are fine when they help a customer with the customer’s own use of Terraform.
- Providers are separate. Provider authors choose their own licence, and HashiCorp’s own providers and SDKs stay on MPL 2.0.
- Old releases stay MPL. The change is not retroactive. MPL security backports ended on 31 December 2023.
- Each BSL version converts to MPL 2.0 four years after it was first published under the BSL.
- A modified copy cannot be relicensed under another licence.
So, for a team managing its own cloud accounts, the FAQ says there is no change. The question becomes real if you sell a platform, managed service or paid support that runs Terraform for customers. Then read the licence and FAQ with your legal team. OpenTofu’s repository is under MPL 2.0, the same licence Terraform had before August 2023.
Licence is one input. The platform you run on and the features you need matter just as much.
Where the code has diverged
Both projects started from the same code. Some features now exist in only one, and some arrived in both with different details.
What OpenTofu added
- 1.7.0 (30 April 2024): state and plan encryption at rest, with AES-GCM and key providers for a PBKDF2 passphrase, AWS KMS, GCP KMS and OpenBao. It also added provider-defined functions, the
removedblock andfor_eachinimportblocks. - 1.8.0 (29 July 2024): early evaluation, which allows variables and locals in module sources, backend configuration and encryption configuration, with limits. It also added the
.tofuextension: iffoo.tfandfoo.tofusit in the same directory, OpenTofu loads onlyfoo.tofu. Test mocks arrived in the same release. - 1.9.0 (10 January 2025):
for_eachon provider blocks, useful when infrastructure repeats per region, and-exclude, the opposite of-target. - 1.10.0 (23 June 2025): modules and provider mirrors from OCI registries, S3 state locking without DynamoDB, and deprecated variables and outputs.
- 1.11.0 (9 December 2025): ephemeral values, write-only attributes and an
enabledmeta-argument insidelifecycle. - 1.12.0 (14 May 2026):
prevent_destroythat can refer to variables, import by resource identity, a newlanguageblock for version constraints, and fuller provider hashes in lock files. - 1.13.0 (29 September 2026): symbol libraries and built-in linting, both experimental. The
winrmconnection type was removed.
What Terraform added
- 1.6.0 (4 October 2023):
terraform testbecame generally available. - 1.7.0 (17 January 2024): mocks in tests and the
removedblock. - 1.8.0 (10 April 2024): provider-defined functions, with the same
provider::name::function()syntax. - 1.10.0 (27 November 2024): ephemeral resources and ephemeral values.
- 1.11.0 (27 February 2025): write-only attributes, and S3 native state locking made generally available.
- 1.13.0 (20 August 2025): a
terraform stackscommand. Stacks are a configuration layer in HCP Terraform that deploys a group of components across many environments. - 1.14.0 (19 November 2025): list resources, the
terraform querycommand and a new top-level actions block for provider-defined operations outside normal create, read, update and delete. - 1.15.0 (29 April 2026): variables and locals in module
sourceandversion, which narrows one early gap. - 1.16.0 (26 August 2026):
importblocks inside modules.
The Terraform CLI also integrates with HCP Terraform (earlier Terraform Cloud) and Terraform Enterprise through the cloud block, documented for Terraform 1.1.0 and later. OpenTofu keeps a generic cloud block for “cloud backends”, and its docs say a service may implement only a subset of features. If your runs live in HCP Terraform today, that is the biggest practical tie to Terraform.
Terraform’s changelogs from 1.6 to 1.16 show no state encryption, provider for_each or -exclude.
The lesson in the lists
Same name does not mean same behaviour. OpenTofu’s migration guide from the 1.9 period said its removed block worked differently, the encode_tfvars, decode_tfvars and encode_expr functions were missing, and some test override patterns were not supported. OpenTofu added the tfvars functions in 1.10.0. Check the version you will actually run.
Compatibility and migration
State files
OpenTofu’s guide for interdependent configurations says OpenTofu reads Terraform 1.x state files, and that Terraform “may not reliably read” OpenTofu state, especially when OpenTofu-only features are used. OpenTofu’s FAQ page still says existing state works “up to those created with Terraform versions 1.5.x”. The two pages do not agree, so test with your own state instead of trusting either line.
Encryption is the clearest one-way door: Terraform has no matching feature, so encrypted state is OpenTofu-only. OpenTofu documents an unencrypted fallback method to roll it back. Practise that, and back up your keys.
The official guides
The OpenTofu 1.9 documentation had separate guides for Terraform 1.5 or lower, 1.6, 1.7, 1.8 and 1.9; the 1.9 guide asked you to be on Terraform 1.9.8 and move to OpenTofu 1.9.0 first. From the 1.10 documentation onwards there is one general guide, which does not name a highest supported Terraform version. Its steps: back up state and code, install OpenTofu, run tofu init, run tofu plan and expect no changes, run tofu apply so OpenTofu updates the state file, then try a small change. It also gives rollback steps.
If root modules read each other through terraform_remote_state, OpenTofu’s separate guide says to migrate bottom-up: configurations that read state move first, and those whose state others read move last. Bring all of them to the same Terraform version before you start.
Registry addresses and lock files
A short provider source such as hashicorp/aws means registry.opentofu.org/hashicorp/aws in OpenTofu and registry.terraform.io/hashicorp/aws in Terraform. Both tools record providers in .terraform.lock.hcl under the full address, so expect the lock file to change on the first tofu init. Review that diff and commit it. From 1.12, OpenTofu records hashes for all supported platforms during tofu init. On older versions, run tofu providers lock with each -platform your team uses.
CI changes
- Install and pin the
tofubinary. Rename commands in scripts, and check wrappers, hooks and policy tools that readshow -jsonoutput. - If you built images on
ghcr.io/opentofu/opentofu, note that using it as a base image stopped being supported in 1.10. - For modules used by both tools, OpenTofu’s docs suggest
versions.tffor the Terraform constraint andversions.tofufor the OpenTofu one; OpenTofu then ignoresversions.tf. - Official 32-bit builds end after the 1.13 series.
A decision guide
Ask these in one meeting and write the answers down:
- Do your runs, policies and approvals live in HCP Terraform or Terraform Enterprise, or do you plan to use Stacks? If yes, staying on Terraform is simpler.
- Do you sell, or plan to sell, anything that hosts or embeds infrastructure as code for customers? If yes, get legal advice on the BSL. OpenTofu’s MPL 2.0 has no such competitive-use restriction.
- Do you need state encryption inside the tool, provider
for_eachacross regions or variables in backend configuration? These point to OpenTofu. - Do you need
terraform query, actions orimportblocks inside modules? These point to Terraform. - Is every provider and module you use available on the registry you will use?
- Does your CI or automation vendor support the tool and version you want?
- How many root modules share state, and in what order would they move?
- Who owns upgrades? OpenTofu publishes support windows; its changelog says the v1.13.x series is supported until 1 August 2027.
A middle path is fine. Keep shared modules free of tool-only features, and put tool-specific pieces in .tofu files.
Practice drill: test before you decide
Unlearn two ideas first: “a fork means the tools are identical” and “a licence change means our usage is now illegal”. Then, in a sandbox with read-only cloud credentials:
- Pick a small, non-critical root module. Run
terraform planand confirm there are no changes. - From that working directory, pull a copy of state. Treat the file as a secret.
- Make two clean copies of the code without the
.terraformdirectory, one per tool. Point each at a local state copy with an override file; in both tools a backend block in an override file wins. - Plan with both tools and compare the actions.
mkdir -p /tmp/drill
terraform state pull > /tmp/drill/state.tfstate
cp /tmp/drill/state.tfstate /tmp/drill/state-tofu.tfstate
# in the OpenTofu copy of the code
cat > backend_override.tf <<'EOF'
terraform {
backend "local" {
path = "/tmp/drill/state-tofu.tfstate"
}
}
EOF
tofu init
tofu plan -out=tofu.plan
tofu show -json tofu.plan > tofu-plan.json
jq '[(.resource_changes // [])[]
| select(.change.actions != ["no-op"])
| {address, actions: .change.actions}]' tofu-plan.json
- Repeat in the Terraform copy, using
/tmp/drill/state.tfstateandterraform show -json. Both lists should be empty. Investigate any difference before you go further. - Read the
.terraform.lock.hcldiff and note each changed provider address. - Rollback test. Only if the OpenTofu plan is empty, run
tofu applyagainst the local copy so OpenTofu rewrites it. Then point the Terraform copy atstate-tofu.tfstate, runterraform init -reconfigureandterraform plan. If Terraform reads it with no changes, your rollback path works for this module. - If you plan to use encryption, repeat the drill with it on, then roll it back with the
unencryptedmethod.
Write down what surprised you. That note is worth more than any comparison table, this one included.
Sources
- HashiCorp: HashiCorp adopts Business Source License (10 August 2023)
- HashiCorp: Licensing FAQ
- HashiCorp: Business Source License text
- Terraform CHANGELOG (main, with links to each minor series)
- Terraform v1.16 CHANGELOG
- Terraform releases on GitHub
- Terraform docs: Stacks overview
- Terraform docs: HCP Terraform CLI integration
- Terraform docs: Ephemeral values in resources
- Terraform docs: Override files
- Terraform docs: Dependency lock file
- OpenTofu: Manifesto
- OpenTofu blog: OpenTofu announces fork of Terraform (25 August 2023)
- OpenTofu blog: The OpenTofu fork is now available (5 September 2023)
- OpenTofu blog: OpenTofu is going GA (10 January 2024)
- OpenTofu blog: OpenTofu v1.13.0
- OpenTofu v1.13 CHANGELOG (links to earlier series)
- OpenTofu releases on GitHub
- OpenTofu docs: Migration guide
- OpenTofu docs: Migrating interdependent configurations
- OpenTofu 1.9 docs source: Migrating from Terraform 1.9.x
- OpenTofu docs: State and plan encryption
- OpenTofu docs: Files and directories, the .tofu extension
- OpenTofu docs: Provider requirements
- OpenTofu docs: Dependency lock file
- OpenTofu docs: Settings and the language block
- OpenTofu docs: Cloud backend with the CLI
- OpenTofu docs: Override files
- OpenTofu FAQ
- Linux Foundation: Linux Foundation launches OpenTofu (20 September 2023)
- CNCF: OpenTofu project page
- IBM newsroom: IBM to acquire HashiCorp (24 April 2024)
- IBM newsroom: IBM completes acquisition of HashiCorp (27 February 2025)
Releted Posts
Redis, Valkey, and Dragonfly operations: persistence and failover
A cache becomes a database the day nobody can rebuild it. After that day, persistence and failover are not settings copied from a blog.
Read moreRedis, Valkey, and Dragonfly benchmarks: read the method first
A benchmark number without its method sounds complete, but it does not tell you what happened. The first note in this series, Redis, Valkey, or Dragonfly: revisit the choice before you treat them as the same cache, covered licences, history, data file compatibility, and cluster mode.
Read moreRedis, Valkey, or Dragonfly: revisit the choice before you treat them as the same cache
If your service already uses Redis, the name on the port has not changed. The product behind that name has. Treating Redis, Valkey, and Dragonfly as three labels for one cache is the habit worth unlearning.
Read more