DEV Community

Uwadone Joshua
Uwadone Joshua

Posted on

Deploy an EC2 instance inside a custom VPC using Terraform.

Deploy an EC2 instance inside a custom VPC using Terraform.

This guide will set up the following:

  • A VPC with one Availability Zones (AZs).
  • In the AZ, there will be:
  • A public subnet for resources like NAT gateway and EC2 instance.
  • Internet Gateway for outbound internet traffic from public subnets.
  • Route Tables to handle routing within the subnets.
  • Security Groups to control traffic to/from instances. In this project, you will learn how to automatically deploy an EC2 instance inside a custom VPC using Terraform.

Prerequisites

  1. An active AWS account with an IAM user already created
  2. Text editor of your choice (VSCode Recommended)
  3. Terraform Installed: Make sure you have Terraform installed on your machine, you should also have a basic knowledge of how it works.
  4. AWS credentials: You should have AWS credentials configured locally using AWS CLI or through environment variables.
  5. AWS Provider: This guide uses the AWS provider.
  6. Bash scripting knowledge

As you should know by now, Terraform is an IaC tool that helps to automate processes which increase delivery time of software. In this tutorial, Terraform will be employed in setting up an ec2 instance in a VPC and all of its components

Setting up the project environment
The first step is to create a folder on your device and open it up in VSCode. We will be creating 4 terraform files for this project;
Your project directory can be structured like this:
terraform/
├── provider.tf
├── variables.tf
├── main.tf
├── outputs.tf

Here is the outline of all the resources, we will be creating.

  • Create a VPC folder and files
  • Define the Provider Block
  • Create the VPC Block
  • Create the Subnet(s)
  • Create an Internet Gateway
  • Create Route Tables
  • Associate Subnet with Route Tables
  • Create Security Groups
  • Create KeyPairs
  • Create EC2 Instance

Step-by-Step Terraform Configuration

1. Creating your Provider Configuration
The first step is to configure the AWS provider on your provider.tf file
hcl
#Create a Terraform Provider Block
terraform {
required_providers {
aws = {
source = “hashicorp/aws”
version = “~>5.68.0”
}
}
}
provider “aws” {
region = “us-east-1” # Select your desired region
}

Provider Block

2. Creating your VPC Block

Create a VPC using the following block.
hcl
#Create the VPC Block
resource"aws_vpc" "my_vpc" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "my-vpc"
}
}

VPC Block

3. Creating your Subnet Block

For this demo, we will create only one subnet in one availability zone.
hcl
#Create the Subnet(s)
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = var.public_subnet_cidr
availability_zone = var.availability_zone
map_public_ip_on_launch = true
tags = {
Name = "my-pub-sub"
}
}

Subnet Block

4. Internet Gateway

An Internet Gateway will allow public subnets to have access to the internet.
hcl
#Create an Internet Gateway
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.my_vpc.id
tags = {
Name = "my-internet-gateway"
}
}

Internet Gateway

5. Route Tables

We need a route table for both public and private subnets. Public subnets route through the Internet Gateway, while private subnets route through a NAT Gateway.

hcl
#Create Route Tables
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "public-rt"
}
}

Route Table Resource Block

6. Associate public subnets with the public route table

hcl
#Associate Public Subnet with the Public Route Table
resource "aws_route_table_association" "public_rt_association" {
subnet_id = aws_subnet.public_subnet.id
route_table_id = aws_route_table.public_rt.id
}

Route Table Association

7. Security Groups

Here’s a basic security group allowing inbound SSH access from your IP and allowing all outbound traffic.

hcl
#Create Security Groups
resource "aws_security_group" "my-sg" {
vpc_id = aws_vpc.my_vpc.id # Ensure the security group is created in the same VPC
name = "my security group"
description = "my security group"
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allow traffic from anywhere
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "my-sg"
}
}

Security Group

Security Group Contd

8. Key Pairs
A key pair is a set of cryptographic keys used for authentication and encryption. It consists of a public key and a private key.

Public Key: This key is freely shared and can be used to encrypt data. Only the corresponding private key can decrypt the data.
Private Key: This key is kept secret and should never be shared. It's used to decrypt data encrypted with the public key.

hcl
Generate a new private key
resource "tls_private_key" "terraform_kp" {
algorithm = "RSA"
rsa_bits = 4096
}
Create AWS Key Pair using the public key generated above
resource "aws_key_pair" "my-terraform-kp" {
key_name = "terraform-kp" # New Key Pair Name
public_key = tls_private_key.terraform_kp.public_key_openssh
}
To create a file or folder to save your Private Key
resource "local_file" "terraform_kp" {
content = tls_private_key.terraform_kp.private_key_pem
filename = "terraform-kp.pem" # Save as a .pem file
}

Key Pair Resource Block

9. Create an EC Instance

#Create EC2 Instance with NGINX installation via user_data
resource "aws_instance" "project_server" {
depends_on = [aws_security_group.my-sg, aws_subnet.public_subnet]
ami = "ami-0e86e20dae9224db8" # Amazon Ubuntu AMI
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet.id
associate_public_ip_address = true
key_name = "terraform-kp"
vpc_security_group_ids = [aws_security_group.my-sg.id]
}

EC2 Resource Block

10. Outputs

You can create an outputs.tf to display useful information like the VPC ID and subnet IDs after deployment.
outputs.tf:

hcl
Output Public IP
output "project_server_public_ip" {
value = aws_instance.project_server.public_ip
}
Output Public DNS
output "aws_instance_public_dns" {
value = aws_instance.project_server.public_dns
}

Output.tf

11. Variables

You can create a variables.tf file to display your variables like the VPC ID and subnet IDs after deployment.

variable "vpc_cidr" {
default = "10.0.0.0/16"
}
variable "public_subnet_cidr" {
default = "10.0.1.0/24"
}
variable "private_subnet_cidr" {
default = "10.0.3.0/24"
}
variable "availability_zone" {
default = "us-east-1a"
}

Variable.tf

12. How to Deploy

Ø Initialize Terraform:
Navigate to your project directory and run:
bash
terraform init

Terraform Init

Ø Plan the infrastructure:
Review the changes that Terraform will make:
bash
terraform plan

Terrform Plan

Terrform Plan Contd

Ø Apply the configuration:
Deploy the resources by running:

bash
terraform apply

Terrform Apply

Terrform apply Contd

Ø Confirm:
Type yes when prompted to confirm the creation of resources.

Confirm Terrform Apply

13. Verify the Resources Created:

Navigate to your AWS management console and search for VPC to see the newly created VPC via terraform

VPC resource

From your AWS management console dashboard, search for EC2 to see the newly created EC2 via terraform

EC2 Resource

14. Clean Up Resources:

If you’re done and no longer need your resources, you can terminate them to avoid incurring charges.
Run the following command to clean your resources
bash
terraform destroy

Terraform Destroy

You will see a prompt to type YES in order to confirm your destroy action. Type YES, and your resources would be deleted completely as shown below.

Confirm Terraform Destroy

Conclusion
By following these steps and customizing the Terraform configuration to your specific needs, you can effectively launch EC2 instances in a VPC using Terraform, and you should be able to SSH into your website using the EC2 instance’s public IP.

If you find this helpful, please click the clap 👏 button below a few times to show your support for the author 👇

Top comments (0)