Amazon Linux 2 End of Life 2026: What AWS Users Need to Do
Amazon Linux 2 reaches end of life June 30, 2026. Migrate EC2 instances, Lambda runtimes, and ECS containers to Amazon Linux 2023 before the deadline using
DevOps
Complete guide to migrating from Terraform to OpenTofu. Install OpenTofu, migrate state files, update CI/CD pipelines, handle provider registries
OpenTofu is a drop-in replacement for Terraform with an open-source MPL 2.0 license. Migration is straightforward for most projects — the CLI, HCL syntax, and state format are compatible. This guide covers the complete migration process including CI/CD updates and potential gotchas.
brew install opentofu
tofu versioncurl -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh
chmod +x install-opentofu.sh
./install-opentofu.sh --install-method deb
tofu versioncurl -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh
chmod +x install-opentofu.sh
./install-opentofu.sh --install-method rpm
tofu versiondocker pull ghcr.io/opentofu/opentofu:1.9
docker run --rm -v $(pwd):/workspace -w /workspace ghcr.io/opentofu/opentofu:1.9 initcd your-terraform-project/
# Remove Terraform's cached providers (OpenTofu will re-download)
rm -rf .terraform
rm .terraform.lock.hcl
# Initialize with OpenTofu
tofu init
# Plan — should show NO changes
tofu planIf tofu plan shows no changes, your migration is 90% done. The state file, HCL syntax, and providers all work.
# Check state is readable
tofu state list
# Verify a specific resource
tofu state show aws_instance.web
# Compare with what Terraform showed
# (If you still have terraform installed)
terraform state list # Should match exactly# Before
stages:
- plan
- apply
plan:
image: hashicorp/terraform:1.10
script:
- terraform init
- terraform plan -out=tfplan
artifacts:
paths: [tfplan]
apply:
image: hashicorp/terraform:1.10
script:
- terraform init
- terraform apply -auto-approve tfplan
# After
plan:
image: ghcr.io/opentofu/opentofu:1.9
script:
- tofu init
- tofu plan -out=tfplan
artifacts:
paths: [tfplan]
apply:
image: ghcr.io/opentofu/opentofu:1.9
script:
- tofu init
- tofu apply -auto-approve tfplan# Before
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.10.0"
# After
- uses: opentofu/setup-opentofu@v1
with:
tofu_version: "1.9.0"
- run: |
tofu init
tofu plan
tofu apply -auto-approve# repos.yaml
repos:
- id: "/.*/",
workflow: opentofu
workflows:
opentofu:
plan:
steps:
- env:
name: ATLANTIS_TERRAFORM_VERSION
value: "1.9.0"
- init
- planIf you have shell scripts or Makefiles:
# Before
TF = terraform
# After — support both with a fallback
TF = $(shell command -v tofu 2>/dev/null || echo terraform)
plan:
$(TF) init
$(TF) plan
apply:
$(TF) init
$(TF) apply -auto-approveOr use an alias for gradual migration:
# ~/.bashrc
alias terraform='tofu'terraform {
# Before — Terraform only
required_version = ">= 1.7.0"
# After — allow both Terraform and OpenTofu
required_version = ">= 1.7.0"
# OpenTofu respects the same constraint
}One advantage of OpenTofu — client-side state encryption:
terraform {
encryption {
key_provider "aws_kms" "state_key" {
kms_key_id = "alias/terraform-state"
region = "us-east-1"
}
method "aes_gcm" "default" {
keys = key_provider.aws_kms.state_key
}
state {
method = method.aes_gcm.default
enforced = true
}
plan {
method = method.aes_gcm.default
enforced = true
}
}
}After enabling encryption, the state file is encrypted before it reaches your backend. Even if someone accesses your S3 bucket, they can't read the state without the KMS key.
OpenTofu uses registry.opentofu.org by default but falls back to registry.terraform.io. Most providers work without changes:
# Works in both — source is the same
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}OpenTofu generates .terraform.lock.hcl in the same format. However, the hashes may differ between Terraform and OpenTofu for the same provider version. Re-run:
tofu providers lock \
-platform=linux_amd64 \
-platform=darwin_arm64This is the main migration blocker. If you use HCP Terraform as your backend:
# This does NOT work with OpenTofu
terraform {
cloud {
organization = "my-org"
workspaces { name = "production" }
}
}You need to migrate to a different backend first:
# Switch to S3 backend
terraform {
backend "s3" {
bucket = "my-tf-state"
key = "production/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}# Migrate state from HCP to S3
terraform init -migrate-state
# Then switch to OpenTofu
tofu initIf you use Sentinel policies (HCP Terraform only), you'll need to rewrite them as OPA/Rego policies:
# policy/no-public-s3.rego
package terraform.analysis
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket_public_access_block"
resource.change.after.block_public_acls != true
msg := sprintf("S3 bucket %s must block public ACLs", [resource.address])
}tofu init + tofu plan — verify no changes.terraform.lock.hclMigrating from Terraform to OpenTofu is a 30-minute task for most projects: install OpenTofu, run tofu init, verify tofu plan shows no changes, and update your CI/CD pipeline. The main blocker is HCP Terraform — if you use it as a backend, you'll need to migrate state to S3/GCS first. For self-hosted backends, the migration is seamless.
Amazon Linux 2 reaches end of life June 30, 2026. Migrate EC2 instances, Lambda runtimes, and ECS containers to Amazon Linux 2023 before the deadline using
Import dozens of existing AWS resources into Terraform at once using import blocks, for_each, and generate-config-out.
Use Terraform import blocks to bring existing AWS resources under management. Code-based import without CLI commands, generate config automatically
Terraform vs OpenTofu compared for 2026. Licensing (BSL vs MPL), feature differences (Stacks, ephemeral resources), provider compatibility