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
- An active AWS account with an IAM user already created
- Text editor of your choice (VSCode Recommended)
- Terraform Installed: Make sure you have Terraform installed on your machine, you should also have a basic knowledge of how it works.
- AWS credentials: You should have AWS credentials configured locally using AWS CLI or through environment variables.
- AWS Provider: This guide uses the AWS provider.
- 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
}
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"
}
}
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"
}
}
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"
}
}
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"
}
}
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
}
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"
}
}
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
}
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]
}
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
}
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"
}
12. How to Deploy
Ø Initialize Terraform:
Navigate to your project directory and run:
bash
terraform init
Ø Plan the infrastructure:
Review the changes that Terraform will make:
bash
terraform plan
Ø Apply the configuration:
Deploy the resources by running:
bash
terraform apply
Ø Confirm:
Type yes
when prompted to confirm the creation of resources.
13. Verify the Resources Created:
Navigate to your AWS management console and search for VPC to see the newly created VPC via terraform
From your AWS management console dashboard, search for EC2 to see the newly created EC2 via terraform
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
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.
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)