
Par défaut, Terraform stocke le state dans un fichier local
(terraform.tfstate). C'est suffisant pour apprendre, mais en équipe on le
déplace vers un backend distant (S3, GCS, HCP…) pour partager le state et
le verrouiller. Le vrai sujet n'est pas « choisir un backend », c'est
comment le configurer proprement : le bloc backend a une contrainte
surprenante, et la migration a des pièges qui coûtent cher.
Les comportements mesurables de ce guide (messages d'init, résolution de la
configuration partielle, préservation du lineage) ont été rejoués sur
Terraform v1.15.4. Les arguments propres au backend S3 (use_lockfile,
skip_s3_checksum) reposent sur la doc officielle.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Pourquoi le bloc
backendn'accepte ni variable ni local - La configuration partielle et
-backend-config, un fichier par environnement - La migration du state :
-migrate-statecontre-reconfigure - Le verrouillage S3, opt-in, et la dépréciation de DynamoDB
- Le diagnostic :
.terraform/terraform.tfstate, et où fuitent les secrets
Le bloc backend n'accepte aucune valeur nommée
Section intitulée « Le bloc backend n'accepte aucune valeur nommée »C'est le piège central, et la doc est nette : « A backend block cannot refer to named values (like input variables, locals, or data source attributes). » Le bloc est lu très tôt, avant l'évaluation des variables. Vérifié sur 1.15.4, ceci échoue :
terraform { backend "local" { path = var.chemin # Error: Variables not allowed }}On ne peut donc pas paramétrer un backend par des variables. C'est la raison d'être de la configuration partielle.
La configuration partielle et -backend-config
Section intitulée « La configuration partielle et -backend-config »On laisse le bloc incomplet et on fournit le reste à l'init :
terraform { backend "local" {} # partiel : aucune valeur ici}Trois formes de -backend-config existent : un fichier (nommage recommandé
*.<backend>.tfbackend), une paire KEY=VALUE, ou la saisie interactive :
terraform init -backend-config=dev.local.tfbackendterraform init -backend-config="path=etat/dev/terraform.tfstate"Un fichier par environnement (dev, prod…) alimente le même bloc sans jamais
coder le chemin en dur. Sans ce mécanisme, un même dossier ne peut pas servir deux
environnements. Réinitialisé sans -backend-config, un bloc partiel résout ses
valeurs à null : c'est la preuve qu'il est bien partiel.
Le fichier .terraform/terraform.tfstate : votre diagnostic
Section intitulée « Le fichier .terraform/terraform.tfstate : votre diagnostic »Terraform enregistre le backend réellement retenu dans
.terraform/terraform.tfstate : backend.type, la backend.config résolue
et un hash. Ce n'est pas le state lui-même.
jq '.backend | {type, path: .config.path}' .terraform/terraform.tfstateC'est l'outil de diagnostic numéro un d'un problème de backend, et le seul moyen de
voir ce que -backend-config a produit. À noter : il n'existe pas tant que le
backend est le local implicite.
Migrer le state : -migrate-state contre -reconfigure
Section intitulée « Migrer le state : -migrate-state contre -reconfigure »Quand la configuration du backend change, un terraform init nu refuse de
tourner. Vérifié sur 1.15.4, message exact :
Error: Backend configuration changed
Either -reconfigure or -migrate-state must be supplied to update the backendconfiguration.Il n'y a donc aucun risque de perte silencieuse : c'est un arrêt franc qui vous force à choisir, en connaissance de cause, entre deux comportements opposés :
| Option | Ce qu'elle fait | Quand |
|---|---|---|
-migrate-state | copie le state existant vers le nouveau backend | déplacer un projet vivant |
-reconfigure | ignore le state de l'ancien backend, repart de zéro | changer sans rien emporter |
Une migration réussie conserve le lineage du state : c'est la preuve d'une
copie, pas d'un apply neuf (qui fabriquerait un lineage différent). Se tromper
d'option est une source classique de state perdu.
Pour une migration non interactive (en CI, objectif 3c), ajoutez
-force-copy, qui répond « yes » à la place de l'opérateur :
terraform init -migrate-state -force-copy -backend-config=dev.local.tfbackendLe verrouillage : opt-in sur S3, DynamoDB déprécié
Section intitulée « Le verrouillage : opt-in sur S3, DynamoDB déprécié »Un backend distant peut verrouiller le state pour éviter deux écritures
simultanées, mais ce n'est pas automatique partout. Sur le backend S3, « State
locking is an opt-in feature » : use_lockfile vaut false par défaut. Une
configuration S3 sans use_lockfile = true n'a donc aucun verrou, malgré ce
qu'on croit souvent.
L'ancien mécanisme par DynamoDB (dynamodb_table) est désormais déprécié :
« DynamoDB-based locking is deprecated and will be removed in a future minor
version. » Le chemin actuel est use_lockfile = true (verrou par fichier
.tflock dans le bucket).
Backends S3-compatibles (MinIO, Ceph…)
Section intitulée « Backends S3-compatibles (MinIO, Ceph…) »Le backend s3 fonctionne avec des stockages compatibles, mais « Support for S3
Compatible storage providers is offered as best effort ». Deux points utiles :
skip_s3_checksum = trueest destiné aux implémentations non AWS (« Useful for some S3-Compatible APIs »), avec les autresskip_*.regionest obligatoire, mais peut venir de l'environnement (AWS_REGION) comme les identifiants ; un serveur compatible l'accepte quelle qu'elle soit.
Mettre en pratique
Section intitulée « Mettre en pratique »Le lab backends fait passer un projet du backend local implicite à un backend
local paramétré : bloc partiel, -backend-config par environnement, et
migration prouvée par la préservation du lineage. Il se joue hors ligne,
sans compte cloud.
À retenir
Section intitulée « À retenir »- Le bloc
backendn'accepte aucune valeur nommée : d'où la configuration partielle et-backend-config, un fichier par environnement. - Un
initaprès changement de backend refuse : il faut choisir entre-migrate-state(copie) et-reconfigure(abandonne). - Une migration réussie conserve le
lineage;-force-copyla rend non interactive. - Le verrou S3 est opt-in (
use_lockfile = true) ; DynamoDB est déprécié. .terraform/terraform.tfstateporte la config résolue (et la fuite en clair) : c'est votre diagnostic.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous portent sur les pièges du backend : la variable qu'on ne peut pas utiliser, le choix entre migrer et reconfigurer, et le verrou qu'on croit actif. Chaque réponse donne la vérification correspondante.
Réponse courte
Non. Le blocbackend n'accepte ni var., ni local., ni data source.Détail
backend "local" { path = var.chemin } # Error: Variables not allowed
Le bloc est lu avant l'évaluation des variables. La réponse est la configuration partielle : un bloc incomplet, complété à l'init par -backend-config.Réponse courte
Configuration partielle + un fichier-backend-config par environnement.Détail
terraform init -backend-config=dev.local.tfbackend
terraform init -reconfigure -backend-config=prod.local.tfbackend
Le même bloc backend "local" {} résout sur dev ou prod selon le fichier passé. Sans -backend-config, il résout ses valeurs à null.Réponse courte
-migrate-state copie le state (lineage conservé) ; -reconfigure abandonne l'ancien state.Détail
| Option | Effet |
|---|---|
-migrate-state |
copie vers le nouveau backend |
-reconfigure |
ignore l'ancien, repart de zéro |
lineage : c'est la preuve d'une copie, pas d'un apply neuf. Se tromper d'option perd le state.Réponse courte
C'est volontaire :Backend configuration changed, il faut fournir -reconfigure ou -migrate-state.Détail
Error: Backend configuration changed
Either -reconfigure or -migrate-state must be supplied to update the
backend configuration.
Aucune perte silencieuse : Terraform s'arrête et vous force à choisir entre copier (-migrate-state) et abandonner (-reconfigure).Réponse courte
Non par défaut : sur S3, le verrou est opt-in (use_lockfile = true).Détail
« State locking is an opt-in feature of the S3 backend » :use_lockfile vaut false par défaut. Une config S3 sans cette ligne n'a aucun verrou. L'ancien dynamodb_table est déprécié (« will be removed in a future minor version ») ; utilisez use_lockfile = true.Réponse courte
Dans.terraform/terraform.tfstate : backend.type et la backend.config résolue.Détail
jq '.backend | {type, path: .config.path}' .terraform/terraform.tfstate
C'est le seul moyen de voir ce que -backend-config a produit (et le diagnostic n°1 d'un souci de backend). Il n'existe pas tant que le backend est le local implicite, et la config résolue y est en clair : passez les identifiants par l'environnement.Réponse courte
Avec-force-copy : terraform init -migrate-state -force-copy -backend-config=....Détail
-force-copy répond « yes » à la place de l'opérateur, ce qui rend la migration non interactive : indispensable en CI/CD (objectif 3c). Le lineage du state est conservé, comme dans une migration manuelle.Pour aller plus loin
Section intitulée « Pour aller plus loin »- terraform state mv : deplacer une ressource dans le state sans la detruire.
- Sauvegarder et restaurer le state Terraform : ce qui reste quand un backend distant est perdu.
- Variables par environnement : le pendant applicatif du
-backend-configpar environnement. - Backends : la reference officielle : la liste complete des arguments du backend S3.
- Backend pg : le backend PostgreSQL, et pourquoi il refuse
force-unlock.