Skip to content
Back to skills

Terraform Guide

ASecurity

Guide Terraform — écriture de modules, state management, workspaces, providers et bonnes pratiques HCL. À utiliser quand l'utilisateur écrit ou débogue du Terraform précisément ; pour le choix d'outil IaC, voir dev-infrastructure-as-code. Se déclenche aussi avec "terraform", "terraform plan", "terraform apply", "module terraform", "tfstate", "HCL", "terraform import". Also triggers on "Terraform module", "terraform state", "provision with Terraform".

  • 27 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 18, 2026
ai-agentsbashsqlawsazureterraformgitapidatabasebackendci/cd

Works with

  • api

Security analysis

A100/100

Scanned October 18, 2026

npx -y skills add khalilbenaz/claude-skills-collection --skill terraform-guide --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Terraform Guide?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Terraform Guide
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/khalilbenaz-terraform-guide/badge)](https://www.skillsdirectory.com/skills/khalilbenaz-terraform-guide)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: terraform-guide
description: Guide Terraform — écriture de modules, state management, workspaces, providers et bonnes pratiques HCL. À utiliser quand l'utilisateur écrit ou débogue du Terraform précisément ; pour le choix d'outil IaC, voir dev-infrastructure-as-code. Se déclenche aussi avec "terraform", "terraform plan", "terraform apply", "module terraform", "tfstate", "HCL", "terraform import". Also triggers on "Terraform module", "terraform state", "provision with Terraform".
---

# Guide Terraform

## 1. Workflow opérationnel (étapes numérotées)

1. **Initialiser** — configurer le backend et télécharger les providers.
   ```bash
   terraform init -upgrade          # première fois ou mise à jour providers
   terraform init -reconfigure      # changer de backend sans migrer l'état
   ```
2. **Valider** — vérifier la syntaxe avant de planifier.
   ```bash
   terraform validate
   terraform fmt -recursive         # formater tout le répertoire
   ```
3. **Planifier** — toujours sauvegarder le plan pour un apply déterministe.
   ```bash
   terraform plan -out=tfplan.bin
   terraform show -json tfplan.bin | jq '.resource_changes[] | select(.change.actions != ["no-op"])'
   ```
4. **Appliquer** — uniquement depuis le plan sauvegardé.
   ```bash
   terraform apply tfplan.bin
   ```
5. **Vérifier le drift** — détecter les divergences entre state et réalité.
   ```bash
   terraform plan -refresh-only     # voir ce qui a changé hors Terraform
   terraform apply -refresh-only    # re-synchroniser le state sans modifier les ressources
   ```
6. **Détruire proprement** — cibler d'abord, jamais en masse sans review.
   ```bash
   terraform destroy -target=module.networking.azurerm_subnet.main
   ```

---

## 2. Structure de projet recommandée

```
infrastructure/
├── environments/
│   ├── dev/
│   │   ├── main.tf          # appels aux modules
│   │   ├── variables.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   └── production/
├── modules/
│   ├── networking/          # un module = une responsabilité
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── database/
│   └── app-service/
└── shared/
    └── versions.tf          # contraintes de version providers
```

**Critère de découpage** : un module par "domaine fonctionnel" (réseau, stockage, compute). Éviter les modules à 1 ressource (sur-découpage) et les modules "tout en un" (couplage fort).

---

## 3. Module réutilisable — exemple complet

```hcl
# modules/app-service/variables.tf
variable "app_name"           { type = string }
variable "environment"        {
  type    = string
  validation {
    condition     = contains(["dev", "staging", "production"], var.environment)
    error_message = "Valeurs acceptées : dev, staging, production."
  }
}
variable "sku"                { type = string; default = "B1" }
variable "location"           { type = string }
variable "resource_group_name"{ type = string }
variable "app_settings"       { type = map(string); default = {} }

# modules/app-service/main.tf
locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
    Application = var.app_name
  }
}

resource "azurerm_service_plan" "this" {
  name                = "plan-${var.app_name}-${var.environment}"
  location            = var.location
  resource_group_name = var.resource_group_name
  os_type             = "Linux"
  sku_name            = var.sku
  tags                = local.common_tags
}

resource "azurerm_linux_web_app" "this" {
  name                = "app-${var.app_name}-${var.environment}"
  location            = var.location
  resource_group_name = var.resource_group_name
  service_plan_id     = azurerm_service_plan.this.id
  tags                = local.common_tags

  site_config {
    always_on = var.environment == "production"
    application_stack { dotnet_version = "8.0" }
  }

  app_settings = var.app_settings
}

# modules/app-service/outputs.tf
output "app_url"     { value = "https://${azurerm_linux_web_app.this.default_hostname}" }
output "app_id"      { value = azurerm_linux_web_app.this.id }
output "plan_id"     { value = azurerm_service_plan.this.id }
```

Appel depuis un environnement :
```hcl
module "api" {
  source              = "../../modules/app-service"
  app_name            = "myapi"
  environment         = "production"
  sku                 = "P1v3"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
}
```

---

## 4. State management

### Backend distant avec locking (Azure)
```hcl
# environments/production/backend.tf
terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state"
    storage_account_name = "stterraformstprod"
    container_name       = "tfstate"
    key                  = "myapp.production.tfstate"
    use_azuread_auth     = true   # évite les clés de compte (2025+)
  }
}
```

### Backend S3 + DynamoDB (AWS)
```hcl
terraform {
  backend "s3" {
    bucket         = "myco-tfstate-prod"
    key            = "myapp/production/terraform.tfstate"
    region         = "eu-west-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"
  }
}
```

### Commandes de gestion du state
```bash
terraform state list                              # toutes les ressources
terraform state show azurerm_linux_web_app.this   # détail d'une ressource
terraform state mv  module.old.res module.new.res # renommer sans recréer
terraform state rm  azurerm_resource_group.legacy # retirer du state sans détruire
terraform import    azurerm_resource_group.legacy /subscriptions/.../rg-name
```

---

## 5. Versions et contraintes providers

```hcl
# shared/versions.tf — à copier dans chaque environnement
terraform {
  required_version = ">= 1.7, < 2.0"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.110"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }
}
```

Verrouiller le `.terraform.lock.hcl` dans Git — il garantit la reproductibilité des builds.

---

## 6. Garde-fous et pièges fréquents

| Piège | Symptôme | Remède |
|-------|----------|--------|
| State en local / commité dans Git | Conflits d'équipe, secrets exposés | Backend distant + `.gitignore` sur `*.tfstate*` |
| `terraform apply` sans plan sauvegardé | Apply incohérent si state a changé entre-temps | Toujours `-out=tfplan.bin` + `apply tfplan.bin` |
| Hard-coding de secrets dans HCL | Secrets dans Git | `var` + Key Vault / Secrets Manager ou `sensitive = true` |
| Modules trop fins (1 ressource) | Overhead de composition, appels imbriqués | Regrouper par domaine fonctionnel |
| `terraform destroy` sans `-target` | Destruction de toute l'infra | Toujours cibler ou utiliser des workspaces isolés |
| Drift ignoré | État réel diverge du plan | `plan -refresh-only` en CI hebdomadaire |
| Pas de `lifecycle.prevent_destroy` sur ressources critiques | Suppression accidentelle BDD/stockage | Ajouter `prevent_destroy = true` sur les ressources stateful |

```hcl
# Protéger une base de données critique
resource "azurerm_postgresql_flexible_server" "main" {
  # ...
  lifecycle {
    prevent_destroy = true
  }
}
```

---

## 7. Bonnes pratiques 2026

- **Épingler les versions** providers via `.terraform.lock.hcl` (commité dans Git).
- **Secrets** : ne jamais les mettre dans `.tfvars`; utiliser `sensitive = true` + injection CI (env vars `TF_VAR_*`).
- **Tagging systématique** : module `locals` avec `common_tags` hérité par toutes les ressources.
- **Outputs sensibles** : marquer `sensitive = true` pour éviter les logs en clair.
- **CI/CD** : `terraform plan` en PR (commentaire automatique), `terraform apply` uniquement sur merge main.
- **Workspaces** : réservés aux environnements éphémères (feature branches) — ne pas les utiliser pour prod/staging (préférer des dossiers séparés avec leur propre state).
- **Tflint + Checkov** : linting et scan de sécurité avant le plan.
  ```bash
  tflint --recursive
  checkov -d . --framework terraform
  ```

---

## 8. Commandes de référence rapide

```bash
# Init & format
terraform init -upgrade && terraform fmt -recursive && terraform validate

# Plan sécurisé
terraform plan -var-file=environments/prod.tfvars -out=tfplan.bin

# Inspection du plan
terraform show tfplan.bin                   # lisible humain
terraform show -json tfplan.bin | jq '.'   # JSON pour scripts

# State ops
terraform state list
terraform state show <resource_address>
terraform state mv   <src> <dst>
terraform state rm   <resource_address>

# Import ressource existante
terraform import <resource_address> <cloud_id>

# Drift
terraform plan -refresh-only
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.