Introduction
In this article, I'll walk you through deploying an NGINX web server on an AWS EC2 instance using Terraform. This step-by-step guide provides all the necessary Terraform scripts to configure a Virtual Private Cloud (VPC), set up a security group, provision an EC2 instance, and deploy NGINX. By the end of this tutorial, you'll have a fully functional web server hosted on AWS.
Prerequisites
- An AWS account.
- Terraform installed on your machine.
- Basic knowledge of AWS and Terraform concepts.
Cost for this hands on tutorial
- 0.0$ (make sure to destroy immediately after testing)
Project Structure
Here's the structure of our Terraform project:
terraform_project/
โโโ main.tf
โโโ variables.tf
โโโ outputs.tf
โโโ vpc.tf
โโโ elastic_ip.tf
โโโ provider.tf
โโโ security_group.tf
โโโ userdata.tpl
โโโ terraform.tfvars
โโโ key.tf
Each file has a specific purpose, as detailed below.
Let's use a shell script to create the following structure so that you won't have to type them manually on your terminal
touch.sh
make sure to chmod +x touch.sh
making the script executable
#!/bin/bash
# Create project directory
mkdir -p terraform_project
cd terraform_project || exit
# Create empty files
touch main.tf
touch variables.tf
touch outputs.tf
touch vpc.tf
touch elastic_ip.tf
touch provider.tf
touch security_group.tf
touch userdata.tpl
touch terraform.tfvars
touch key.tf
echo "Empty Terraform project structure created successfully!"
Provider Configuration (provider.tf
)
The provider.tf
file sets up the AWS provider:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = var.aws_region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}
This configuration ensures Terraform uses the AWS provider with the necessary credentials and region.
Variables Configuration(variables.tf
)
Define reusable variables:
variable "aws_access_key" {
type = string
description = "AWS access key"
}
variable "aws_secret_key" {
type = string
description = "AWS secret key"
}
variable "aws_region" {
type = string
description = "AWS region"
default = "eu-central-1"
}
variable "key_name" {
type = string
description = "SSH key pair name"
default = "auto-generated-key-pair"
}
variable "instance_type" {
type = string
description = "EC2 instance type"
default = "t2.micro"
}
variable "ami_id" {
type = string
description = "AMI ID for the EC2 instance"
default = "ami-09042b2f6d07d164a"
}
VPC Configuration (vpc.tf
)
We create a VPC, subnet, and route table for our infrastructure:
vpc.tf
resource "aws_vpc" "main_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "main_vpc"
}
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.main_vpc.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "eu-central-1a"
tags = {
Name = "public_subnet"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.main_vpc.id
tags = {
Name = "igw"
}
}
resource "aws_route_table" "public_route" {
vpc_id = aws_vpc.main_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
Name = "public_route"
}
}
resource "aws_route_table_association" "public_route_association" {
route_table_id = aws_route_table.public_route.id
subnet_id = aws_subnet.public_subnet.id
}
Security Group Configuration (security_group.tf
)
Allow HTTP (port 80) and SSH (port 22) traffic:
security_group.tf
resource "aws_security_group" "my_security_group" {
name = "my_security_group"
description = "Allow inbound SSH and HTTP"
vpc_id = aws_vpc.main_vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
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"]
}
}
Elastic IP Configuration (elastic_ip.tf
)
Allocate an Elastic IP and associate it with the EC2 instance:
elastic_ip.tf
resource "aws_eip" "elastic_ip" {
instance = aws_instance.nginx_instance.id
}
resource "aws_eip_association" "main" {
instance_id = aws_instance.nginx_instance.id
allocation_id = aws_eip.elastic_ip.id
}
SSH Key Pair (key.tf
)
Generate a secure SSH key pair:
key.tf
resource "tls_private_key" "rsa_4096" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "local_file" "private_key" {
filename = "${path.module}/var.key_name.pem"
content = tls_private_key.rsa_4096.private_key_pem
}
resource "aws_key_pair" "key_pair" {
key_name = var.key_name
public_key = tls_private_key.rsa_4096.public_key_openssh
}
EC2 Instance Configuration (main.tf
)
Launch an EC2 instance and configure it with NGINX:
main.tf
resource "aws_instance" "nginx_instance" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.key_name
vpc_security_group_ids = [aws_security_group.my_security_group.id]
subnet_id = aws_subnet.public_subnet.id
user_data = file("userdata.tpl")
tags = {
Name = "nginx_instance"
}
}
Create Output for resources(outputs.tf
)
# outputs.tf
output "instance_id" {
description = "ID of the deployed EC2 instance"
value = aws_instance.nginx_instance.id
}
output "instance_public_ip" {
description = "Public IP address of the EC2 instance"
value = aws_eip.elastic_ip.public_ip
}
output "key_pair_name" {
description = "Name of the SSH key pair"
value = aws_key_pair.key_pair.key_name
}
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main_vpc.id
}
output "subnet_id" {
description = "Subnet ID"
value = aws_subnet.public_subnet.id
}
User Data Script (userdata.tpl
)
Automate NGINX installation:
userdata.tpl
#!/bin/bash
apt-get update
apt-get install -y nginx
echo "<html><body><h1>Congratulations!! You have successfully deployed an EC2 instance with NGINX on it.</h1></body></html>" > /var/www/html/index.html
systemctl start nginx
systemctl enable nginx
Also you will need to create a terraform.tfvars
where you will put your secrete and key
terraform.tfvars
# terraform.tfvars
aws_access_key = "your aws access key"
aws_secret_key = "your aws secret key"
key_name = "value"
Note:
You should not always push this file to your github repo as it contains sensitive information, always remember to specify in your .gitignore file
Deploying the Infrastructure
Initialize Terraform:
terraform init
You should see:
terraform validate
Plan the infrastructure:
terraform plan
Apply the configuration:
terraform apply
And after that you can copy the the EIP and check on the browser if everything is successful
terraform destroy
Wondering why i used tf
on my terminal?๐ค๐ค you should create an alias for terraform like so
alias tf="terraform"
Note:
Also make sure to follow best practices like Creating an IAM user for this labs don't use your main account
Conclusion
Congratulations! Youโve successfully deployed an EC2 instance running NGINX using Terraform. If you encounter any challenges or have questions, feel free to reach out. Happy coding! ๐
Top comments (0)