Terraform to OpenTofu Migration in 2026 — The Post-BSL Decision Framework for Azure Teams
By Law Wen Feng | June 2026
Two years ago, I wrote about HashiCorp's switch from the Mozilla Public License (MPL) to the Business Source License (BSL) and the community's response — the creation of OpenTofu under the Linux Foundation. At the time, many of us in the Azure ecosystem took a wait-and-see approach. OpenTofu was promising, but it hadn't yet reached feature parity. In 2026, that has changed. If you're leading an Azure-first team in Southeast Asia and still running Terraform, it's time to make a deliberate decision — not just react to blog posts.
This article lays out the decision framework I use with clients: a practical, no-hype assessment of what OpenTofu offers today, when Terraform (and IBM's stewardship) still makes sense, and when Azure-native tooling like Bicep deserves a second look.
The State of Play in 2026
What Happened with BSL
In August 2023, HashiCorp relicensed Terraform and its entire toolchain from MPL 2.0 to the Business Source License v1.1. The BSL is not open source by the Open Source Definition — it permits use but restricts competitive commercial use. If you're building a product that competes with HashiCorp Cloud Platform (HCP), you can't use the BSL-licensed code.
In 2025, IBM completed its acquisition of HashiCorp. The acquisition didn't change the BSL terms, but it raised legitimate questions about long-term stewardship. For most end-users running terraform apply in their CI/CD pipelines, the BSL doesn't directly restrict usage. But for teams building internal platforms, CI tooling, or drift-detection systems that wrap Terraform, the license creates real legal and architectural constraints.
My take: if you're an enterprise team simply applying infrastructure, the BSL itself may not be your primary concern. But the governance model matters. IBM's priorities shift. The Linux Foundation's governance of OpenTofu doesn't.
OpenTofu's Feature Parity Milestone
As of OpenTofu 1.10 (released early 2026), the project has reached genuine feature parity with Terraform for the vast majority of Azure workloads. Here's what matters:
State Encryption. Since OpenTofu 1.7, state files can be natively encrypted at rest using AES-256-GCM. This was a community priority from day one. In 1.10, external key provider support is fully mature — you can integrate with Azure Key Vault, HashiCorp Vault, or any secrets manager through a simple command-line provider. This is something Terraform still doesn't offer natively.
Removed Blocks. The removed block lets you clean up state without destroying infrastructure. This is incredibly useful for decommissioning resources that were managed by OpenTofu but are being retired or moved to another system.
removed {
from = azurerm_network_security_rule.legacy
lifecycle {
destroy = false
}
}Dynamic Provider Configurations. OpenTofu 1.8 introduced early evaluation of variables, letting you use var and local references in backend blocks and module sources. Before this, you couldn't parameterize your state backend. Now you can.
terraform {
backend "azurerm" {
resource_group_name = var.state_resource_group
storage_account_name = var.state_storage_account
container_name = var.state_container
key = "${var.environment}/main.tfstate"
}
}OCI Registry Support. OpenTofu 1.10 can pull providers and modules from OCI-compliant container registries. For air-gapped Azure environments (common in government and banking sectors across Malaysia and Singapore), this eliminates the dependency on public registries.
Native S3 State Locking. No more DynamoDB dependency for S3 backends. OpenTofu uses S3's conditional writes natively. For Azure teams, this matters less (we use Azure Blob), but it signals the project's engineering maturity.
The bottom line: OpenTofu is no longer a "promising fork." It's a production-ready tool with features Terraform doesn't have.
The 3-Command Migration
I know this sounds too simple. It's not. The real work is in the preparation. But the actual tool migration from Terraform to OpenTofu is genuinely three commands:
# 1. Back up your state (do this regardless)
az storage blob download \
--account-name mystataccount \
--container-name tfstate \
--name main.tfstate \
--file ./backups/main.tfstate.bak
# 2. Install OpenTofu and initialize
tofu init upgrade
# 3. Validate with a plan — should be identical to your last terraform plan
tofu plan -out=tfplanThat's it. OpenTofu reads the same HCL configuration files, the same state format, and the same provider binaries. If tofu plan shows a clean plan identical to what terraform plan showed, you've migrated.
The preparation work is where the real effort lives:
- Audit your provider versions. OpenTofu supports the same Terraform Registry providers. Pin your versions explicitly and confirm they're available.
- Review any Terraform-specific features you use. If you're using Terraform Cloud state locking, HCP Terraform workspaces, or Sentinel policies, those require separate planning.
- Update your CI/CD pipelines. Swap
terraformcommands fortofu(or alias it — OpenTofu respectsTF_CLI_ARGSenv vars). - Test with a non-critical environment first. I recommend starting with a dev or staging subscription.
Decision Matrix: OpenTofu vs Terraform Cloud vs Bicep
This is the question I get asked most often. There's no universal answer, but here's how I frame it:
Choose OpenTofu if:
- You want permissive, OSI-approved licensing (MPL 2.0) with no commercial restrictions.
- Your team builds internal platforms or wraps IaC in custom tooling — BSL would be a legal concern.
- State encryption is a compliance requirement (it's native in OpenTofu, not in Terraform).
- You prefer Linux Foundation governance over IBM stewardship.
- You need fast release cadence — OpenTofu ships monthly, Terraform quarterly.
- You're in an air-gapped or highly regulated Azure environment where OCI registry support matters.
Choose Terraform Cloud (HCP Terraform) if:
- Your team already pays for HCP Terraform and deeply uses its managed state, policy-as-code (Sentinel), and run trigger features.
- You need vendor-backed SLAs for compliance audits in regulated industries.
- Your workloads rely on Terraform-specific features like Stacks or native Sentinel integration.
- Migration cost outweighs licensing concern — if BSL doesn't affect your use case, stay.
Choose Bicep if:
- You are 100% Azure-native with no multi-cloud requirements.
- You want first-class ARM template integration and Azure CLI tooling.
- Your team already has strong Bicep/Azure CLI skills and no HCL investment.
- You prefer Microsoft's governance over community or third-party governance.
- You're building greenfield projects without existing Terraform state.
For most of my clients — Azure-first teams in Southeast Asia with existing Terraform investments — the answer is OpenTofu. Bicep is excellent for greenfield Azure-only work, but switching IaC languages mid-flight is a much bigger lift than swapping the CLI binary.
GitHub Actions CI/CD with OpenTofu
If you're running Azure deployments through GitHub Actions, here's a practical CI/CD pattern using OpenTofu. This is a simplified version of what I deploy for clients:
name: OpenTofu Azure Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
TF_VERSION: "1.10.3"
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: ${{ env.TF_VERSION }}
tofu_wrapper: false
- name: OpenTofu Init
run: tofu init -backend-config="backend.tfvars"
- name: OpenTofu Format Check
run: tofu fmt -check -recursive
- name: OpenTofu Validate
run: tofu validate
- name: OpenTofu Plan
id: plan
run: tofu plan -no-color -out=tfplan
continue-on-error: true
- name: Upload Plan Artifact
uses: actions/upload-artifact@v4
with:
name: tfplan
path: tfplan
apply:
needs: plan
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: ${{ env.TF_VERSION }}
tofu_wrapper: false
- name: Download Plan
uses: actions/download-artifact@v4
with:
name: tfplan
- name: OpenTofu Apply
run: tofu apply -auto-approve tfplanA few things to note about this pipeline:
- The
opentofu/setup-opentofuaction is maintained by the OpenTofu project. It's the equivalent ofhashicorp/setup-terraform. - We store the plan artifact between jobs — this ensures the apply uses the exact same plan that was reviewed.
- For state encryption with Azure Key Vault, add this to your backend configuration:
terraform {
encryption {
key_provider "external" "azkv" {
command = ["az", "keyvault", "secret", "show",
"--vault-name", "mykeyvault",
"--name", "opentofu-state-key",
"--query", "value", "-o", "tsv"]
}
method "aes_gcm" "state" {
keys = key_provider.external.azkv
}
state {
method = method.aes_gcm.state
}
}
}This encrypts your state file end-to-end using a key stored in Azure Key Vault. If your compliance team has asked "is our state encrypted at rest?" — this is the answer.
Azure-Specific Considerations
Working in the Azure ecosystem with OpenTofu brings a few Azure-specific nuances worth calling out:
Provider Compatibility. The azurerm provider is fully compatible with OpenTofu. It's MPL-licensed and available in the OpenTofu registry. No changes needed to your provider blocks.
State Backend. Azure Blob Storage works as a backend for both tools. If you're using the azurerm backend, your configuration carries over unchanged:
terraform {
backend "azurerm" {
resource_group_name = "rg-terraform-state"
storage_account_name = "stterraformstate"
container_name = "tfstate"
key = "prod/aks.tfstate"
}
}Azure Identity. OpenTofu supports the same Azure authentication mechanisms — ARM_CLIENT_ID/ARM_CLIENT_SECRET for service principals, or Workload Identity for GitHub Actions and AKS workloads. No changes needed.
Bicep as a Co-Existence Strategy. I've seen teams successfully use Bicep for subscription-level governance (management groups, policy assignments, RBAC) while using OpenTofu for resource-level infrastructure (AKS clusters, databases, networking). This hybrid approach gives you the best of both worlds — Microsoft-native governance with OpenTofu's flexibility and licensing.
Private Endpoints and Air-Gapped Environments. OpenTofu 1.10's OCI registry support is particularly valuable here. You can mirror providers to Azure Container Registry and configure tofu init to pull from your private registry:
provider_installation {
oci_mirror {
repository_template = "myacr.azurecr.io/opentofu-providers/${namespace}/${type}"
include = ["registry.opentofu.org/azurerm/*"]
}
}What I Tell My Clients
After walking through the technical details, here's the practical advice I give Azure-first teams in the region:
- If you're running Terraform today and it works, you don't need to panic. The BSL doesn't force you to do anything tomorrow. But you should plan a migration window.
- The migration is a weekend project, not a quarter-long initiative. Three commands to swap the binary. A week of testing. Then you're done.
- State encryption alone justifies the move for many organizations. If your security team has ever asked about state file protection, OpenTofu gives you a native, auditable answer.
- Don't use this as an excuse to rewrite everything in Bicep. Unless you have zero existing Terraform investment and are 100% Azure-only, the migration cost isn't worth it. OpenTofu is a drop-in replacement, not a rewrite.
- Governance matters more than features. OpenTofu's Linux Foundation governance gives you a community-driven roadmap that isn't beholden to any single vendor's quarterly earnings. In a region where vendor lock-in is a real concern, this matters.
Key Takeaways
- OpenTofu 1.10 has reached genuine feature parity with Terraform for Azure workloads, including state encryption, removed blocks, dynamic provider configurations, and OCI registry support — features Terraform doesn't offer natively.
- The migration is a drop-in replacement. Swap the
terraformbinary fortofu, runtofu init upgrade, and validate withtofu plan. Your HCL code, state files, and providers carry over unchanged. - The BSL license doesn't force you to migrate, but it should inform your decision. If your team builds internal platforms, wraps IaC in custom tooling, or operates in regulated environments, the licensing and governance model matters.
- For Azure-first teams, OpenTofu with Azure Blob backends and Azure Key Vault encryption is the pragmatic choice. It gives you native state encryption, air-gapped registry support, and Linux Foundation governance — all without changing your existing architecture.
- Consider a hybrid strategy: Bicep for Azure subscription governance, OpenTofu for resource-level infrastructure. This gives you Microsoft-native policy integration where it matters and OpenTofu's flexibility everywhere else.
Law Wen Feng is a Principal Solution Architect based in Malaysia, specializing in cloud-native architecture and infrastructure automation for enterprise teams across Southeast Asia. Find more at wenfeng.my.