| name | opentofu-migration |
| description | Migrate from Terraform to OpenTofu with state compatibility, provider registry setup, and CI/CD pipeline updates. Use when adopting the open-source Terraform fork or evaluating license-free IaC. |
| license | MIT |
| metadata | {"author":"devops-skills","version":"1.0"} |
OpenTofu Migration
Migrate infrastructure-as-code from HashiCorp Terraform to the open-source OpenTofu fork.
When to Use This Skill
Use this skill when:
- Migrating from Terraform to OpenTofu for licensing reasons
- Setting up a new IaC project and evaluating OpenTofu vs Terraform
- Updating CI/CD pipelines to use OpenTofu
- Configuring the OpenTofu provider registry
Prerequisites
- Existing Terraform codebase (0.13+)
- OpenTofu CLI installed
- State backend access (S3, GCS, Azure Blob, etc.)
Install OpenTofu
brew install opentofu
curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh \
-o install-opentofu.sh
chmod +x install-opentofu.sh
./install-opentofu.sh --install-method deb
rm install-opentofu.sh
./install-opentofu.sh --install-method rpm
docker run --rm -v $(pwd):/workspace -w /workspace \
ghcr.io/opentofu/opentofu:latest init
tofu --version
Migration Checklist
1. Verify Compatibility
terraform version
tofu init
tofu plan
2. Replace CLI Commands
| Terraform | OpenTofu |
|---|
terraform init | tofu init |
terraform plan | tofu plan |
terraform apply | tofu apply |
terraform destroy | tofu destroy |
terraform fmt | tofu fmt |
terraform validate | tofu validate |
terraform state | tofu state |
terraform import | tofu import |
3. Update Provider Lock File
rm .terraform.lock.hcl
tofu init -upgrade
tofu providers
4. Update State Backend
State files are compatible — no migration needed. Just verify:
# backend.tf — works identically with OpenTofu
terraform {
backend "s3" {
bucket = "mycompany-tfstate"
key = "prod/infrastructure.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
tofu init
tofu state list
5. Provider Registry
OpenTofu uses its own registry but mirrors most Terraform providers:
# versions.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.25"
}
# OpenTofu-specific providers
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
}
OpenTofu-Specific Features
State Encryption (Not in Terraform)
# OpenTofu supports native state encryption
terraform {
encryption {
key_provider "pbkdf2" "my_key" {
passphrase = var.state_passphrase
}
method "aes_gcm" "encrypt" {
keys = key_provider.pbkdf2.my_key
}
state {
method = method.aes_gcm.encrypt
enforced = true
}
plan {
method = method.aes_gcm.encrypt
enforced = true
}
}
}
Early Variable/Local Evaluation
# OpenTofu allows variables in backend config and module sources
terraform {
backend "s3" {
bucket = var.state_bucket # Works in OpenTofu, not Terraform
key = "${var.project}/terraform.tfstate"
region = var.aws_region
}
}
CI/CD Pipeline Updates
GitHub Actions
name: OpenTofu
on:
pull_request:
paths: ["infra/**"]
push:
branches: [main]
paths: ["infra/**"]
permissions:
id-token: write
contents: read
pull-requests: write
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: "1.8.0"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/tofu-deploy
aws-region: us-east-1
- name: Init
run: tofu init
GitLab CI
stages: [validate, plan, apply]
variables:
TOFU_VERSION: "1.8.0"
.tofu-base:
image: ghcr.io/opentofu/opentofu:${TOFU_VERSION}
before_script:
- tofu init
validate:
extends: .tofu-base
stage: validate
script:
- tofu fmt -check
- tofu validate
plan:
extends: .tofu-base
stage: plan
script:
- tofu plan -out=tfplan
artifacts:
paths: [tfplan]
apply:
extends: .tofu-base
stage: apply
script:
- tofu apply tfplan
when: manual
only: [main]
dependencies: [plan]
Coexistence Strategy
If you need both tools during migration:
alias tf="terraform"
alias tofu="tofu"
export PATH="/opt/opentofu/bin:$PATH"
if [ -f ".use-opentofu" ]; then
exec tofu "$@"
else
exec terraform "$@"
fi
Troubleshooting
| Issue | Solution |
|---|
| Provider not found | Run tofu init -upgrade, check registry.opentofu.org |
| State lock conflict | Same as Terraform — check DynamoDB/blob lease |
| Version constraint error | Update required_version to >= 1.6.0 |
| Backend migration | State is compatible — just run tofu init |
| Missing provider credentials | Same env vars work (AWS_*, GOOGLE_*, ARM_*) |
Related Skills