agentsclimarketplace

Terraform guide

Skill WhiteMuush/Your-Claude-DevOps-Teacher/skills/terraform-guide

Guide Terraform pour l'Infrastructure as Code, modules, state management, workspaces et bonnes pratiques. À utiliser quand l'utilisateur écrit du Terraform, conçoit des modules ou gère de l'infrastructure cloud. Se déclenche aussi avec "terraform", "infrastructure as code", "terraform plan", "terraform apply", "module terraform", "tfstate", "HCL".From its SKILL.md

Install
npx -y skills add WhiteMuush/Your-Claude-DevOps-Teacher --skill terraform-guide

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.6 KB, ~2.2k tokens by cl100k_base, as published. Nobody here has run it

Guide Terraform

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

  1. Initialiser, configurer le backend et télécharger les providers.
    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.
    terraform validate
    terraform fmt -recursive         # formater tout le répertoire
    
  3. Planifier, toujours sauvegarder le plan pour un apply déterministe.
    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é.
    terraform apply tfplan.bin
    
  5. Vérifier le drift, détecter les divergences entre state et réalité.
    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.
    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

# 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 :

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)

# 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)

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

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

# 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ègeSymptômeRemède
State en local / commité dans GitConflits d'équipe, secrets exposésBackend distant + .gitignore sur *.tfstate*
terraform apply sans plan sauvegardéApply incohérent si state a changé entre-tempsToujours -out=tfplan.bin + apply tfplan.bin
Hard-coding de secrets dans HCLSecrets dans Gitvar + Key Vault / Secrets Manager ou sensitive = true
Modules trop fins (1 ressource)Overhead de composition, appels imbriquésRegrouper par domaine fonctionnel
terraform destroy sans -targetDestruction de toute l'infraToujours cibler ou utiliser des workspaces isolés
Drift ignoréÉtat réel diverge du planplan -refresh-only en CI hebdomadaire
Pas de lifecycle.prevent_destroy sur ressources critiquesSuppression accidentelle BDD/stockageAjouter prevent_destroy = true sur les ressources stateful
# 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.
    tflint --recursive
    checkov -d . --framework terraform
    

8. Commandes de référence rapide

# 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

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,851. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.