IaC Ecosystem

OpenTofu: Open Source Terraform

● Beginner ⏱ 15 min read terraform

In August 2023, HashiCorp changed Terraform's license from the Mozilla Public License (MPL 2.0) to the Business Source License (BSL 1.1). The BSL restricts using Terraform to build competing products — a change that alarmed the ecosystem. In response, a group of companies forked Terraform at version 1.5.x and created OpenTofu under the Linux Foundation. OpenTofu is a drop-in replacement for Terraform with the same HCL syntax, the same provider ecosystem, and an active development roadmap.

Why OpenTofu Exists

The BSL change meant that:

OpenTofu's goal: maintain a truly open-source (MPL 2.0) Terraform-compatible tool that the community controls. The OpenTofu Steering Committee includes representatives from major infrastructure companies including Gruntwork, Spacelift, Harness, and others.

🧭
If you use Terraform today, you don't need to migrate

Terraform under the BSL is still available and usable for most workloads. The BSL restriction targets products that compete with HashiCorp commercially. Internal use, DevOps tooling, and most common use cases are unaffected. OpenTofu is the right choice if you need the MPL license, want community governance, or want features OpenTofu ships first.

Compatibility with Terraform

OpenTofu maintains high compatibility with Terraform at the HCL and state level:

AspectStatus
HCL syntaxFully compatible — same .tf files work unchanged
State file formatCompatible — OpenTofu reads Terraform state files
Provider registryCompatible — uses the same registry.terraform.io providers
Module registryCompatible — registry.terraform.io modules work
Backend configurationCompatible — S3, GCS, Azure Blob, etc.
Terraform Cloud / HCPNot compatible — OpenTofu uses its own cloud offering

OpenTofu tracks Terraform closely. As of OpenTofu 1.8+, the two tools share the same foundational feature set from the 1.5 fork point, plus additional features OpenTofu has added independently.

What OpenTofu Adds

OpenTofu ships features that didn't exist in Terraform at fork time, or that it implements differently:

Provider-defined functions (1.7+)

Providers can expose custom functions callable in HCL expressions — not just resources and data sources:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Call a provider-defined function
output "ami_name" {
  value = provider::aws::arn_parse(var.ami_arn).resource
}

Stacks (experimental, 1.8+)

Stacks let you deploy a single module configuration across multiple environments or regions in one operation, with a new .tfstack.hcl file type.

Early variable evaluation

OpenTofu allows variable references in backend and provider blocks — something Terraform doesn't support. This eliminates the need for wrapper scripts or partial backend configuration in many cases:

variable "environment" {
  type = string
}

terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "${var.environment}/terraform.tfstate"  # works in OpenTofu, not in Terraform
    region = "us-east-1"
  }
}

State Encryption

State files contain sensitive values — passwords, API keys, private keys — and Terraform stores them in plaintext (relying on backend-level encryption like S3 SSE). OpenTofu 1.7 added native state encryption: the state file is encrypted before writing, regardless of the backend.

terraform {
  encryption {
    key_provider "pbkdf2" "main" {
      passphrase = var.state_passphrase
    }

    method "aes_gcm" "default" {
      keys = key_provider.pbkdf2.main
    }

    state {
      method = method.aes_gcm.default
    }

    plan {
      method = method.aes_gcm.default
    }
  }
}

Key providers beyond PBKDF2 include AWS KMS, GCP KMS, and OpenBao (the open-source Vault fork). The encryption is transparent to normal operations — tofu plan and tofu apply work the same way.

Provider Ecosystem

OpenTofu uses the same providers as Terraform. All providers published to registry.terraform.io work with OpenTofu without modification — providers use a stable plugin protocol (gRPC) that both tools implement.

OpenTofu also maintains its own registry at registry.opentofu.org, which mirrors the main registry and adds OpenTofu-specific providers and modules.

The required_providers block works identically:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.50"
    }
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
  }
  required_version = ">= 1.7"
}

Migrating from Terraform

Migration is intentionally low-friction. The main steps:

1. Install OpenTofu

# macOS
brew install opentofu

# Linux (official install script)
curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh | sh

# Verify
tofu version

2. Replace the terraform binary

OpenTofu uses the tofu command instead of terraform. All subcommands are identical: tofu init, tofu plan, tofu apply, tofu destroy.

3. Re-initialize the working directory

tofu init

OpenTofu re-downloads providers and re-creates the lock file. Your existing state and .tf files are untouched.

4. Verify the plan matches expectations

tofu plan

A clean plan (no unexpected changes) confirms compatibility. If you see unexpected resource replacements, compare the provider versions — you may need to pin to the version that was in your Terraform lock file.

Updating CI/CD

Replace hashicorp/setup-terraform with the OpenTofu equivalent:

- uses: opentofu/setup-opentofu@v1
  with:
    tofu_version: "~1.8"

Key Takeaways