Infrastructure as Code avec OpenTofu (compatible Terraform) et Ansible
Quitter

Leçon 1 sur 10 · Fondamentaux

L'infrastructure as code : pourquoi, avec quels outils

30 min Debian 12

Objectif

Comprendre ce que signifie « décrire son infrastructure en code », ce que cela change au quotidien pour une équipe, et situer les principaux outils : OpenTofu et Terraform, Ansible, Pulumi, CloudFormation. Vous écrirez ensuite votre toute première configuration OpenTofu.

L'essentiel

  • L'infrastructure as code (IaC) consiste à décrire réseaux, serveurs, pare-feu, bases de données ou enregistrements DNS dans des fichiers texte, versionnés dans Git, puis à laisser un outil les créer et les maintenir.
  • Une approche déclarative décrit l'état voulu (« trois serveurs web ») ; l'outil calcule lui-même les actions. Une approche impérative décrit les étapes (« crée un serveur, puis un deuxième… »).
  • On distingue le provisionnement (créer les ressources : OpenTofu, Terraform, CloudFormation, Pulumi) et la gestion de configuration (installer et régler les logiciels dans les machines : Ansible, Puppet, Chef).
  • OpenTofu est un dérivé libre de Terraform, créé en 2023 après le changement de licence de Terraform ; il en garde le langage (HCL) et la quasi-totalité des commandes.
  • Un outil déclaratif est idempotent : relancé dix fois, il ne fait des changements que s'il y a un écart entre le code et la réalité.

Le problème : l'infrastructure faite à la main

Imaginez une agence web de Casablanca qui héberge les sites de vingt clients. Depuis cinq ans, chaque serveur a été créé à la main dans la console du fournisseur : un clic pour la machine, un autre pour le pare-feu, une règle ajoutée « temporairement » un soir de panne.

Résultat :

  • personne ne sait exactement comment le serveur du client principal est configuré ; l'administrateur qui l'a monté est parti ;
  • créer un environnement de test identique à la production prend deux jours, et il n'est jamais vraiment identique ;
  • après un incident (suppression accidentelle, piratage), reconstruire prend une semaine ;
  • les changements ne sont pas relus : une règle de pare-feu ouverte à tout Internet passe inaperçue.

On parle de serveurs « flocons de neige » (snowflake servers) : chacun est unique et impossible à reproduire.

La solution : tout décrire en fichiers

# reseau.tf — un extrait de ce que vous écrirez dans cette formation
resource "aws_security_group" "web" {
  name = "web-client-atlas"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Ce que l'on gagne :

Avant (à la main) Après (IaC)
La documentation est fausse ou absente Le code est la documentation
Un changement = un clic invisible Un changement = un commit relu par un collègue
Le test ne ressemble pas à la production Le même code crée test et production
Reconstruire prend des jours tofu apply recrée tout en minutes
« Qui a ouvert ce port ? » git log répond, avec la date et la raison

L'IaC applique à l'infrastructure les pratiques du développement logiciel : gestion de versions, revue de code, tests, intégration continue.

Déclaratif ou impératif

Comparons deux façons de demander trois serveurs web.

Approche impérative, un script :

# creer-serveurs.sh — chaque lancement CRÉE trois serveurs de plus
for i in 1 2 3; do
  fournisseur-cli server create --name "web-$i" --type petit --image debian-12
done

Si vous lancez ce script deux fois, vous avez six serveurs. S'il échoue au deuxième, il faut nettoyer à la main. Pour passer de trois à cinq serveurs, il faut écrire un autre script.

Approche déclarative, OpenTofu :

resource "fournisseur_server" "web" {
  count = 3
  name  = "web-${count.index + 1}"
  type  = "petit"
  image = "debian-12"
}

Vous décrivez le résultat. Au premier lancement, OpenTofu crée trois serveurs. Au deuxième, il ne fait rien : la réalité correspond déjà au code. Si vous écrivez count = 5, il en crée deux. Si vous écrivez count = 2, il en supprime un. C'est l'outil qui calcule la différence.

Pour cela, OpenTofu garde un état (state) : la liste de ce qu'il a créé, avec les identifiants réels chez le fournisseur. Vous l'étudierez en détail dans la leçon 2.1.

Le paysage des outils

Outil Catégorie Langage Cibles Licence
OpenTofu provisionnement déclaratif HCL tout fournisseur ayant une API (AWS, Azure, GCP, OVHcloud, Scaleway, Proxmox, Kubernetes, DNS…) MPL 2.0 (libre), fondation Linux
Terraform provisionnement déclaratif HCL les mêmes BUSL 1.1 depuis la version 1.6 (2023)
Ansible gestion de configuration, orchestration YAML (playbooks) les systèmes (Linux, Windows, réseau), par SSH, sans agent GPL v3
Pulumi provisionnement déclaratif Python, TypeScript, Go, C#… tout fournisseur Apache 2.0 (moteur)
CloudFormation provisionnement déclaratif YAML ou JSON AWS uniquement service AWS
Bicep / ARM provisionnement déclaratif Bicep, JSON Azure uniquement service Microsoft
Puppet, Chef gestion de configuration DSL propres les systèmes, avec agent variées
cloud-init configuration au premier démarrage YAML une machine virtuelle neuve Apache 2.0 / GPL v3

Quelques repères pour choisir :

  • Plusieurs fournisseurs ou un fournisseur local (OVHcloud, un hébergeur marocain, Proxmox) : OpenTofu ou Terraform, grâce à leurs milliers de providers.
  • Tout chez AWS et une équipe qui veut rester dans l'écosystème : CloudFormation est possible, mais vous serez enfermé chez AWS.
  • Une équipe de développeurs qui préfère un vrai langage de programmation (boucles, tests unitaires) : Pulumi.
  • Configurer ce qu'il y a dans les machines (paquets, fichiers, services) : Ansible. On le combine très souvent avec OpenTofu (leçon 3.1) : OpenTofu crée les machines, Ansible les configure.

OpenTofu n'est pas un outil de gestion de configuration : il crée et supprime des ressources, mais n'installe pas nginx dans une machine (il peut seulement transmettre un script de démarrage, cloud-init par exemple).

OpenTofu et Terraform : un peu d'histoire

  • 2014 : HashiCorp publie Terraform sous licence libre MPL 2.0. Il devient l'outil de référence de l'IaC multi-cloud.
  • Août 2023 : HashiCorp passe ses produits, dont Terraform à partir de la version 1.6, sous Business Source License (BUSL 1.1). Le code reste lisible, mais certains usages concurrents de HashiCorp ne sont plus autorisés. Des entreprises et des contributeurs lancent alors un dérivé du code MPL, d'abord appelé OpenTF.
  • Septembre 2023 : le projet rejoint la Linux Foundation sous le nom OpenTofu.
  • Janvier 2024 : sortie d'OpenTofu 1.6, première version stable, compatible avec Terraform 1.5/1.6.
  • Depuis : les deux projets évoluent séparément. OpenTofu ajoute ses propres fonctions (chiffrement de l'état, enabled dans lifecycle, fichiers .tofu…), Terraform les siennes. HashiCorp a par ailleurs été racheté par IBM (opération finalisée en 2025).

En pratique, pour cette formation :

OpenTofu Terraform
Commande tofu init, tofu plan, tofu apply terraform init, terraform plan, terraform apply
Langage HCL, fichiers .tf (et .tofu) HCL, fichiers .tf
Bloc de réglages terraform { … } (même nom, par compatibilité) terraform { … }
Registre public registry.opentofu.org registry.terraform.io
Fournisseurs les mêmes (hashicorp/aws, hashicorp/local…) les mêmes

Ce que vous apprenez ici sert donc aussi sur un projet Terraform existant. Passer d'un projet Terraform récent à OpenTofu demande en général de sauvegarder l'état, d'installer tofu, puis de lancer tofu init et un tofu plan qui ne doit montrer aucun changement.

Le flux de travail d'OpenTofu

   écrire (*.tf)  ──▶  tofu init  ──▶  tofu plan  ──▶  revue  ──▶  tofu apply
        ▲              télécharge      calcule les      (vous,      applique les
        │              les providers   différences      un collègue) changements
        └──────────────── git commit, push, merge request ◀───────────────┘
  1. Écrire : vous décrivez les ressources dans des fichiers .tf.
  2. Planifier : tofu plan compare le code, l'état et la réalité, puis affiche ce qui serait créé (+), modifié (~) ou détruit (-).
  3. Appliquer : tofu apply exécute le plan, après votre confirmation.

La leçon suivante détaille ces commandes.

Votre premier fichier

Le type de ressource terraform_data est fourni par OpenTofu lui-même, sans aucun téléchargement : il ne crée rien chez un fournisseur, il garde simplement une valeur dans l'état. C'est parfait pour apprendre.

# /root/iac/premier/main.tf
resource "terraform_data" "bonjour" {
  input = "Bonjour depuis Rabat"
}
# /root/iac/premier/outputs.tf
output "message" {
  value = terraform_data.bonjour.output
}
cd /root/iac/premier
tofu init          # aucun fournisseur à télécharger ici
tofu apply         # répondez « yes »
# Outputs:
# message = "Bonjour depuis Rabat"

Et ce qui ne va pas dans Git :

# .gitignore (dans ce fichier, un commentaire occupe toute la ligne)
# fournisseurs téléchargés, recréés par tofu init
.terraform/
# l'état peut contenir des secrets : il va dans un backend distant
*.tfstate
# ses sauvegardes (terraform.tfstate.backup)
*.tfstate.*
crash.log
# plans enregistrés
*.tfplan

Le fichier .terraform.lock.hcl, lui, doit être validé : il fige les versions exactes des fournisseurs pour toute l'équipe.

Pièges fréquents

  • Mélanger le clic et le code : une modification faite à la main dans la console sera annulée (ou provoquera une erreur) au prochain tofu apply. Une fois en IaC, tout passe par le code.
  • Versionner l'état (terraform.tfstate) dans Git : il peut contenir des mots de passe en clair, et deux personnes l'écrasent mutuellement.
  • Croire qu'OpenTofu configure les logiciels dans les machines : pour cela, Ansible ou cloud-init.
  • Se lancer sans plan : un apply sans lire le plan peut détruire une base de données parce qu'un argument a changé.

Lab

Le conteneur de lab contient OpenTofu mais n'a pas d'accès réseau : vous écrivez des fichiers, la correction les relit. La ressource terraform_data ne demande aucun téléchargement : vous pouvez même essayer tofu init puis tofu apply -auto-approve dans le dossier pour voir la sortie.

  1. une première ressource terraform_data ;
  2. une sortie qui affiche sa valeur ;
  3. le bloc terraform qui exige une version minimale, avec des fichiers bien formatés (tofu fmt) ;
  4. le .gitignore d'un projet OpenTofu.

Pour écrire un fichier sans éditeur : cat > main.tf <<'EOF' … EOF.

Quiz

  1. Quelle est la différence entre une approche déclarative et une approche impérative ?
  2. Vous passez count = 3 à count = 5 et relancez OpenTofu. Que se passe-t-il ?
  3. OpenTofu ou Ansible : lequel crée la machine virtuelle, lequel installe nginx dedans ?
  4. Pourquoi OpenTofu existe-t-il, et que garde-t-il de Terraform ?
  5. Faut-il valider dans Git terraform.tfstate ? Et .terraform.lock.hcl ?
Réponses
  1. Déclaratif : on décrit l'état final voulu et l'outil calcule les actions. Impératif : on écrit la suite des actions à exécuter.
  2. OpenTofu compare le code à l'état, voit qu'il manque deux instances et en crée deux, sans toucher aux trois existantes.
  3. OpenTofu crée la machine (provisionnement) ; Ansible installe et configure nginx dedans (gestion de configuration).
  4. Il a été créé en 2023, sous la Linux Foundation, après le passage de Terraform sous licence BUSL ; il garde le langage HCL, les commandes (avec tofu au lieu de terraform) et les fournisseurs.
  5. Non pour l'état : il peut contenir des secrets et doit être partagé via un backend distant avec verrouillage. Oui pour .terraform.lock.hcl, qui fige les versions des fournisseurs pour toute l'équipe.

Sources de référence : documentation OpenTofu (MPL 2.0). Texte original MasterLinux.

Exercices pratiques

À réaliser sur Debian 12

Le terminal en ligne ouvre bientôt. En attendant, réalisez ces tâches sur votre machine Linux, une machine virtuelle ou WSL.

  1. Écrivez /root/iac/premier/main.tf : une ressource de type terraform_data nommée bonjour, dont l'argument input vaut "Bonjour depuis Rabat"
    Afficher un indiceresource "<type>" "<nom>" { argument = valeur } — sur trois lignes, l'argument indenté de deux espaces.
    Voir la solution
    printf '%s\n' 'resource "terraform_data" "bonjour" {' '  input = "Bonjour depuis Rabat"' '}' > /root/iac/premier/main.tf

    Vérification : f=/root/iac/premier/main.tf; grep -Eq '^resource +"terraform_data" +"bonjour" *[{] *$' $f && grep -Eq '^ +input *= *"Bonjour depuis Rabat" *$' $f && grep -Eq "^[}] *$" $f

  2. Écrivez /root/iac/premier/outputs.tf : une sortie (output) nommée message dont la valeur est l'attribut output de la ressource terraform_data.bonjour
    Afficher un indiceoutput "message" { value = <type>.<nom>.<attribut> }
    Voir la solution
    printf '%s\n' 'output "message" {' '  value = terraform_data.bonjour.output' '}' > /root/iac/premier/outputs.tf

    Vérification : f=/root/iac/premier/outputs.tf; grep -Eq '^output +"message" *[{] *$' $f && grep -Eq '^ +value *= *terraform_data\.bonjour\.output *$' $f

  3. Écrivez /root/iac/premier/versions.tf : un bloc terraform qui exige une version d'OpenTofu supérieure ou égale à 1.6.0 (required_version). Vos trois fichiers doivent être bien formatés : tofu fmt -check /root/iac/premier ne doit rien signaler
    Afficher un indiceLe bloc s'appelle bien terraform, même avec OpenTofu. Deux espaces d'indentation, une espace de chaque côté du signe égal.
    Voir la solution
    printf '%s\n' 'terraform {' '  required_version = ">= 1.6.0"' '}' > /root/iac/premier/versions.tf

    Vérification : f=/root/iac/premier/versions.tf; grep -Eq "^terraform *[{] *$" $f && grep -Eq '^ +required_version *= *">= *1\.6(\.0)?" *$' $f && { ! command -v tofu >/dev/null 2>&1 || tofu fmt -check /root/iac/premier >/dev/null 2>&1; }

  4. Écrivez /root/iac/premier/.gitignore pour ne jamais versionner le dossier .terraform/ ni les fichiers d'état (*.tfstate et *.tfstate.*), mais SANS ignorer le fichier de verrouillage .terraform.lock.hcl
    Afficher un indiceUne ligne par motif. Le fichier .terraform.lock.hcl, lui, se valide dans Git.
    Voir la solution
    printf '%s\n' '.terraform/' '*.tfstate' '*.tfstate.*' 'crash.log' '*.tfplan' > /root/iac/premier/.gitignore

    Vérification : f=/root/iac/premier/.gitignore; grep -Eq "^(\*\*/)?\.terraform/?$" $f && grep -Eq "^\*\.tfstate$" $f && grep -Eq "^\*\.tfstate\.\*$" $f && ! grep -q "lock" $f

Références officielles consultées : OpenTofu — Getting started — https://opentofu.org/docs/intro/ ; OpenTofu — OpenTofu vs. Chef, Puppet, etc. — https://opentofu.org/docs/intro/vs/chef-puppet/ ; OpenTofu — OpenTofu vs. CloudFormation, Heat, etc. — https://opentofu.org/docs/intro/vs/cloudformation/ ; OpenTofu — Migrating to OpenTofu — https://opentofu.org/docs/intro/migration/ ; OpenTofu — Use cases — https://opentofu.org/docs/intro/use-cases/. Texte original MasterLinux.