TL;DR — Resumo Rápido

OpenTofu é o fork open-source do Terraform da Linux Foundation. Aprenda instalação, migração, criptografia de estado, sintaxe HCL e integração CI/CD.

OPENTOFU — INFRAESTRUTURA COMO CÓDIGO OPEN-SOURCE Terraform (BSL) HashiCorp / IBM Mudança de licença ago 2023 Fork OpenTofu (MPL 2.0) Linux Foundation registry.opentofu.org Criptografia de Estado AES-GCM / AWS KMS / GCP KMS Avaliação Antecipada de Vars vars em provider / backend Funções de Provedores funções HCL personalizadas Pipeline CI/CD setup-opentofu Action tofu plan → aprovação tofu apply autenticação OIDC AWS / Azure / GCP sem credenciais de longa duração Substituto direto do Terraform · MPL 2.0 · Linux Foundation · tofu substitui terraform em todo lugar

O OpenTofu é o fork open-source do Terraform mantido sob a Linux Foundation, criado após a HashiCorp mudar a licença do Terraform de Mozilla Public License 2.0 para a Business Source License (BSL) em agosto de 2023. Este guia cobre tudo que você precisa para entender as origens do OpenTofu, instalá-lo, migrar projetos Terraform existentes sem fricção, dominar os fundamentos de HCL, gerenciar estado com segurança usando criptografia do lado do cliente e integrá-lo em pipelines CI/CD modernos.

Por Que o OpenTofu Existe: A História do Fork de Licença

O Terraform foi open-source sob MPL 2.0 por mais de nove anos. Em 10 de agosto de 2023, a HashiCorp anunciou que o Terraform 1.6 e todas as versões futuras seriam lançadas sob a Business Source License (BSL 1.1) — uma licença de código-fonte disponível que restringe o uso do software para competir comercialmente com a HashiCorp.

A resposta da comunidade foi rápida. Em dias, engenheiros da Spacelift, Gruntwork, Env0, Harness, Scalr e outros assinaram uma carta aberta e criaram o fork OpenTofu a partir da última versão MPL 2.0 (Terraform 1.5.7). A Linux Foundation aceitou o OpenTofu como projeto em setembro de 2023, e o OpenTofu 1.6.0 — o primeiro lançamento estável com novos recursos — foi lançado em janeiro de 2024.

Implicações principais da mudança de licença:

  • Terraform OSS agora é BSL — você não pode construir um produto concorrente com ele
  • OpenTofu permanece em MPL 2.0 — completamente open-source, sem restrições comerciais
  • HashiCorp (agora IBM) controla o Terraform Cloud e o Terraform Enterprise
  • OpenTofu tem governança comunitária, com um Comitê Técnico Diretor e processo RFC aberto

Compatibilidade OpenTofu vs Terraform

O OpenTofu 1.6–1.9 tem como alvo compatibilidade direta com o Terraform 1.5.x:

Recurso OpenTofu Terraform OSS
Sintaxe HCL Idêntica ao TF 1.5 Igual
Ecossistema de provedores registry.opentofu.org + fallback terraform.io registry.terraform.io
Formato do arquivo de estado .tfstate compatível binariamente Mesmo formato
.terraform.lock.hcl Funciona sem alterações Igual
Comandos do binário tofu substitui terraform 1:1 terraform
Criptografia de estado Sim (AES-GCM, KMS) Não
Avaliação antecipada de variáveis Sim (1.8+) Não
Funções definidas por provedor Sim (1.8+) Não
Bloco removed Sim (1.7+) Parcial
Terraform Cloud Incompatível Nativo

O custo prático de migração para a maioria das equipes é uma substituição em massa de terraformtofu nos scripts de CI. Os arquivos HCL, provedores, módulos e arquivos de estado não são alterados.

Instalação

apt (Debian / Ubuntu)

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://get.opentofu.org/opentofu.gpg | \
  sudo tee /etc/apt/keyrings/opentofu.gpg > /dev/null
curl -fsSL https://packages.opentofu.org/opentofu/tofu/gpgkey | \
  sudo gpg --no-tty --batch --dearmor -o /etc/apt/keyrings/opentofu-repo.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/opentofu.gpg,/etc/apt/keyrings/opentofu-repo.gpg] \
  https://packages.opentofu.org/opentofu/tofu/any/ any main" | \
  sudo tee /etc/apt/sources.list.d/opentofu.list
sudo apt update && sudo apt install -y opentofu
tofu version

dnf (RHEL / Fedora / Rocky)

sudo tee /etc/yum.repos.d/opentofu.repo <<'EOF'
[opentofu]
name=opentofu
baseurl=https://packages.opentofu.org/opentofu/tofu/rpm_any/rpm_any/$basearch
enabled=1
gpgcheck=1
gpgkey=https://get.opentofu.org/opentofu.gpg
EOF
sudo dnf install -y opentofu

Homebrew

brew install opentofu

asdf

asdf plugin add opentofu
asdf install opentofu 1.9.0
asdf global opentofu 1.9.0

Migrando do Terraform

Passo 1 — Instalar o OpenTofu ao lado do Terraform

Ambos os binários podem coexistir. tofu e terraform são executáveis separados.

Passo 2 — Executar tofu init no seu projeto existente

cd meu-projeto-terraform/
tofu init

O OpenTofu lê o mesmo bloco versions.tf / required_providers. Ele baixa provedores de registry.opentofu.org. Seu .terraform.lock.hcl é reutilizado como está.

Passo 3 — Substituir terraform por tofu nos scripts de CI

# Antes
terraform fmt -check
terraform init -input=false
terraform plan -out=tfplan
terraform apply -auto-approve tfplan

# Depois (sem mudança de lógica)
tofu fmt -check
tofu init -input=false
tofu plan -out=tfplan
tofu apply -auto-approve tfplan

Passo 4 — Verificar compatibilidade de estado

O formato JSON .tfstate é idêntico. Se você gerencia estado remoto (S3, GCS, Azure Blob), nenhuma migração é necessária. Execute um plan com o OpenTofu: ele deve mostrar sem mudanças se a infraestrutura corresponde ao estado existente.

tofu plan
# Esperado: No changes. Your infrastructure matches the configuration.

Fundamentos de HCL

Provedores, Recursos e Fontes de Dados

terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.40"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name        = "${var.project}-vpc"
    Environment = var.environment
  }
}

data "aws_ami" "al2023" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-2023.*-x86_64"]
  }
}

Variáveis, Locais e Outputs

variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "O ambiente deve ser dev, staging ou prod."
  }
}

locals {
  common_tags = {
    Project     = var.project
    Environment = var.environment
    ManagedBy   = "opentofu"
  }
}

output "vpc_id" {
  description = "ID da VPC criada"
  value       = aws_vpc.main.id
}

count e for_each

resource "aws_subnet" "public" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  tags = merge(local.common_tags, { Name = "${var.project}-publica-${count.index + 1}" })
}

resource "aws_s3_bucket" "this" {
  for_each = var.buckets
  bucket   = "${var.project}-${each.key}-${data.aws_caller_identity.current.account_id}"
  tags     = merge(local.common_tags, { Name = each.key })
}

Blocos dinâmicos

resource "aws_security_group" "web" {
  name   = "${var.project}-sg-web"
  vpc_id = aws_vpc.main.id

  dynamic "ingress" {
    for_each = var.regras_ingresso
    content {
      from_port   = ingress.value.porta
      to_port     = ingress.value.porta
      protocol    = ingress.value.protocolo
      cidr_blocks = ingress.value.cidrs
      description = ingress.value.descricao
    }
  }
}

Gerenciamento de Estado

Backends remotos

# S3 + DynamoDB
terraform {
  backend "s3" {
    bucket         = "meu-bucket-estado-tofu"
    key            = "prod/infra/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "tofu-bloqueios-estado"
    encrypt        = true
  }
}

Criptografia de Estado do Lado do Cliente (exclusivo do OpenTofu)

# AWS KMS (recomendado para produção)
terraform {
  encryption {
    key_provider "aws_kms" "chave_prod" {
      kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/mrk-abc123"
      region     = "us-east-1"
      key_spec   = "AES_256"
    }

    method "aes_gcm" "metodo_prod" {
      keys = key_provider.aws_kms.chave_prod
    }

    state {
      method = method.aes_gcm.metodo_prod
    }

    plan {
      method = method.aes_gcm.metodo_prod
    }
  }
}

Comandos úteis de estado

tofu state list
tofu state show aws_instance.web[0]
tofu import aws_s3_bucket.assets meu-bucket-existente
tofu state mv aws_instance.web aws_instance.app
tofu force-unlock LOCK_ID

Módulos

# Caminho local
module "vpc" {
  source  = "./modules/vpc"
  project = var.project
  cidr    = "10.0.0.0/16"
}

# Tag Git
module "vpc_staging" {
  source  = "git::https://github.com/org/infra-modules.git//vpc?ref=v2.3.0"
  project = var.project
  cidr    = "10.1.0.0/16"
}

# Registro OpenTofu/Terraform
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.0"

  cluster_name = "${var.project}-${var.environment}"
  vpc_id       = module.vpc.vpc_id
  subnet_ids   = module.vpc.subnet_ids
}

Workspaces

tofu workspace new staging
tofu workspace new prod
tofu workspace list
tofu workspace select staging
locals {
  config_ambiente = {
    dev     = { tipo_instancia = "t3.micro",  min = 1, max = 2  }
    staging = { tipo_instancia = "t3.small",  min = 2, max = 4  }
    prod    = { tipo_instancia = "t3.medium", min = 3, max = 10 }
  }
  atual = local.config_ambiente[terraform.workspace]
}

Integração CI/CD

GitHub Actions com OIDC

name: OpenTofu Plan e Apply

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  id-token: write
  contents: read
  pull-requests: write

jobs:
  tofu:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configurar OpenTofu
        uses: opentofu/setup-opentofu@v1
        with:
          tofu_version: "1.9.0"

      - name: Configurar credenciais AWS via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsTofu
          aws-region: us-east-1

      - name: tofu init
        run: tofu init -input=false

      - name: tofu fmt check
        run: tofu fmt -check -recursive

      - name: tofu validate
        run: tofu validate

      - name: tofu plan
        run: tofu plan -out=tfplan -input=false

      - name: tofu apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: tofu apply -auto-approve tfplan

Tabela Comparativa de Ferramentas

Recurso OpenTofu Terraform OSS Terraform Cloud Pulumi Crossplane CDK for TF
Licença MPL 2.0 BSL 1.1 Proprietária Apache 2.0 Apache 2.0 MPL 2.0
Linguagem HCL HCL HCL Python/TS/Go YAML/Go Python/TS/Java
Criptografia de estado Sim (integrada) Não Sim (gerenciada) Sim (gerenciada) N/A Não
Avaliação antecipada de vars Sim (1.8+) Não Não N/A N/A N/A
Ecossistema de provedores Provedores Terraform Provedores Terraform Provedores Terraform Provedores Pulumi + ponte TF CRDs Kubernetes Provedores Terraform
Curva de aprendizado Baixa (HCL) Baixa (HCL) Baixa Média (código real) Alta (CRDs K8s) Média
Melhor para IaC open-source Equipes pequenas aceitando BSL Equipes querendo backend gerenciado Devs que preferem código Equipes nativas de Kubernetes Devs que não gostam de HCL

Exemplo Prático: Infraestrutura AWS

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = merge(local.common_tags, { Name = "${var.project}-vpc" })
}

resource "aws_subnet" "public" {
  count                   = var.az_count
  vpc_id                  = aws_vpc.main.id
  cidr_block              = cidrsubnet(var.vpc_cidr, 8, count.index)
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true
  tags = merge(local.common_tags, { Name = "${var.project}-publica-${count.index + 1}" })
}

resource "aws_lb" "main" {
  name               = "${var.project}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = aws_subnet.public[*].id
  tags               = local.common_tags
}

resource "aws_autoscaling_group" "app" {
  name                = "${var.project}-asg"
  vpc_zone_identifier = aws_subnet.private[*].id
  target_group_arns   = [aws_lb_target_group.app.arn]
  min_size            = local.atual.min
  max_size            = local.atual.max

  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }
}

output "dns_alb" {
  description = "Nome DNS do Application Load Balancer"
  value       = aws_lb.main.dns_name
}

Armadilhas e Casos Extremos

Fallback do registro de provedores: O OpenTofu verifica registry.opentofu.org primeiro. Se um provedor estiver apenas em registry.terraform.io, adicione um source explícito em required_providers.

Migração de criptografia de estado: Habilitar criptografia em um arquivo de estado não criptografado existente é uma operação unidirecional por chave. Planeje o rollout cuidadosamente — documente o ARN da sua chave e garanta que vários membros da equipe tenham acesso ao KMS antes de habilitar.

Avaliação antecipada de variáveis (1.8+): As variáveis agora podem ser usadas nos blocos backend e provider, eliminando a necessidade de soluções alternativas de configuração parcial de backend.

Isolamento de workspaces: Os workspaces de CLI compartilham o mesmo bucket de backend mas usam chaves de estado diferentes. Eles NÃO fornecem isolamento de credenciais de nuvem, funções IAM ou configurações de provedor.

Resumo

  • O OpenTofu foi bifurcado do Terraform 1.5.7 em agosto de 2023 após a mudança de licença BSL da HashiCorp, e agora é um projeto da Linux Foundation sob MPL 2.0
  • É um substituto direto do Terraform 1.5.x — mesmo HCL, mesmos provedores, mesmo formato de estado; a migração requer apenas substituir tofu por terraform nos comandos
  • A criptografia de estado do lado do cliente (AES-GCM, AWS KMS, GCP KMS) é o recurso novo mais significativo do OpenTofu — indisponível no Terraform OSS
  • A avaliação antecipada de variáveis (1.8+) permite variáveis nos blocos backend e provider, eliminando muitas soluções alternativas de configuração parcial
  • Instale via apt, dnf, brew, asdf, Docker ou a action do GitHub setup-opentofu
  • A integração CI/CD é direta: substitua terraform por tofu, use OIDC para autenticação em nuvem e siga o fluxo plan → revisão → apply

Artigos Relacionados