- Introduction
- Why the Comparison Matters Now
- License Comparison: BSL vs MPL 2.0
- Core Feature Comparison Table
- State Encryption: OpenTofu's Killer Feature
- Provider Iteration: A Breakthrough for Multi-Region/Multi-Account Management
- Testing Framework Comparison
- Migration Strategy: From Terraform to OpenTofu
- Bringing In Existing Resources with the Import Block
- Comparing the Alternatives: Pulumi, AWS CDK, Crossplane
- Team Adoption Guide: Which Tool Should You Choose
- Failure Cases and Troubleshooting
- Production Operations Best Practices
- Performance Benchmarks
- 2026 Roadmap Outlook
- Conclusion
- References

Introduction
In August 2023, HashiCorp's announcement that it would change Terraform's license from MPL 2.0 to the BSL (Business Source License) sent a shock through the IaC (Infrastructure as Code) ecosystem. OpenTofu, born as the community's response, was accepted as a CNCF Incubating project in April 2025 and entered a phase of serious enterprise adoption. As of 2026, OpenTofu has moved past v1.10 and offers features Terraform does not have, including State encryption, an improved testing framework, and provider iteration.
Terraform, meanwhile, still holds a 32.8% market share and is strengthening an integrated-platform strategy centered on HCP (HashiCorp Cloud Platform). With the spread of GenAI, 71% of cloud teams report growth in the volume of their IaC code — which makes choosing the right IaC tool a strategic decision tied directly to team productivity and infrastructure security.
This article compares the 2026 state of OpenTofu and Terraform in depth across license, features, performance, ecosystem, and migration, and offers a selection guide suited to your team's situation.
Why the Comparison Matters Now
Joining CNCF and the Shift in the Ecosystem
OpenTofu's acceptance as a CNCF Incubating project means more than an organizational change. Vendor-neutral development is guaranteed under CNCF governance, and the project has earned community trust on the level of Kubernetes, Prometheus, and Envoy.
How GenAI Is Reshaping the IaC Landscape
According to a 2026 survey, 71% of cloud teams are seeing their IaC code volume grow because of GenAI. Tool choice now matters for quality-checking AI-generated Terraform/OpenTofu code, automating review, and detecting drift.
The License Fork in the Road
The practical impact of the BSL license is arriving in earnest in 2026. Building commercial services on top of Terraform is restricted, which directly affects Managed Service Providers and Platform Engineering teams.
License Comparison: BSL vs MPL 2.0
The license difference is not merely a legal matter — it is a core factor determining the tool's future direction and how much freedom a team has.
| Item | Terraform (BSL 1.1) | OpenTofu (MPL 2.0) |
|---|---|---|
| Source code disclosure | Open (conditional) | Fully open |
| Commercial use | Competing products restricted | No restriction |
| Forking allowed | Limited | Free |
| Offering a Managed Service | Not allowed if it competes with HashiCorp | Free |
| CNCF governance | None (HashiCorp alone) | CNCF Incubating |
| Community contribution | CLA required | DCO (Developer Certificate of Origin) |
| License change after 4 years | Converts automatically to Apache 2.0 | No change (always MPL 2.0) |
The Practical Impact of the BSL
The scenarios to watch out for when using Terraform under the BSL license are as follows.
# Internal use like this is permitted even under the BSL
# - Managing your own infrastructure
# - Building internal Platform Engineering tooling
# - Configuring customer infrastructure for consulting purposes
# Cases like the following may violate the BSL
# - Shipping a SaaS product that wraps Terraform
# - Offering a Managed IaC service that bundles the Terraform CLI
# - Building a competing IaC platform on top of Terraform
Core Feature Comparison Table
The table below compares the core features of OpenTofu v1.10 and Terraform v1.10 as of March 2026.
| Feature | OpenTofu 1.10+ | Terraform 1.10+ | Notes |
|---|---|---|---|
| State encryption | Native support | Not supported (needs HCP) | OpenTofu-only feature |
| Provider Iteration (for_each) | Supported | Not supported | Iteration at the provider level |
| Testing framework | tofu test (extended) | terraform test | Similar, but OpenTofu is more flexible |
| Import block | Supported (generate option) | Supported (generate option) | Comparable on both sides |
| Moved block | Supported | Supported | Tracks resource moves |
| Check block | Supported | Supported | Assertion-based validation |
| Removed block | Supported | Supported | Safe resource removal |
| S3 State Locking (no DynamoDB) | Supported | Not supported | OpenTofu-only improvement |
| Early Variable Evaluation | Supported | Not supported | Evaluates variables early |
| Override Files (.tofu) | Supported | Not applicable | OpenTofu-only override |
| Registry | registry.opentofu.org | registry.terraform.io | High provider compatibility |
| CLI name | tofu | terraform | Identical command structure |
State Encryption: OpenTofu's Killer Feature
State files store sensitive data — database passwords, API keys, certificates — in plaintext. OpenTofu solves this with native State encryption.
Configuring OpenTofu State Encryption
# main.tf - OpenTofu State encryption configuration
terraform {
encryption {
# Option 1: PBKDF2-based passphrase encryption
method "aes_gcm" "passphrase" {
keys = key_provider.pbkdf2.mykey
}
key_provider "pbkdf2" "mykey" {
passphrase = var.state_encryption_passphrase
}
state {
method = method.aes_gcm.passphrase
enforced = true
}
plan {
method = method.aes_gcm.passphrase
enforced = true
}
}
}
Enterprise Encryption with AWS KMS
# State encryption backed by AWS KMS
terraform {
encryption {
key_provider "aws_kms" "production" {
kms_key_id = "arn:aws:kms:ap-northeast-2:123456789012:key/mrk-abc123"
region = "ap-northeast-2"
key_spec = "AES_256"
}
method "aes_gcm" "kms_encrypt" {
keys = key_provider.aws_kms.production
}
state {
method = method.aes_gcm.kms_encrypt
enforced = true
}
plan {
method = method.aes_gcm.kms_encrypt
enforced = true
}
}
backend "s3" {
bucket = "my-tofu-state"
key = "prod/terraform.tfstate"
region = "ap-northeast-2"
encrypt = true
use_lockfile = true # Native S3 locking, no DynamoDB required
}
}
State Security in Terraform (for Comparison)
Terraform does not support native State encryption, so you have to fall back on workarounds like the following.
# Terraform - server-side encryption on the S3 backend (not State-level encryption)
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "ap-northeast-2"
encrypt = true # SSE-S3 or SSE-KMS
kms_key_id = "arn:aws:kms:ap-northeast-2:123456789012:key/mrk-abc123"
dynamodb_table = "terraform-locks" # A DynamoDB lock table is required
}
}
# Caution: S3 encrypt=true is only "encryption at rest"
# Download the State file from S3 and it is exposed in plaintext
# terraform state pull also prints plaintext
Provider Iteration: A Breakthrough for Multi-Region/Multi-Account Management
OpenTofu's Provider Iteration lets you instantiate the same provider repeatedly with different configurations.
# OpenTofu - creating multi-region resources with provider for_each
variable "regions" {
type = set(string)
default = ["ap-northeast-2", "us-east-1", "eu-west-1"]
}
provider "aws" "by_region" {
for_each = var.regions
region = each.value
}
resource "aws_s3_bucket" "regional_logs" {
for_each = var.regions
provider = aws.by_region[each.value]
bucket = "app-logs-${each.value}"
tags = {
Region = each.value
Purpose = "regional-logs"
}
}
Doing the same thing in Terraform means defining a separate provider alias by hand for every region.
# Terraform - manual provider aliases (limited scalability)
provider "aws" {
alias = "ap_northeast_2"
region = "ap-northeast-2"
}
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
}
provider "aws" {
alias = "eu_west_1"
region = "eu-west-1"
}
# Every new region means adding a provider block and a resource block by hand
resource "aws_s3_bucket" "logs_apne2" {
provider = aws.ap_northeast_2
bucket = "app-logs-ap-northeast-2"
}
resource "aws_s3_bucket" "logs_use1" {
provider = aws.us_east_1
bucket = "app-logs-us-east-1"
}
Testing Framework Comparison
OpenTofu Test
# tests/vpc.tftest.hcl - OpenTofu test
variables {
vpc_cidr = "10.0.0.0/16"
environment = "test"
project_name = "myapp"
}
run "create_vpc" {
command = apply
assert {
condition = aws_vpc.main.cidr_block == "10.0.0.0/16"
error_message = "VPC CIDR does not match the expected value"
}
assert {
condition = aws_vpc.main.enable_dns_hostnames == true
error_message = "DNS hostnames must be enabled"
}
assert {
condition = length(aws_subnet.private) == 3
error_message = "There must be 3 private subnets"
}
}
run "verify_security_group" {
command = plan
assert {
condition = aws_security_group.web.ingress[0].from_port == 443
error_message = "HTTPS ingress must be configured"
}
}
Terraform Test (for Comparison)
# tests/vpc.tftest.hcl - Terraform test (similar structure)
variables {
vpc_cidr = "10.0.0.0/16"
environment = "test"
}
run "create_vpc" {
command = apply
assert {
condition = aws_vpc.main.cidr_block == "10.0.0.0/16"
error_message = "VPC CIDR mismatch"
}
}
# Note: the basic structure is the same, but OpenTofu offers more
# test-runner options and mock provider capabilities
Migration Strategy: From Terraform to OpenTofu
Pre-Migration Compatibility Check
Always verify the compatibility of your current environment before migrating.
# 1. Check the current Terraform version
terraform version
# Terraform v1.10.x
# 2. List the providers in use
terraform providers
# 3. Check the State file version
terraform state pull | python3 -c "
import sys, json
state = json.load(sys.stdin)
print(f'State Version: {state.get(\"version\", \"unknown\")}')
print(f'TF Version: {state.get(\"terraform_version\", \"unknown\")}')
print(f'Resources: {len(state.get(\"resources\", []))}')
"
Step-by-Step Migration Procedure
# Step 1: Install OpenTofu
# macOS
brew install opentofu
# Linux (official install script)
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh -s -- --install-method rpm
# Check the version
tofu version
# OpenTofu v1.10.x
# Step 2: Initialize inside the existing project directory
cd /path/to/terraform/project
# Clean out the .terraform directory (optional - for a clean start)
rm -rf .terraform .terraform.lock.hcl
# Initialize with OpenTofu
tofu init
# Step 3: Confirm with plan that nothing changes
tofu plan
# When all is well: "No changes. Your infrastructure matches the configuration."
# Step 4: Check State file integrity
tofu state list
tofu state show aws_vpc.main
Switching Over in the CI/CD Pipeline
# .github/workflows/tofu-deploy.yml
name: OpenTofu Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
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.10.0'
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-tofu
aws-region: ap-northeast-2
- name: OpenTofu Init
run: tofu init -no-color
- name: OpenTofu Plan
id: plan
run: tofu plan -no-color -out=tfplan
continue-on-error: true
- name: Comment PR with Plan
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const plan = `${{ steps.plan.outputs.stdout }}`;
const truncated = plan.length > 60000
? plan.substring(0, 60000) + '\n... (truncated)'
: plan;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## OpenTofu Plan\n\`\`\`\n${truncated}\n\`\`\``
});
apply:
needs: plan
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v1
with:
tofu_version: '1.10.0'
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-tofu
aws-region: ap-northeast-2
- name: OpenTofu Init & Apply
run: |
tofu init -no-color
tofu apply -no-color -auto-approve
GitLab CI Integration
# .gitlab-ci.yml
stages:
- validate
- plan
- apply
variables:
TOFU_VERSION: '1.10.0'
TF_ROOT: 'infrastructure/production'
.tofu_base:
image: ghcr.io/opentofu/opentofu:${TOFU_VERSION}
before_script:
- cd ${TF_ROOT}
- tofu init -no-color
validate:
extends: .tofu_base
stage: validate
script:
- tofu validate -no-color
- tofu fmt -check -recursive
plan:
extends: .tofu_base
stage: plan
script:
- tofu plan -no-color -out=plan.cache
artifacts:
paths:
- ${TF_ROOT}/plan.cache
expire_in: 1 week
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
apply:
extends: .tofu_base
stage: apply
script:
- tofu apply -no-color -auto-approve plan.cache
dependencies:
- plan
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
Atlantis Integration
# atlantis.yaml
version: 3
automerge: false
delete_source_branch_on_merge: true
projects:
- name: production-infra
dir: infrastructure/production
workspace: default
terraform_version: v1.10.0 # When using OpenTofu with Atlantis
workflow: opentofu
autoplan:
when_modified:
- '*.tf'
- '*.tfvars'
- 'modules/**/*.tf'
enabled: true
workflows:
opentofu:
plan:
steps:
- env:
name: ATLANTIS_TERRAFORM_EXECUTABLE
value: tofu
- init
- plan
apply:
steps:
- env:
name: ATLANTIS_TERRAFORM_EXECUTABLE
value: tofu
- apply
Bringing In Existing Resources with the Import Block
Both OpenTofu and Terraform support the declarative import block.
# imports.tf - bringing existing resources into code
import {
to = aws_vpc.existing_production
id = "vpc-0abc123def456"
}
import {
to = aws_subnet.existing_private["ap-northeast-2a"]
id = "subnet-0abc123"
}
import {
to = aws_security_group.existing_web
id = "sg-0abc123"
}
# Automatic code generation (supported by both OpenTofu and Terraform)
# tofu plan -generate-config-out=generated.tf
# or
# terraform plan -generate-config-out=generated.tf
# Run and verify the import
tofu plan -generate-config-out=generated_imports.tf
# Review the generated code
cat generated_imports.tf
# Apply after making any necessary edits
tofu apply
Comparing the Alternatives: Pulumi, AWS CDK, Crossplane
OpenTofu and Terraform are not the whole of IaC. Depending on your team's tech stack and requirements, another tool may fit better.
| Item | OpenTofu/Terraform | Pulumi | AWS CDK | Crossplane |
|---|---|---|---|---|
| Language | HCL | TypeScript, Python, Go, etc. | TypeScript, Python, etc. | YAML (K8s CRD) |
| Learning curve | Medium (learn HCL) | Low (a language you know) | Low (a language you know) | High (K8s required) |
| Multi-cloud | Strong | Strong | AWS only | Strong |
| State management | File-based | SaaS/file | CloudFormation | K8s etcd |
| Drift detection | Manual, via plan | Preview + Watch | Drift Detection | Automatic, controller |
| Ease of testing | Limited (tftest) | Rich unit testing | CDK Assertions | K8s testing tools |
| Community size | Very large | Growing | AWS ecosystem | K8s ecosystem |
| Production usage | Very extensive | Increasing | Extensive in AWS environments | Increasing in K8s environments |
// Pulumi example - defining infrastructure in TypeScript
import * as aws from '@pulumi/aws'
const vpc = new aws.ec2.Vpc('production-vpc', {
cidrBlock: '10.0.0.0/16',
enableDnsHostnames: true,
tags: {
Name: 'production-vpc',
ManagedBy: 'pulumi',
},
})
// You can put your existing TypeScript knowledge straight to work
const subnets = ['a', 'b', 'c'].map(
(az, i) =>
new aws.ec2.Subnet(`private-${az}`, {
vpcId: vpc.id,
cidrBlock: `10.0.${i + 1}.0/24`,
availabilityZone: `ap-northeast-2${az}`,
})
)
Team Adoption Guide: Which Tool Should You Choose
When to Choose OpenTofu
- Organizations for which an open-source license is mandatory: public agencies, academic institutions, companies with an OSS-first policy
- When State security comes first: regulated environments in finance, healthcare, and the public sector
- When you are building a Managed IaC service: avoiding the BSL license restriction
- Organizations standardizing on the CNCF ecosystem: consistency with Kubernetes, ArgoCD, Crossplane, and the like
- When multi-region/multi-account management is frequent: putting Provider Iteration to work
When to Stay on Terraform
- When you already use HCP Terraform (formerly Terraform Cloud): the benefits of the integrated platform
- When you are tightly integrated with the HashiCorp ecosystem (Vault, Consul, Nomad): native integration
- When you need dependable enterprise support: HashiCorp's commercial support
- When the team's migration cost outweighs the benefit: existing CI/CD, training material, and module assets
- When you make heavy use of Sentinel policies: OpenTofu's OPA alternative takes more setup
Migration Decision Checklist
#!/bin/bash
# migration-readiness-check.sh
# Script that checks readiness for an OpenTofu migration
echo "=== OpenTofu Migration Readiness Check ==="
# 1. Terraform version compatibility
TF_VERSION=$(terraform version -json | python3 -c "import sys,json; print(json.load(sys.stdin)['terraform_version'])")
echo "[1] Current Terraform Version: ${TF_VERSION}"
MAJOR=$(echo "${TF_VERSION}" | cut -d. -f1)
MINOR=$(echo "${TF_VERSION}" | cut -d. -f2)
if [ "${MAJOR}" -ge 1 ] && [ "${MINOR}" -ge 6 ]; then
echo " -> Compatible with OpenTofu migration"
else
echo " -> WARNING: Upgrade Terraform first before migration"
fi
# 2. Check the providers in use
echo ""
echo "[2] Provider Check:"
terraform providers | grep -E "provider\[" | sort -u
# 3. Check the State backend
echo ""
echo "[3] Backend Configuration:"
grep -r "backend " *.tf 2>/dev/null || echo " Local backend (default)"
# 4. Check external module sources
echo ""
echo "[4] Module Sources:"
grep -r "source " modules/ *.tf 2>/dev/null | grep -v ".terraform" | head -20
# 5. Whether provisioners are used (a migration risk factor)
echo ""
echo "[5] Provisioner Usage (migration risk):"
grep -rn "provisioner " *.tf modules/ 2>/dev/null || echo " No provisioners found (good)"
echo ""
echo "=== Check Complete ==="
Failure Cases and Troubleshooting
Case 1: Recovering a Corrupted State File
# Symptom: "Error refreshing state" during tofu plan
# 1. Check the State backup
ls -la terraform.tfstate.backup
# 2. Restore from the backup
cp terraform.tfstate.backup terraform.tfstate
# 3. Check State integrity
tofu state list
# 4. If the remote State is corrupted - pull it locally and repair by hand
tofu state pull > state_backup.json
# Edit the JSON file to remove the corrupted resource
python3 -c "
import json
with open('state_backup.json', 'r') as f:
state = json.load(f)
# Filter out the corrupted resource
state['resources'] = [
r for r in state['resources']
if r.get('type') != 'corrupted_resource_type'
]
with open('state_fixed.json', 'w') as f:
json.dump(state, f, indent=2)
"
# Push the repaired State
tofu state push state_fixed.json
Case 2: Provider Version Incompatibility
# Problem: a particular provider stops working after the OpenTofu migration
terraform {
required_providers {
aws = {
# Name the OpenTofu registry explicitly
source = "hashicorp/aws"
# Widen the version range to secure compatibility
version = ">= 5.0, < 6.0"
}
# Community providers may live under a different source
datadog = {
source = "DataDog/datadog"
version = "~> 3.0"
}
}
}
# Provider mirroring configuration (air-gapped environment)
# .tofurc or .terraformrc
# provider_installation {
# filesystem_mirror {
# path = "/usr/share/tofu/providers"
# include = ["registry.opentofu.org/*/*"]
# }
# }
Case 3: Lock Conflict During Migration
# Symptom: running Terraform and OpenTofu at the same time causes a State Lock conflict
# 1. Force-release the lock (caution: confirm nobody else is working)
tofu force-unlock LOCK_ID
# 2. Inspect the DynamoDB lock table directly (when using the Terraform backend)
aws dynamodb scan \
--table-name terraform-locks \
--filter-expression "attribute_exists(LockID)" \
--output json
# 3. Switch to native S3 locking (OpenTofu only)
# Remove dynamodb_table from the backend "s3" configuration, then
# add use_lockfile = true
Production Operations Best Practices
Standardizing Module Structure
# Recommended directory layout (common to OpenTofu and Terraform)
infrastructure/
environments/
production/
main.tf
variables.tf
outputs.tf
terraform.tfvars
backend.tf
staging/
main.tf
variables.tf
outputs.tf
terraform.tfvars
backend.tf
modules/
vpc/
main.tf
variables.tf
outputs.tf
tests/
vpc.tftest.hcl
ecs-service/
main.tf
variables.tf
outputs.tf
tests/
ecs.tftest.hcl
global/
iam/
main.tf
dns/
main.tf
Automating Drift Detection
# .github/workflows/drift-detection.yml
name: Infrastructure Drift Detection
on:
schedule:
- cron: '0 9 * * 1-5' # 9 a.m. on weekdays
jobs:
detect-drift:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [production, staging]
steps:
- uses: actions/checkout@v4
- uses: opentofu/setup-opentofu@v1
- name: Detect Drift
id: drift
run: |
cd infrastructure/environments/${{ matrix.environment }}
tofu init -no-color
tofu plan -no-color -detailed-exitcode 2>&1 | tee plan_output.txt
echo "exitcode=$?" >> "$GITHUB_OUTPUT"
continue-on-error: true
- name: Notify on Drift
if: steps.drift.outputs.exitcode == '2'
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Infrastructure drift detected in ${{ matrix.environment }}!",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Drift detected* in `${{ matrix.environment }}`\nRun: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DRIFT_WEBHOOK }}
Performance Benchmarks
These are performance comparison results at real production scale (more than 500 resources).
| Operation | OpenTofu 1.10 | Terraform 1.10 | Difference |
|---|---|---|---|
| init (cold start) | 12.3s | 11.8s | OpenTofu +4% |
| plan (500 resources) | 45.2s | 47.8s | OpenTofu -5% |
| plan (with State encryption) | 48.1s | Not applicable | About 6% encryption overhead |
| apply (50 resources changed) | 120s | 118s | Essentially identical |
| state list (500 resources) | 0.8s | 0.9s | Essentially identical |
| refresh (500 resources) | 62s | 65s | OpenTofu -5% |
The performance difference is negligible for most workloads. Choose a tool on features, license, and ecosystem support rather than on performance.
2026 Roadmap Outlook
OpenTofu Roadmap
- Stronger State migration tooling: support for converting State from other IaC tools
- Native OPA/Rego integration: a built-in policy engine
- Provider Development Kit improvements: a better provider development experience
- CDKTF compatibility: a compatibility layer with CDK for Terraform
Terraform Roadmap
- A stronger HCP Terraform: AI-driven code review and cost forecasting
- Stacks: orchestrating deployments across environments (a new abstraction layer)
- Sentinel v2: an upgraded policy engine
- Expanding the Cloud Operating Model: deeper HashiCorp platform integration
Conclusion
As of 2026, OpenTofu and Terraform remain highly compatible in features while diverging in their own directions. OpenTofu is building differentiation in open-source governance, State encryption, and Provider Iteration, while Terraform is strengthening the value of an integrated platform centered on HCP.
There is no single "right answer" in choosing a tool. You have to weigh your team's license requirements, security regulations, existing dependence on the HashiCorp ecosystem, multi-cloud strategy, and long-term technical vision together. That said, if you are starting a new project or your organization has license concerns, looking at OpenTofu first is a reasonable choice in 2026.
References
- OpenTofu official documentation - documentation for OpenTofu-only features such as State encryption and Provider Iteration
- Terraform official documentation - HCL syntax, providers, and backend configuration guides
- CNCF OpenTofu Incubating announcement - the official blog post on joining CNCF
- Spacelift OpenTofu vs Terraform comparison - feature and performance comparison analysis
- HashiCorp BSL FAQ - a detailed explanation of the BSL license
- OpenTofu GitHub Repository - source code and issue tracker
- Terraform Registry - provider and module registry
- OpenTofu Registry - the OpenTofu provider registry
- CNCF Landscape - IaC - the full map of the CNCF infrastructure tooling ecosystem
- Pulumi vs Terraform comparison - reference for comparing the alternatives