📋 ITAG Templates · Catalogue 30+ templates pro · Voir tout
← Retour au catalogue 📥 Télécharger ce template

🌐 Module Terraform — VPC AWS multi-AZ

Format : Terraform (.tf) · production-ready Auteur : Équipe pédagogique ITAG · DevOps Pack Mise à jour : 2026 (provider AWS 5.x · Terraform 1.7+)


🎯 Description

Module Terraform réutilisable pour provisionner un VPC AWS production-grade : 3 AZ, subnets publics + privés + database, NAT gateway, bastion host optionnel, flow logs, network ACLs.

📋 Ressources créées

Networking

Routing

Sécurité

Optional

🛠️ Variables clés

💾 Code Terraform complet

provider.tf

terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" { region = var.region

default_tags { tags = { Project = var.project_name Environment = var.environment ManagedBy = "Terraform" } } }

main.tf

# ── VPC ──────────────────────────────────────────────────────────────────────
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

tags = { Name = "${var.project_name}-${var.environment}-vpc" } }

── SUBNETS PUBLICS ───────────────────────────────────────────────────────────

resource "aws_subnet" "public_a" { vpc_id = aws_vpc.main.id cidr_block = "10.0.1.0/24" availability_zone = "${var.region}a" map_public_ip_on_launch = true

tags = { Name = "${var.project_name}-${var.environment}-public-a" Tier = "public" } }

resource "aws_subnet" "public_b" { vpc_id = aws_vpc.main.id cidr_block = "10.0.2.0/24" availability_zone = "${var.region}b" map_public_ip_on_launch = true

tags = { Name = "${var.project_name}-${var.environment}-public-b" Tier = "public" } }

── SUBNETS PRIVÉS ────────────────────────────────────────────────────────────

resource "aws_subnet" "private_a" { vpc_id = aws_vpc.main.id cidr_block = "10.0.10.0/24" availability_zone = "${var.region}a"

tags = { Name = "${var.project_name}-${var.environment}-private-a" Tier = "private" } }

resource "aws_subnet" "private_b" { vpc_id = aws_vpc.main.id cidr_block = "10.0.11.0/24" availability_zone = "${var.region}b"

tags = { Name = "${var.project_name}-${var.environment}-private-b" Tier = "private" } }

── INTERNET GATEWAY ──────────────────────────────────────────────────────────

resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id

tags = { Name = "${var.project_name}-${var.environment}-igw" } }

── ROUTE TABLE PUBLIQUE ──────────────────────────────────────────────────────

resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id

route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id }

tags = { Name = "${var.project_name}-${var.environment}-rt-public" } }

resource "aws_route_table_association" "public_a" { subnet_id = aws_subnet.public_a.id route_table_id = aws_route_table.public.id }

resource "aws_route_table_association" "public_b" { subnet_id = aws_subnet.public_b.id route_table_id = aws_route_table.public.id }

── NAT GATEWAYS (HA — un par AZ) ────────────────────────────────────────────

resource "aws_eip" "nat_a" { count = var.enable_nat_gateway ? 1 : 0 domain = "vpc"

tags = { Name = "${var.project_name}-${var.environment}-eip-nat-a" } }

resource "aws_eip" "nat_b" { count = var.enable_nat_gateway ? 1 : 0 domain = "vpc"

tags = { Name = "${var.project_name}-${var.environment}-eip-nat-b" } }

resource "aws_nat_gateway" "nat_a" { count = var.enable_nat_gateway ? 1 : 0 allocation_id = aws_eip.nat_a[0].id subnet_id = aws_subnet.public_a.id

tags = { Name = "${var.project_name}-${var.environment}-nat-a" }

depends_on = [aws_internet_gateway.main] }

resource "aws_nat_gateway" "nat_b" { count = var.enable_nat_gateway ? 1 : 0 allocation_id = aws_eip.nat_b[0].id subnet_id = aws_subnet.public_b.id

tags = { Name = "${var.project_name}-${var.environment}-nat-b" }

depends_on = [aws_internet_gateway.main] }

── ROUTE TABLES PRIVÉES (via NAT) ───────────────────────────────────────────

resource "aws_route_table" "private_a" { count = var.enable_nat_gateway ? 1 : 0 vpc_id = aws_vpc.main.id

route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.nat_a[0].id }

tags = { Name = "${var.project_name}-${var.environment}-rt-private-a" } }

resource "aws_route_table" "private_b" { count = var.enable_nat_gateway ? 1 : 0 vpc_id = aws_vpc.main.id

route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.nat_b[0].id }

tags = { Name = "${var.project_name}-${var.environment}-rt-private-b" } }

resource "aws_route_table_association" "private_a" { count = var.enable_nat_gateway ? 1 : 0 subnet_id = aws_subnet.private_a.id route_table_id = aws_route_table.private_a[0].id }

resource "aws_route_table_association" "private_b" { count = var.enable_nat_gateway ? 1 : 0 subnet_id = aws_subnet.private_b.id route_table_id = aws_route_table.private_b[0].id }

── SECURITY GROUP BASTION ────────────────────────────────────────────────────

resource "aws_security_group" "bastion" { name = "${var.project_name}-${var.environment}-bastion-sg" description = "Security group for bastion host — SSH access" vpc_id = aws_vpc.main.id

ingress { description = "SSH from allowed CIDR" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = [var.allowed_cidr] }

egress { description = "All outbound traffic" from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] }

tags = { Name = "${var.project_name}-${var.environment}-bastion-sg" } }

variables.tf

variable "region" {
  description = "AWS region to deploy resources"
  type        = string
  default     = "eu-west-1"
}

variable "environment" { description = "Deployment environment (dev / staging / prod)" type = string default = "dev"

validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "environment must be one of: dev, staging, prod." } }

variable "project_name" { description = "Name used as prefix for all resource names" type = string default = "myapp" }

variable "vpc_cidr" { description = "CIDR block for the VPC" type = string default = "10.0.0.0/16" }

variable "allowed_cidr" { description = "CIDR allowed to SSH into the bastion host" type = string default = "0.0.0.0/0" # Restreindre en production ! }

variable "enable_nat_gateway" { description = "Provision NAT Gateways for private subnets (adds cost)" type = bool default = true }

outputs.tf

output "vpc_id" {
  description = "ID of the created VPC"
  value       = aws_vpc.main.id
}

output "public_subnet_ids" { description = "List of public subnet IDs" value = [aws_subnet.public_a.id, aws_subnet.public_b.id] }

output "private_subnet_ids" { description = "List of private subnet IDs" value = [aws_subnet.private_a.id, aws_subnet.private_b.id] }

output "nat_gateway_ids" { description = "IDs of NAT Gateways (empty if enable_nat_gateway=false)" value = var.enable_nat_gateway ? [ aws_nat_gateway.nat_a[0].id, aws_nat_gateway.nat_b[0].id ] : [] }

output "bastion_sg_id" { description = "ID of the bastion security group" value = aws_security_group.bastion.id }

💼 Cas d'usage

📥 Télécharger ce template

Télécharger le fichier .md · ← Catalogue Terraform · Parcours DevOps →


ITAG · Non-affiliés HashiCorp / AWS. Terraform® et AWS® sont des marques déposées.

Template prêt pour vous

Tous les templates ITAG sont produits par notre équipe pédagogique. Téléchargement gratuit, usage libre.

📋 Catalogue complet 📅 Coach 1:1