OpenTofu vs Terraform: Migrating After the License Change

Photo by Collins, Tudor Washington, 1898-1970, photographer via Wikimedia Commons (CC BY 4.0)
For the forked baseline (Terraform 1.5.x), yes: the HCL syntax, module structure, provider protocol, and state file format are identical, and the same provider binaries work with both. Most projects migrate with no source changes at all. The two have diverged since 2026, though, so OpenTofu-only features like state encryption are not portable back to Terraform.
No. State files are binary-compatible between Terraform 1.5.x and OpenTofu in both directions. You point OpenTofu at your existing state, whether local or in a remote backend, and it reads it directly. A correct migration ends with a plan showing zero changes.
After backing up your state, install the tofu binary and run tofu init -upgrade in the project directory, then tofu plan. The init pulls providers from the OpenTofu registry and refreshes the lock file, and the plan should report no changes against your existing state. Then update your CI to call tofu instead of terraform.
Yes, in the general case, because state stays binary-compatible in both directions. The one exception is OpenTofu's state encryption: once you encrypt state and plan files, Terraform can no longer read them. Treat enabling encryption as a committed, one-way decision made separately from the initial migration.
In August 2023 HashiCorp moved Terraform from the open-source MPL 2.0 to the Business Source License, which restricts building competing commercial products on the code and is not OSI-approved open source. The community forked the last MPL release into OpenTofu, now governed under the Linux Foundation with an MPL 2.0 license. For teams selling platforms or managed services, that license difference is usually the deciding factor.

Photo by Collins, Tudor Washington, 1898-1970, photographer via Wikimedia Commons (CC BY 4.0)
Key Takeaway
OpenTofu is a drop-in, MPL-licensed fork of Terraform. State files are binary-compatible with Terraform 1.5.x in both directions, providers resolve from the same names, and most migrations are a binary swap plus tofu init -upgrade and a zero-change plan. Enabling OpenTofu state encryption is the one one-way door.
In August 2023 HashiCorp relicensed Terraform from the MPL 2.0 open-source license to the Business Source License. The BSL is not open source: it restricts anyone from offering a competing product built on the code. The community forked the last MPL version, and that fork became OpenTofu, now governed under the Linux Foundation. Three years on, the question every platform team eventually asks is simple: do I stay on Terraform, or move to OpenTofu, and what does moving actually cost me?
I run my own infrastructure as code on a self-hosted VPS fleet, and I went through this evaluation for real. The short version: for most teams the license risk is the only argument that matters, and OpenTofu removes it without asking you to relearn the tool. But there are real caveats around state, the registry, and the point where the two projects have genuinely diverged. Here is what actually happens when you switch.
Terraform's BSL means you cannot build a commercial product that competes with HashiCorp using their code, and the exact boundary of what counts as competing is deliberately vague. For a company just provisioning its own cloud, this rarely bites in practice. But it is a compliance question your legal team will eventually raise, and it is a real blocker if you sell any kind of platform or managed service. OpenTofu is MPL 2.0, an OSI-approved license with no such clause. If license certainty matters to you, that alone settles the decision. Everything below is about how painless the switch is once you have decided.
OpenTofu forked from Terraform 1.5.x, so the HCL syntax, module structure, provider protocol, and command surface are identical. Your existing .tf files, your modules, your variable files, all of it works unchanged. The CLI is named tofu instead of terraform, but the subcommands (init, plan, apply, destroy, state) are the same. In most projects the only edit you make is renaming the binary you invoke in CI. Providers are the big compatibility win: the same provider binaries serve both engines, and shorthand addresses like hashicorp/aws resolve automatically.
Do not delete the terraform binary on day one. Keep both installed during migration so you can run terraform plan and tofu plan side by side and diff the output. A clean zero-change plan from tofu against your existing state is your proof the swap was transparent.
This is the part people worry about most, and the good news is that state format is binary-compatible between Terraform 1.5.x and OpenTofu in both directions. You point OpenTofu at your existing state file, whether it lives in an S3 backend, a GCS bucket, or a local file, and it reads it directly. No state migration command, no conversion step, no re-import. That is why a well-behaved migration ends in a plan showing zero changes: OpenTofu sees exactly the resources Terraform recorded.
The one-way door is state encryption. OpenTofu can encrypt state and plan files at rest with your own keys, a feature Terraform's open CLI does not have. Once you enable it, those files are unreadable to Terraform. If you turn on encryption you are committed to OpenTofu, so decide that deliberately and only after the plain migration is verified.
Here is the actual sequence I use for a single project. It backs up state first, keeps the state backend untouched, and verifies with a plan before anything is applied. On a small project this is genuinely a five-minute job; the afternoon-long variants come from hardcoded binary names in wrapper scripts, lock-file churn, and CI runner images that still ship only terraform.
# 1. Back up remote state before touching anything
terraform state pull > terraform.tfstate.backup
# 2. Confirm both binaries are available
terraform version # e.g. Terraform v1.14.x
tofu version # e.g. OpenTofu v1.12.x
# 3. Re-init with OpenTofu, refreshing provider lock
tofu init -upgrade
# 4. The proof: this MUST say "No changes"
tofu plan
# Expected tail of output:
# No changes. Your infrastructure matches the configuration.
# 5. If a provider is not on the OpenTofu registry, pin it
# explicitly to the Terraform registry in required_providers:
#
# source = "registry.terraform.io/namespace/name"Terraform pulls providers and modules from registry.terraform.io; OpenTofu defaults to registry.opentofu.org. The OpenTofu registry mirrors the major providers you already use (AWS, AzureRM, Google, and thousands more) and resolves the same shorthand source addresses, so most configs need no change. When a provider is not yet published to the OpenTofu registry, you override the source to the fully-qualified Terraform registry address in your required_providers block. OpenTofu 1.10 also added OCI registry support, letting you host providers in a standard container registry, which is handy for air-gapped or tightly-controlled environments.
For the first couple of years the projects tracked each other closely. In 2026 they have genuinely diverged: OpenTofu ships CLI features Terraform's open binary does not have. State and plan encryption arrived in 1.7, early variable evaluation (including in backend configuration) in 1.8, provider iteration with for_each and the -exclude targeting flag in 1.9, and OCI registry support in 1.10. If any of those solve a real problem for you, that is now a reason to move beyond just the license. Conversely, Terraform's paid HCP Terraform platform and its Stacks feature remain HashiCorp's own, so a team deeply invested in that managed tooling has a reason to stay.
| Dimension | OpenTofu | Terraform |
|---|---|---|
| License | MPL 2.0, OSI-approved open source | Business Source License (not open source) |
| Governance | Linux Foundation, multi-vendor | HashiCorp (IBM-owned) |
| State file format | Binary-compatible with Terraform 1.5.x both ways | Same base format (fork origin) |
| State encryption | Built in since 1.7 (one-way once enabled) | Not in the open CLI |
| Default registry | registry.opentofu.org (+ OCI, + TF registry fallback) | registry.terraform.io |
| Migration effort | Binary swap + tofu init -upgrade + zero-change plan | N/A (source) |
For a new project, or any team without a hard dependency on HCP Terraform, I default to OpenTofu. The license certainty is free, the extra CLI features are real, and the migration is close to a no-op. For an established Terraform shop, treat it as a low-risk, high-value move: migrate one non-critical project first, prove the zero-change plan, update CI, then roll the pattern out. Leave state encryption as a deliberate second step, because that is the only decision you cannot easily walk back. The compatibility promise is not marketing here; it genuinely held up when I ran it.