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 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é | OpenTofu | Terraform OSS |
|---|---|---|
| Syntaxe HCL | Identique à TF 1.5 | Identique |
| Écosystème de fournisseurs | registry.opentofu.org + fallback terraform.io | registry.terraform.io |
| Format du fichier d’état | .tfstate binaire compatible | Même format |
.terraform.lock.hcl | Fonctionne sans modification | Identique |
| Commandes du binaire | tofu remplace terraform 1:1 | terraform |
| Chiffrement d’état | Oui (AES-GCM, KMS) | Non |
| Évaluation anticipée des variables | Oui (1.8+) | Non |
| Fonctions définies par fournisseur | Oui (1.8+) | Non |
Bloc removed | Oui (1.7+) | Partiel |
| Terraform Cloud | Incompatible | Natif |
Le coût pratique de migration pour la plupart des équipes est un chercher-remplacer de terraform → tofu 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é | OpenTofu | Terraform OSS | Terraform Cloud | Pulumi | Crossplane | CDK for TF |
|---|---|---|---|---|---|---|
| Licence | MPL 2.0 | BSL 1.1 | Propriétaire | Apache 2.0 | Apache 2.0 | MPL 2.0 |
| Langage | HCL | HCL | HCL | Python/TS/Go | YAML/Go | Python/TS/Java |
| Chiffrement d’état | Oui (intégré) | Non | Oui (géré) | Oui (géré) | N/A | Non |
| Évaluation anticipée vars | Oui (1.8+) | Non | Non | N/A | N/A | N/A |
| Écosystème fournisseurs | Fournisseurs Terraform | Fournisseurs Terraform | Fournisseurs Terraform | Fournisseurs Pulumi + pont TF | CRDs Kubernetes | Fournisseurs Terraform |
| Courbe d’apprentissage | Faible (HCL) | Faible (HCL) | Faible | Moyenne (vrai code) | Élevée (CRDs K8s) | Moyenne |
| Idéal pour | IaC open-source | Petites équipes acceptant BSL | Équipes voulant un backend géré | Développeurs préférant le code | Équipes natives Kubernetes | Dé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àterraformdans 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
backendetprovider, éliminant de nombreux contournements de configuration partielle - Installez via
apt,dnf,brew,asdf, Docker ou l’action GitHubsetup-opentofu - L’intégration CI/CD est simple : remplacez
terraformpartofu, utilisez OIDC pour l’authentification cloud et suivez le flux plan → révision → apply
Articles Connexes
- Introduction à Terraform : Infrastructure as Code
- Ansible Playbooks et Rôles : Guide Complet d’Automatisation d’Infrastructure
- Ansible pour Débutants : Automatiser la Configuration des Serveurs Sans Agent
- Docker Compose : Définir et Exécuter des Applications Multi-Conteneurs
- GitHub Actions : Guide Complet d’Automatisation CI/CD