TL;DR — Résumé Rapide

OpenTofu est le fork open-source de Terraform de la Linux Foundation. Installation, migration, chiffrement d'état, syntaxe HCL et intégration CI/CD.

OPENTOFU — INFRASTRUCTURE AS CODE OPEN-SOURCE Terraform (BSL) HashiCorp / IBM Changement licence août 2023 Fork OpenTofu (MPL 2.0) Linux Foundation registry.opentofu.org Chiffrement d'état AES-GCM / AWS KMS / GCP KMS Évaluation anticipée des vars vars dans provider / backend Fonctions de fournisseurs fonctions HCL personnalisées Pipeline CI/CD setup-opentofu Action tofu plan → approbation tofu apply authentification OIDC AWS / Azure / GCP sans identifiants longue durée Remplacement direct de Terraform · MPL 2.0 · Linux Foundation · tofu remplace terraform partout

OpenTofu est le fork open-source de Terraform maintenu sous la Linux Foundation, créé après que HashiCorp ait changé la licence de Terraform de Mozilla Public License 2.0 vers la Business Source License (BSL) en août 2023. Ce guide couvre tout ce dont vous avez besoin pour comprendre les origines d’OpenTofu, l’installer, migrer des projets Terraform existants sans friction, maîtriser les fondamentaux de HCL, gérer l’état de manière sécurisée avec le chiffrement côté client et l’intégrer dans des pipelines CI/CD modernes.

Pourquoi OpenTofu Existe : L’Histoire du Fork de Licence

Terraform était open-source sous MPL 2.0 pendant plus de neuf ans. Le 10 août 2023, HashiCorp a annoncé que Terraform 1.6 et toutes les versions futures seraient publiées sous la Business Source License (BSL 1.1) — une licence de code source disponible qui restreint l’utilisation du logiciel pour concurrencer HashiCorp commercialement.

La réponse de la communauté fut rapide. En quelques jours, des ingénieurs de Spacelift, Gruntwork, Env0, Harness, Scalr et d’autres ont signé une lettre ouverte et créé le fork OpenTofu à partir de la dernière version MPL 2.0 (Terraform 1.5.7). La Linux Foundation a accepté OpenTofu comme projet en septembre 2023, et OpenTofu 1.6.0 — la première version stable avec de nouvelles fonctionnalités — est sorti en janvier 2024.

Implications clés du changement de licence :

  • Terraform OSS est désormais BSL — vous ne pouvez pas construire un produit concurrent avec lui
  • OpenTofu reste en MPL 2.0 — entièrement open-source, sans restrictions commerciales
  • HashiCorp (maintenant IBM) contrôle Terraform Cloud et Terraform Enterprise
  • OpenTofu est gouverné par la communauté, avec un Comité de Pilotage Technique et un processus RFC ouvert

Compatibilité OpenTofu vs Terraform

OpenTofu 1.6–1.9 cible la compatibilité directe avec Terraform 1.5.x :

FonctionnalitéOpenTofuTerraform OSS
Syntaxe HCLIdentique à TF 1.5Identique
Écosystème de fournisseursregistry.opentofu.org + fallback terraform.ioregistry.terraform.io
Format du fichier d’état.tfstate binaire compatibleMême format
.terraform.lock.hclFonctionne sans modificationIdentique
Commandes du binairetofu remplace terraform 1:1terraform
Chiffrement d’étatOui (AES-GCM, KMS)Non
Évaluation anticipée des variablesOui (1.8+)Non
Fonctions définies par fournisseurOui (1.8+)Non
Bloc removedOui (1.7+)Partiel
Terraform CloudIncompatibleNatif

Le coût pratique de migration pour la plupart des équipes est un chercher-remplacer de terraformtofu dans les scripts CI. Les fichiers HCL, fournisseurs, modules et fichiers d’état ne sont pas modifiés.

Installation

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

Migration depuis Terraform

Étape 1 — Installer OpenTofu aux côtés de Terraform

Les deux binaires peuvent coexister. tofu et terraform sont des exécutables séparés.

Étape 2 — Exécuter tofu init dans votre projet existant

cd mon-projet-terraform/
tofu init

OpenTofu lit le même bloc versions.tf / required_providers. Il télécharge les fournisseurs depuis registry.opentofu.org. Votre .terraform.lock.hcl est réutilisé tel quel.

Étape 3 — Remplacer terraform par tofu dans les scripts CI

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

# Après (sans changement de logique)
tofu fmt -check
tofu init -input=false
tofu plan -out=tfplan
tofu apply -auto-approve tfplan

Étape 4 — Vérifier la compatibilité d’état

Le format JSON .tfstate est identique. Si vous gérez l’état distant (S3, GCS, Azure Blob), aucune migration n’est nécessaire. Exécutez un plan avec OpenTofu : il devrait afficher aucun changement si l’infrastructure correspond à l’état existant.

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

Fondamentaux de HCL

Fournisseurs, Ressources et Sources de Données

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"]
  }
}

Variables, Locaux et Outputs

variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "L'environnement doit être dev, staging ou prod."
  }
}

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

output "vpc_id" {
  description = "ID du VPC créé"
  value       = aws_vpc.main.id
}

count et 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}-public-${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 })
}

Blocs dynamiques

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

  dynamic "ingress" {
    for_each = var.regles_entree
    content {
      from_port   = ingress.value.port
      to_port     = ingress.value.port
      protocol    = ingress.value.protocole
      cidr_blocks = ingress.value.cidrs
      description = ingress.value.description
    }
  }
}

Gestion de l’État

Backends distants

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

Chiffrement d’État Côté Client (exclusif à OpenTofu)

# AWS KMS (recommandé pour la production)
terraform {
  encryption {
    key_provider "aws_kms" "cle_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" "methode_prod" {
      keys = key_provider.aws_kms.cle_prod
    }

    state {
      method = method.aes_gcm.methode_prod
    }

    plan {
      method = method.aes_gcm.methode_prod
    }
  }
}

Commandes d’état utiles

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

Modules

# Chemin 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"
}

# Registre 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
}

Espaces de Travail (Workspaces)

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

Intégration CI/CD

GitHub Actions avec OIDC

name: OpenTofu Plan et 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: Configurer OpenTofu
        uses: opentofu/setup-opentofu@v1
        with:
          tofu_version: "1.9.0"

      - name: Configurer les identifiants 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

Tableau Comparatif des Outils

FonctionnalitéOpenTofuTerraform OSSTerraform CloudPulumiCrossplaneCDK for TF
LicenceMPL 2.0BSL 1.1PropriétaireApache 2.0Apache 2.0MPL 2.0
LangageHCLHCLHCLPython/TS/GoYAML/GoPython/TS/Java
Chiffrement d’étatOui (intégré)NonOui (géré)Oui (géré)N/ANon
Évaluation anticipée varsOui (1.8+)NonNonN/AN/AN/A
Écosystème fournisseursFournisseurs TerraformFournisseurs TerraformFournisseurs TerraformFournisseurs Pulumi + pont TFCRDs KubernetesFournisseurs Terraform
Courbe d’apprentissageFaible (HCL)Faible (HCL)FaibleMoyenne (vrai code)Élevée (CRDs K8s)Moyenne
Idéal pourIaC open-sourcePetites équipes acceptant BSLÉquipes voulant un backend géréDéveloppeurs préférant le codeÉquipes natives KubernetesDéveloppeurs n’aimant pas HCL

Exemple Pratique : Infrastructure 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}-public-${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.actuel.min
  max_size            = local.actuel.max

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

output "dns_alb" {
  description = "Nom DNS de l'Application Load Balancer"
  value       = aws_lb.main.dns_name
}

Pièges et Cas Particuliers

Repli du registre de fournisseurs : OpenTofu vérifie registry.opentofu.org en premier. Si un fournisseur n’est disponible que sur registry.terraform.io, ajoutez un source explicite dans required_providers.

Migration du chiffrement d’état : Activer le chiffrement sur un fichier d’état non chiffré existant est une opération unidirectionnelle par clé. Planifiez le déploiement soigneusement — documentez l’ARN de votre clé et assurez-vous que plusieurs membres de l’équipe aient accès à KMS avant d’activer.

Évaluation anticipée des variables (1.8+) : Les variables peuvent désormais être utilisées dans les blocs backend et provider, éliminant le besoin de contournements de configuration partielle de backend dans de nombreuses configurations.

Isolation des workspaces : Les workspaces CLI partagent le même bucket de backend mais utilisent des clés d’état différentes. Ils ne fournissent PAS d’isolation des identifiants cloud, des rôles IAM ou des configurations de fournisseur.

Résumé

  • OpenTofu a été forké de Terraform 1.5.7 en août 2023 suite au changement de licence BSL de HashiCorp, et est maintenant un projet de la Linux Foundation sous MPL 2.0
  • C’est un remplacement direct de Terraform 1.5.x — même HCL, mêmes fournisseurs, même format d’état ; la migration nécessite uniquement de substituer tofu à terraform dans les commandes
  • Le chiffrement d’état côté client (AES-GCM, AWS KMS, GCP KMS) est la nouvelle fonctionnalité la plus significative d’OpenTofu — indisponible dans Terraform OSS
  • L’évaluation anticipée des variables (1.8+) permet les variables dans les blocs backend et provider, éliminant de nombreux contournements de configuration partielle
  • Installez via apt, dnf, brew, asdf, Docker ou l’action GitHub setup-opentofu
  • L’intégration CI/CD est simple : remplacez terraform par tofu, utilisez OIDC pour l’authentification cloud et suivez le flux plan → révision → apply

Articles Connexes