Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Comprendre le state Terraform

12 min de lecture

logo terraform

Terraform a besoin de savoir ce qui existe déjà avant de décider quoi créer, modifier ou supprimer. Le state est le fichier qui lui sert de mémoire : sans lui, Terraform considère que rien n’existe et tente de tout recréer. Ce guide explique ce qu’est le state, ce qu’il contient, et pourquoi le protéger est essentiel.

Quand vous lancez terraform apply, Terraform compare votre code (ce que vous voulez) avec le state (ce qui existe). La différence entre les deux produit le plan — la liste des actions à effectuer. Si le state est perdu ou corrompu, ce calcul devient impossible : Terraform ne peut plus distinguer une création d’une modification.

Prérequis : avoir suivi Première infrastructure ou avoir créé au moins une ressource avec terraform apply.

  • Ce qu’est le state et pourquoi Terraform en a besoin
  • Ce que contient le fichier terraform.tfstate (structure JSON)
  • Comment le state évolue à chaque apply (serial, backup automatique)
  • Ce qui se passe quand le state est perdu
  • Les règles essentielles pour protéger votre state

Le state est un fichier JSON nommé terraform.tfstate qui enregistre l’état réel de votre infrastructure. Chaque ressource créée par Terraform y est décrite avec ses attributs actuels : identifiant, nom, chemin, taille, configuration réseau…

En une phrase : le state fait le lien entre votre code HCL et les objets réels (VMs, disques, réseaux) qui existent sur l’hyperviseur ou le cloud.

Terraform est déclaratif : vous décrivez l’état final souhaité, et il calcule les actions nécessaires. Pour ce calcul, il a besoin de trois informations :

InformationSourceExemple
Ce que vous voulezVotre code HCL (.tf)name = "ma-vm.qcow2"
Ce qui existeLe fichier stateid = "/var/lib/libvirt/images/ma-vm.qcow2"
Ce qu’il faut faireLe plan (calculé)No changes ou 1 to add

Sans le state, Terraform ne dispose que de votre code. Il ne peut pas savoir si la VM existe déjà ou non. Résultat : il essaie de tout recréer — et échoue souvent parce que les ressources existent déjà.

Pour observer le state en action, créez un projet minimal avec un seul volume :

versions.tf
terraform {
required_version = ">= 1.11.0"
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
version = "~> 0.8"
}
}
}
provider "libvirt" {
uri = "qemu:///system"
}
main.tf
resource "libvirt_volume" "disk" {
name = "state-demo.qcow2"
pool = "default"
target = { format = { type = "qcow2" } }
create = { content = { url = "/chemin/vers/ubuntu-24.04-cloudimg.img" } }
}
outputs.tf
output "disk_path" {
description = "Chemin du volume sur l'hôte"
value = libvirt_volume.disk.path
}
output "disk_name" {
description = "Nom du volume"
value = libvirt_volume.disk.name
}

Appliquez :

Fenêtre de terminal
terraform init
terraform apply -auto-approve

Résultat :

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
disk_name = "state-demo.qcow2"
disk_path = "/var/lib/libvirt/images/state-demo.qcow2"

Un fichier terraform.tfstate est apparu dans le répertoire. C’est le state.

Le state est un fichier JSON lisible. Voici sa structure simplifiée après la création du volume :

{
"version": 4,
"terraform_version": "1.14.3",
"serial": 2,
"lineage": "cedddae6-a296-...",
"outputs": {
"disk_name": {
"value": "state-demo.qcow2",
"type": "string"
},
"disk_path": {
"value": "/var/lib/libvirt/images/state-demo.qcow2",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "libvirt_volume",
"name": "disk",
"provider": "provider[\"registry.terraform.io/dmacvicar/libvirt\"]",
"instances": [
{
"attributes": {
"id": "/var/lib/libvirt/images/state-demo.qcow2",
"name": "state-demo.qcow2",
"pool": "default",
"capacity": 3758096384
}
}
]
}
]
}
ChampRôleExemple
versionVersion du format du state4 (stable depuis Terraform 0.12)
terraform_versionVersion de Terraform utilisée"1.14.3"
serialCompteur incrémenté à chaque modification234
lineageIdentifiant unique du state (UUID)"cedddae6-a296-..."
outputsValeurs des blocs output {}disk_path, disk_name
resourcesListe des ressources gérées avec leurs attributs réelslibvirt_volume.disk

Le state n’est pas figé. Il change à chaque apply qui modifie l’infrastructure ou les outputs.

  1. Premier apply : le state est créé avec serial: 1 (ou 2 selon le provider).

  2. Apply suivant avec changement : Terraform écrit le nouveau state avec un serial incrémenté. L’ancien state est sauvegardé dans terraform.tfstate.backup.

  3. Apply sans changement : le state ne change pas, le serial reste identique.

Vérifiez par vous-même :

Fenêtre de terminal
# Après le premier apply
ls -lh terraform.tfstate terraform.tfstate.backup
-rw-rw-r-- 1 bob bob 1,9K mars 31 13:33 terraform.tfstate
-rw-rw-r-- 1 bob bob 1,9K mars 31 13:33 terraform.tfstate.backup

Le backup contient l’état précédent. Si un apply corrompt le state, vous pouvez restaurer le backup.

C’est la démonstration la plus parlante. Supprimez temporairement le state et lancez un plan :

Fenêtre de terminal
mv terraform.tfstate terraform.tfstate.sauvegarde
terraform plan

Résultat — Terraform veut tout recréer :

Terraform will perform the following actions:
# libvirt_volume.disk will be created
+ resource "libvirt_volume" "disk" {
+ name = "state-demo.qcow2"
+ pool = "default"
...
}
Plan: 1 to add, 0 to change, 0 to destroy.

Le volume existe toujours sur l’hyperviseur, mais Terraform ne le sait plus. Si vous appliquez ce plan, il tentera de créer un doublon — et échouera probablement.

Restaurez le state :

Fenêtre de terminal
mv terraform.tfstate.sauvegarde terraform.tfstate
terraform plan
No changes. Your infrastructure matches the configuration.

Terraform retrouve sa mémoire. Le plan est vide.

Vous n’avez pas besoin d’ouvrir le fichier JSON directement. Terraform fournit des commandes dédiées :

Fenêtre de terminal
# Lister toutes les ressources du state
terraform state list
libvirt_volume.disk
Fenêtre de terminal
# Voir les détails d'une ressource
terraform state show libvirt_volume.disk
# libvirt_volume.disk:
resource "libvirt_volume" "disk" {
allocation = 629989376
capacity = 3758096384
id = "/var/lib/libvirt/images/state-demo.qcow2"
name = "state-demo.qcow2"
path = "/var/lib/libvirt/images/state-demo.qcow2"
pool = "default"
target = {
format = {
type = "qcow2"
}
path = "/var/lib/libvirt/images/state-demo.qcow2"
}
}

Le state enregistre tous les attributs des ressources — y compris les mots de passe, clés SSH et tokens que le provider renvoie. Un terraform.tfstate non protégé est un risque de sécurité.

Donnée sensibleComment elle se retrouve dans le state
Mot de passe base de donnéesAttribut password d’une ressource DB
Clé SSH privéeAttribut private_key d’un tls_private_key
Token APIAttribut token d’un random_password

Règles de base :

  • Ne jamais commiter terraform.tfstate dans Git
  • Ajouter *.tfstate et *.tfstate.backup dans .gitignore
  • Pour un vrai projet, utiliser un backend distant avec chiffrement

Ajoutez ces entrées à votre .gitignore dès le premier terraform init :

# Terraform state — contient des données sensibles
*.tfstate
*.tfstate.backup
*.tfstate.*.backup
# Répertoire de travail Terraform
.terraform/
# Fichiers de variables sensibles
*.tfvars
!example.tfvars
SymptômeCause probableSolution
terraform plan veut tout recréerState absent ou corrompuVérifier terraform.tfstate, restaurer le backup
Error: resource already existsState perdu mais ressource toujours présenteterraform import pour réassocier
serial ne correspond pasDeux apply simultanésUtiliser un backend distant avec verrouillage
State très volumineuxTrop de ressources dans un seul projetDécouper en plusieurs projets/stacks
  • Le state (terraform.tfstate) est la mémoire de Terraform : il fait le lien entre votre code et l’infrastructure réelle
  • Sans state, Terraform considère que rien n’existe et tente de tout recréer
  • Le serial s’incrémente à chaque modification — c’est un mécanisme de protection contre les modifications concurrentes
  • Le backup (terraform.tfstate.backup) contient l’état précédent — c’est votre filet de sécurité immédiat
  • Le state peut contenir des données sensibles : ne jamais le commiter dans Git
  • Utilisez terraform state list et terraform state show pour inspecter le state — pas l’éditeur de texte

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn