on
Migrating from Terraform to OpenTofu: a practical intro and step-by-step path
OpenTofu is the community-driven open-source fork of Terraform that emerged after Terraform’s licensing change. For teams who want to preserve an open, community-owned IaC toolchain while keeping most existing Terraform code and workflows, OpenTofu is intentionally compatible with the Terraform language and ecosystem—while also introducing its own registry, provider protocols, and some new features. (env.dev)
This article gives a concise, practical migration path: why migration can be straightforward, the risks to watch for, and a minimal, reliable procedure you can follow (with example configs and commands). It’s aimed at people with working Terraform code who want a low-friction route into OpenTofu.
Why OpenTofu is a pragmatic option
- OpenTofu started from the last widely open-source Terraform release and preserves the HCL language, CLI behavior, and state format compatibility in most cases. That design makes migration feasible without a wholesale rewrite. (env.dev)
- The community maintains its own provider discovery and distribution (the OpenTofu registry / provider protocol), and you can also mirror providers into OCI registries if you need private distribution. Those changes are the main operational differences you’ll hit. (opentofu.org)
Before you migrate: checklist
- Inventory and pin versions. Record Terraform/OpenTofu-compatible provider versions and any custom providers. Explicit version constraints reduce surprises. (opentofu.org)
- Back up state and lock down changes. Take a copy of every state file (remote and local) and enforce a short change freeze while you switch binaries or migrate.
- Confirm CI/CD and automation. Locate any scripts or CI runners that call the terraform binary and plan to replace or alias them to the OpenTofu binary.
- Test in a sandbox. Use a non-production workspace and a cloned backend before touching production state. This avoids surprises with provider differences or CI behavior. (opentofu.org)
High-level migration approaches
- Binary swap (recommended for most teams): install the OpenTofu binary, keep your HCL files unchanged, and run init/plan/apply. Because OpenTofu was forked from a compatible Terraform release, this often works without code edits. (opentofu.org)
- Gradual migration per environment: use the binary swap in development first, then stage, then production. When state needs a particular order for interdependent configurations, migrate leaf modules first and progress toward roots. OpenTofu’s docs have explicit guidance when multiple configurations share remote state. (opentofu.org)
A minimal, safe step-by-step (binary-swap) procedure
- Freeze writes and snapshot state
- Put a short maintenance window on your IaC changes and snapshot remote state (S3, Azure Blob, GCS, etc.). Export copies locally and to durable storage.
- Install OpenTofu alongside Terraform
- Download and install the OpenTofu binary on a test machine or CI runner. You can keep Terraform installed; make sure the PATH points to the OpenTofu binary when you test.
- Init and validate
- From your configuration directory:
opentofu init opentofu validate opentofu plan -out=tf-plan - Look for provider download or signature errors. If a provider cannot be found, you’ll need to point OpenTofu at a provider mirror or the OpenTofu registry (see provider section below). (opentofu.org)
- From your configuration directory:
- Dry-run in a non-production backend
- Run plan against a cloned backend to confirm no unintentional diffs. If plan is clean, you’ve validated compatibility for that workspace.
- Promote to production
- During the maintenance window, switch the production runners to run the OpenTofu binary and apply the plan. Keep the original Terraform binary available to roll back if required.
Special-case: migrating multiple interdependent configurations If your infrastructure is split into multiple repos or states that reference each other (for example via terraform_remote_state), migration order matters. The safe pattern is to migrate leaf modules first (those that have no dependencies), validate their state, then move upward in the dependency graph. OpenTofu’s migration guidance explains why ordering avoids transient mismatches in state expectations. (opentofu.org)
Providers and the registry: what changes and how to handle them
- OpenTofu uses a provider registry protocol and its own registry endpoint to discover and distribute providers; this is the main runtime difference from using the Terraform public registry. In practice, many existing providers are available in the OpenTofu registry or can be mirrored. (opentofu.org)
- If your environment requires private control over provider binaries (air-gapped or restricted networks), OpenTofu supports mirroring providers to OCI registries. You can configure provider mirrors so OpenTofu pulls provider binaries from your private OCI host rather than the public registry. This is useful for reproducibility and security auditing. (opentofu.org)
Example: an OCI provider mirror snippet Place a provider mirror configuration in your OpenTofu CLI config (example pseudocode — adapt to your platform):
provider_installation {
filesystem_mirror {
path = "/opt/opentofu-providers"
}
oci_mirror {
host = "example.com"
repository = "opentofu-providers/hashicorp/aws"
}
direct {}
}
This tells OpenTofu to look in a local filesystem mirror and an OCI host before falling back to the direct registry. The actual syntax should follow the OpenTofu CLI docs for provider-mirror configuration. (opentofu.org)
Common gotchas and how to spot them
- Provider missing or version mismatch: during init, OpenTofu may report that it can’t find a provider version. Pointing to a correct mirror or adjusting the version constraint usually resolves this. (opentofu.org)
- State file differences: although most state is compatible, there are edge cases—especially around provider-specific state encoding or custom/local providers. Always validate with plan against a cloned backend first. (opentofu.org)
- CI runner and automation assumptions: scripts that look for a binary named terraform may fail. Either install OpenTofu as the terraform binary (binary swap) or update scripts to call opentofu explicitly.
- Interdependent state race: if you have many configurations that rely on each other’s outputs, follow the ordered migration approach and verify remote_state references after each step. (opentofu.org)
Validation and rollback
- Keep the original Terraform binary and a tested rollback plan. If the OpenTofu apply produces unexpected changes, you can re-run the last known working plan with Terraform (or restore the state snapshot).
- Use small, targeted applies for the first production changes to reduce blast radius.
Closing notes OpenTofu’s compatibility-first design makes it a realistic migration target for most Terraform users, but the process still requires disciplined backups, a test-first approach, and attention to provider distribution. The official OpenTofu migration documentation gives detailed steps and edge-case guidance—consult it for deeper scenarios and the exact CLI flags for provider mirrors and registry configuration. (opentofu.org)
If you follow the checklist, perform a binary swap in a staging environment, and validate step-by-step (especially for interdependent states), migration can be low-risk and largely transparent to your teams and automation. (opentofu.org)