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

Structure d'un projet Terraform

9 min de lecture

logo terraform

Un projet Terraform peut tenir dans un seul fichier main.tf. Mais dès qu’il dépasse quelques resources, la convention de découper en fichiers thématiques améliore radicalement la lisibilité. Cette page présente la structure standard, pourquoi elle existe, et comment l’appliquer dès le premier projet.

  • Une convention recommandée : versions.tf, main.tf, variables.tf, outputs.tf, terraform.tfvars
  • Le rôle de chaque fichier : ce qui va où et pourquoi
  • Le fichier .terraform.lock.hcl : à quoi il sert et pourquoi le commiter
  • Le .gitignore recommandé : ce qu’il ne faut jamais pousser dans Git
  • Répertoiremon-projet/
    • versions.tf (providers et contraintes de version)
    • main.tf (resources et data sources)
    • variables.tf (déclarations des variables)
    • outputs.tf (valeurs exposées après apply)
    • terraform.tfvars (valeurs des variables — ne pas commiter si sensible)

Terraform charge tous les fichiers .tf du répertoire courant. L’ordre n’a pas d’importance — il résout les dépendances automatiquement.

Ce fichier déclare les contraintes sur Terraform lui-même et les providers requis. Il est la première chose à créer dans tout nouveau projet.

terraform {
required_version = ">= 1.11.0"
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
version = "~> 0.8"
}
}
}

Le cœur du projet : providers, resources, et data sources. Sur les petits projets, tout tient ici. Sur les projets plus grands, on peut créer des fichiers thématiques (network.tf, compute.tf, storage.tf).

provider "libvirt" {
uri = "qemu:///system"
}
resource "libvirt_volume" "disk" {
name = var.vm_name
pool = "default"
target = {
format = { type = "qcow2" }
}
create = {
content = {
url = var.image_path
}
}
}
resource "libvirt_domain" "vm" {
name = var.vm_name
type = "kvm"
memory = var.memory_mb
memory_unit = "MiB"
vcpu = var.vcpu_count
os = {
type = "hvm"
type_arch = "x86_64"
type_machine = "q35"
}
devices = {
disks = [
{
source = {
file = { file = libvirt_volume.disk.path }
}
target = { dev = "vda", bus = "virtio" }
}
]
interfaces = [
{
model = { type = "virtio" }
source = { network = { network = "default" } }
}
]
}
}

Toutes les déclarations variable {} sont regroupées ici. Ce fichier documente les paramètres d’entrée du projet.

variable "vm_name" {
description = "Nom de la VM libvirt"
type = string
default = "lab-vm"
}
variable "memory_mb" {
description = "RAM allouée en MiB"
type = number
default = 512
}
variable "vcpu_count" {
description = "Nombre de vCPUs"
type = number
default = 1
}
variable "image_path" {
description = "Chemin vers l'image cloud locale"
type = string
default = "/home/bob/images/ubuntu-24.04-cloudimg.img"
}

Les valeurs à exposer après terraform apply : IP, nom, ID, chemin…

output "vm_name" {
description = "Nom de la VM créée"
value = libvirt_domain.vm.name
}
output "disk_path" {
description = "Chemin du disque dans le pool libvirt"
value = libvirt_volume.disk.path
}

Après apply :

Fenêtre de terminal
terraform output vm_name # → "lab-vm"
terraform output disk_path # → "/var/lib/libvirt/images/lab-vm.qcow2"

Valeurs concrètes des variables. Ce fichier surcharge les default déclarés dans variables.tf.

vm_name = "mon-serveur-web"
memory_mb = 1024
vcpu_count = 2

Voici la structure exacte du projet validé pour cette section :

  • Répertoiremon-projet/
    • versions.tf
    • main.tf
    • variables.tf
    • outputs.tf
    • terraform.tfvars
    • Répertoire.terraform/ (généré par terraform init — ne pas commiter)
    • .terraform.lock.hcl (fichier de lock des providers — à commiter)
    • terraform.tfstate (state local — ne pas commiter)

Généré automatiquement par terraform init, ce fichier enregistre les versions exactes des providers installés et leur hash de vérification.

.terraform.lock.hcl
provider "registry.terraform.io/dmacvicar/libvirt" {
version = "0.9.7"
constraints = "~> 0.8"
hashes = [
"h1:...",
]
}

Ce fichier doit être commité dans le dépôt Git. Il garantit que tous les membres de l’équipe installent exactement les mêmes versions de providers.

# Terraform
.terraform/
terraform.tfstate
terraform.tfstate.backup
*.tfvars

*.tfvars est exclu pour éviter de pousser des secrets. Si vos fichiers .tfvars ne contiennent aucune donnée sensible, vous pouvez versionner un fichier d’exemple (terraform.tfvars.example) ou retirer cette ligne.

.terraform.lock.hcl n’est pas dans le .gitignore — il doit être versionné.

Quand un projet grandit, on peut découper par type de ressource :

  • Répertoireinfra-kvm/
    • versions.tf
    • providers.tf (configurations des providers si multiples)
    • network.tf (libvirt_network)
    • compute.tf (libvirt_domain + libvirt_volume)
    • variables.tf
    • outputs.tf
    • locals.tf (locals )
    • terraform.tfvars

Il n’y a pas de règle absolue sur les noms de fichiers — l’essentiel est que la structure soit prévisible et documentée pour toute l’équipe.

  • versions.tf : contraintes de version Terraform et providers.
  • main.tf : provider, resources, data sources.
  • variables.tf : déclarations des paramètres d’entrée.
  • outputs.tf : valeurs exposées après apply.
  • terraform.tfvars (et *.auto.tfvars) : valeurs des variables (hors secrets).
  • .terraform.lock.hcl : à commiter impérativement.
  • .terraform/ et terraform.tfstate : à exclure du Git.

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