OpenTofu 1.6 GA: the migration that takes less than a day
OpenTofu 1.6 went GA on January 10. For most teams the migration is renaming a binary and updating a CI step. The interesting parts are what 1.6 actually shipped, how the BSL clause reads five months on, and why I moved quickly on it for the engagements I'm currently on.
On January 10, OpenTofu 1.6 went GA. Five months after the Linux Foundation announced the project, three months after the first alpha, the OpenTofu team shipped a 1.x release that the project’s roadmap explicitly positioned as a drop-in replacement for Terraform 1.5 with a small set of forward-only features layered on top.
I have been waiting for this release specifically. Two of the engagements I’m on right now have been carrying a BSL-audit question since last August, the customer’s legal team wanted a written answer to “what happens if HashiCorp decides we’re a competitive offering?”, and the answer those teams wanted was “we have a credible alternative we can move to.” Before January 10, that alternative was a release candidate. After January 10, it is a 1.0-grade thing with semantic versioning and a release cadence and a foundation behind it. The conversation changes.
I want to write down what the migration actually looks like, what 1.6 shipped that is worth knowing about, and the BSL clause re-read I did before I told customers it was safe to move.
What 1.6 actually shipped
The OpenTofu team made a deliberate choice to ship a minimal 1.6, the goal of the release was credibility, not feature differentiation. The headline items:
Full Terraform 1.x compatibility. Configurations written against Terraform 1.5 work without modification. State files written by Terraform 1.5 are read and written by OpenTofu 1.6 without conversion. Provider compatibility (the part that worried people most in September) is preserved through a fork of the provider protocol that holds the same interface.
The removed block. This is the one new bit of language surface in 1.6, and it’s a quiet improvement that’s been wanted for a long time. It lets you remove a resource from state declaratively, inside the configuration, without having to run terraform state rm out-of-band. It looks like this:
removed {
from = aws_instance.legacy
lifecycle {
destroy = false
}
}
You add this block, run an apply, the resource is dropped from state but not destroyed in the cloud. Then you delete the block on the next change. The reason this is nice is that it makes the operation reviewable, it goes through the same plan-output-into-the-PR flow as every other change, instead of being a side-channel command somebody ran on their laptop.
State encryption. OpenTofu 1.6 supports encrypting the state file with a per-state passphrase or KMS key, at the OpenTofu level, on top of whatever the backend is already doing. This is mostly belt-and-suspenders for teams whose threat model includes “someone gets read access to the state bucket.” Not every team needs it. The teams that do want it have wanted it for years.
Provider registry. OpenTofu has its own provider registry, populated by the same underlying provider source code that HashiCorp’s registry uses. The registries are kept in sync. The wrinkle is that some providers (specifically the ones owned by HashiCorp itself) are technically only published to the HashiCorp registry, but OpenTofu pulls the source from GitHub and republishes. So far, the cadence is keeping up.
That’s the headline list. There are smaller things (better init performance, some plan diff cleanup, a few bug fixes) but the spirit of the release is “we are exactly Terraform 1.5, plus a couple of well-scoped additions.” That’s the right call. A first major release should not be where you take risks.
The migration mechanics
Here is the migration, in full, for most workloads:
- Install the
tofubinary on developer machines and CI runners. - In your CI config, replace
terraform <subcommand>withtofu <subcommand>wherever it appears. - In your repo, if you have a
.terraform-versionfile, replace it with a.opentofu-versionfile (or use whatever your version manager supports). - Run
tofu init. Watch it pick up the existing.terraform.lock.hcl, the existing state, the existing providers. - Run
tofu plan. It should match the previousterraform planoutput exactly. If it doesn’t, that’s the bug, and it’s overwhelmingly likely to be a config-discovery quirk, not a real diff. - Apply. Move on.
That’s it. For most teams that’s a one-engineer-one-afternoon job. The migration is faster than the meeting where you decide to do the migration.
The places where it does take longer:
- You’re using HashiCorp Cloud or Terraform Cloud as your backend or runner. Then you have to migrate the backend too, which means picking a different remote-state strategy (S3 + DynamoDB, Azure Storage, GCS, or a TACOS-style alternative). That’s a separate project. The actual binary migration is still trivial; the runner migration is the work.
- You’re using a HashiCorp-published provider that lives only on the HashiCorp registry. As of January, this is a short list, and OpenTofu’s registry is republishing all of them. Worth checking your specific provider set against OpenTofu’s registry on the day you migrate.
- You have a custom-built tool that wraps
terraformand parses its output by binary name. Search for the stringterraformacross your tooling. Update it. This is the only place I’ve seen migrations take more than a few hours.
Everything else is a search-and-replace.
I did this migration on the parallel multi-cloud demo I wrote about earlier this month. The diff was eight lines: three .terraform-version files renamed, three CI YAMLs with terraform replaced by tofu, two README mentions. The state files migrated automatically. Provider downloads worked on the first try. The plan output on each cloud matched the previous Terraform run. Total time, including the coffee I was drinking, was under thirty minutes.
Re-reading the BSL clause five months on
The reason any of this matters is the BSL change last August. The reason teams are migrating now, instead of waiting for OpenTofu to develop its own feature surface, is that 1.6 is the first version that lets them give a clean answer to legal when legal asks “what’s our exit strategy if HashiCorp decides we’re a competitor?”
Five months in, the read on the BSL clause has clarified, and the read is roughly what I wrote in August: most teams are not affected by the literal license terms. The “competitive offering” clause is narrower than the panic implied. If you’re using Terraform to manage your own infrastructure, you are not building a competitive offering, even if you’ve wrapped Terraform in a self-service portal. HashiCorp has been consistent about that read in their FAQ updates since.
The teams that are still meaningfully affected:
- Consultancies and MSPs that ship Terraform-based tooling as part of their deliverable. Not the consultants who run Terraform on your behalf, the firms that have built proprietary IaC platforms on top of Terraform and licensed those platforms to clients. The clause covers them in a way that is genuinely uncomfortable.
- The adjacent tooling space. Spacelift, env0, Terragrunt, Atlantis, each of these has had to take a position on whether they’re “competitive.” Most have. The dust has settled in a way that lets each project keep shipping, but they had to spend time on it.
- Forks and aggressive customizations of Terraform itself. If you maintained internal patches that changed the core binary’s behavior, you now have to think about whether your patched fork is a competitor. Most teams aren’t doing this. The ones who were have moved to OpenTofu already.
For everybody else, the answer to “do we have to migrate?” is still no. The question I keep hearing is the next-order one: “do we want to?”
Why I moved quickly
On the two engagements I mentioned, I moved customers to OpenTofu in January for three reasons that aren’t license-driven:
One. The roadmap signals. OpenTofu’s published roadmap for 2024 includes things, built-in state encryption, the removed block, declarative state imports, that the Terraform team has either deprioritized or explicitly declined to ship. The features I expect customers to want next are more likely to land in OpenTofu first. The 1.6 release validated that the project can ship.
Two. The provider tooling is staying neutral. The big providers (AWS, Azure, Google, Kubernetes) are upstreaming changes that work with both binaries. Until that changes (and there’s no signal yet that it will), the provider compatibility story holds. If it ever does change, the cost of moving back to Terraform is the same eight-line diff.
Three. The audit conversation. The customers who needed a written answer for legal have a written answer now. The answer is “OpenTofu 1.6 is GA, our config is portable, our migration is reversible, here is the eight-line diff.” That’s a defensible position. The earlier defensible positions all had asterisks attached.
The decision was easier than I expected once 1.6 actually shipped. The release matters less for what it ships than for what it signals: there is a credible, foundation-backed, semver-bound alternative to HashiCorp’s Terraform, and the cost of moving to it is measured in hours.
What to do, concretely
If you’ve been carrying this question since August, the moves I’d make this week:
Run the migration on one repo. Not production. Pick a low-stakes repo, do the eight-line diff, see the plan match. The exercise is shorter than the meeting you’d schedule about it.
Read the OpenTofu registry against your provider list. Almost everything is there. The exceptions are usually HashiCorp-published utility providers and they almost always have direct OpenTofu equivalents.
Decide whether your backend story changes. If you’re on Terraform Cloud, this is the bigger conversation, and worth having on its own merits, not as a side effect of the binary swap.
Update your CI templates and document the choice. New repos in your org should start with the binary you’ve decided on. The half-and-half state (some repos on each) is a tax on new engineers learning your tooling.
Don’t migrate just because. If your legal team is happy with the BSL read, if your provider story works on Terraform, if you have no specific feature you want from OpenTofu, staying is also fine. The point of 1.6 is that you have the choice. Choice is the win. Migration is one of the answers.
The longer thread
The BSL story is now closing out. Five months after the change, the panic has resolved into a steady-state where both binaries exist, both can manage the same configurations, and most teams can run either one. That is a healthier tooling than the one we had in July 2023, when a single vendor’s licensing decision could rewrite the contracts of every IaC team in the industry.
Finally, the lesson I keep wanting to underline: open source’s failure modes are slow, and so are its recoveries. It took five months between the BSL change and a credible GA fork. That’s faster than I’d have predicted in August, and slower than the people who needed an answer wanted. Both things can be true.
, Sid