Easy Steps to Create AWS VPC with Terraform

Sujit Patel
5 min readApr 27, 2022

--

HashiCorp Terraform is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.

To know more about terraform checkout official Documentation : Link

In this article we’ll create AWS VPC with two private and public subnet along with Internet Gateway and NAT Gateway.

List of Resources will be created.

  1. AWS VPC with CIDR 10.0.0.0/16 (You can change CIDR range in vars.tf)
  2. subnets (public and private)
  3. Internet Gateway
  4. Route Table (for public and private)
  5. Elastic IP for NAT gateway
  6. NAT Gateway
  7. Associate route tables
  8. Default security group for VPC

You can find all the files in my git repository : Link

Prerequisites

  • AWS ACCOUNT
  • AWS Access keys
  • AWS CLI
  • Terrafrom CLI

Steps

  1. First let’s create a dir to keep our all terraform files.
mkdir terraform-vpc

2. Change dir and we’ll create 3 files. using touch command.

touch main.tf vars.tf output.tf
  • main.tf (In this file we’ll define cloud provider and resources we want to create)
  • output.tf (This file stores outputs from terraform apply)
  • vars.tf (we’ll use this file to store variables.)

3. Edit main.tf and write below configuration and save it.

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.6.0"
}
}

required_version = ">= 1.1.7"
}

provider "aws" {
region = var.region
}

#Creating VPC
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true

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

#Creating Public subnet1
resource "aws_subnet" "public_subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet_cidr1
availability_zone = var.availability_zone1
map_public_ip_on_launch = true

tags = {
Name = "${var.environment}-public-subnet-1"
Environment = "${var.environment}"
}
}


#Creating Public subnet2
resource "aws_subnet" "public_subnet2" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.public_subnet_cidr2
availability_zone = var.availability_zone2
map_public_ip_on_launch = true

tags = {
Name = "${var.environment}-public-subnet-2"
Environment = "${var.environment}"
}
}

#Creating Private subnet 1
resource "aws_subnet" "private_subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.private_subnet_cidr1
availability_zone = var.availability_zone1
map_public_ip_on_launch = false

tags = {
Name = "${var.environment}-private-subnet-1"
Environment = "${var.environment}"
}
}

#Creating Private subnet 2
resource "aws_subnet" "private_subnet2" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.private_subnet_cidr2
availability_zone = var.availability_zone2
map_public_ip_on_launch = false

tags = {
Name = "${var.environment}-private-subnet-2"
Environment = "${var.environment}"
}
}

# Creating Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.environment}-igw"
Environment = var.environment
}

}

#Creating Route tables for Private Subnet
resource "aws_route_table" "private" {
vpc_id = aws_vpc.vpc.id

tags = {
Name = "${var.environment}-private-route-table"
Environment = "${var.environment}"
}
}

#Creating Route table Public Subnet
resource "aws_route_table" "public" {
vpc_id = aws_vpc.vpc.id

tags = {
Name = "${var.environment}-public-route-table"
Environment = "${var.environment}"
}
}

#Creating Elastic-IP (eip) for NAT Gateway
resource "aws_eip" "nat_eip" {
vpc = true
depends_on = [aws_internet_gateway.igw]


tags = {
Name = "${var.environment}-nat_eip"
Environment = "${var.environment}"
}
}


#Creating NAT Gateway
resource "aws_nat_gateway" "nat" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.public_subnet1.id

tags = {
Name = "${var.environment}-nat_gateway"
Environment = "${var.environment}"
}
}


#Adding Route for Internet Gateway
resource "aws_route" "public_internet_gateway" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}

#Adding Route for NAT
resource "aws_route" "private_nat_gateway" {
route_table_id = aws_route_table.private.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat.id
}


#Associate route table with public subnet1
resource "aws_route_table_association" "public1" {
subnet_id = aws_subnet.public_subnet1.id
route_table_id = aws_route_table.public.id
}

#Associate route table with public subnet2
resource "aws_route_table_association" "public2" {
subnet_id = aws_subnet.public_subnet2.id
route_table_id = aws_route_table.public.id
}

#Associate route table with private subnet1
resource "aws_route_table_association" "private1" {
subnet_id = aws_subnet.private_subnet1.id
route_table_id = aws_route_table.private.id
}

#Associate route table with private subnet2
resource "aws_route_table_association" "private2" {
subnet_id = aws_subnet.private_subnet2.id
route_table_id = aws_route_table.private.id
}

#Creating default security group for VPC
resource "aws_security_group" "default" {
name = "${var.environment}-default-sg"
description = "Default SG to alllow traffic from the ${var.environment}-VPC"
vpc_id = aws_vpc.vpc.id
depends_on = [
aws_vpc.vpc
]

ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = true
}

egress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = "true"
}

tags = {
Name = "${var.environment}-default-sg"
Environment = "${var.environment}"
}
}

4. Edit vars.tf and write below configuration and save it.

variable "region" {
default = "ap-south-1"
}

variable "environment" {
default = "demo"
description = "Deployment Environment"
}

variable "vpc_cidr" {
default = "10.0.0.0/16"
description = "CIDR block of the vpc"
}

variable "public_subnet_cidr1" {
default = "10.0.0.0/24"
description = "CIDR block of the public subnet"
}

variable "public_subnet_cidr2" {
default = "10.0.1.0/24"
description = "CIDR block of the public subnet"
}

variable "private_subnet_cidr1" {
default = "10.0.2.0/24"
description = "CIDR block of the private subnet"
}

variable "private_subnet_cidr2" {
default = "10.0.3.0/24"
description = "CIDR block of the private subnet"
}

variable "availability_zone1" {
default = "ap-south-1a"
description = "availability zones"
}

variable "availability_zone2" {
default = "ap-south-1b"
description = "availability zones"
}

5. Edit output.tf and write below configuration and save it.

output "vpc_id" {
value = aws_vpc.vpc.id
description = "ID of VPC"
}

output "public_subnet_id1" {
value = aws_subnet.public_subnet1.id
description = "ID of public subnet"
}

output "public_subnet_id2" {
value = aws_subnet.public_subnet2.id
description = "ID of public subnet"
}

output "private_subnet_id1" {
value = aws_subnet.private_subnet1.id
description = "ID of private subnet"
}

output "private_subnet_id2" {
value = aws_subnet.private_subnet2.id
description = "ID of private subnet"
}

output "igw_id" {
value = aws_internet_gateway.igw.id
description = "ID of internet gateway"
}

output "public_route_table_id" {
value = aws_route_table.public.id
description = "ID of public route table"
}

output "private_route_table_id" {
value = aws_route_table.private.id
description = "ID of private route table"
}

output "nat_eip" {
value = aws_eip.nat_eip.public_ip
description = "Contains the public IP address"
}

output "nat_eip_id" {
value = aws_eip.nat_eip.id
description = "Contains the EIP allocation ID"
}

output "security_group_id" {
value = aws_security_group.default.id
description = "Conatins ID of security group"
}

We have create all the necessary files, Now It’s time to create resources in AWS.

6. Run terraform init to initialize the dir.

7. Run terraform plan to check resources before creating.

8. Run terraform apply to create resources in your AWS.

To check output’s of terraform apply run terraform output

It will give you the details like vpc id, nat gateway id, subnet id etc.

Now log into your AWS console and verify the resources.

Congratulations 🎉

--

--

Sujit Patel
Sujit Patel

Written by Sujit Patel

DevOps Engineer, Linux lover, Technology and Automation enthusiast. A strong believer in continuous learning.

Responses (1)