DEV Community

Cover image for Deploying NGINX on AWS EC2 Using Terraform๐Ÿš€๐Ÿš€(Project)
Tandap Noel Bansikah
Tandap Noel Bansikah

Posted on

Deploying NGINX on AWS EC2 Using Terraform๐Ÿš€๐Ÿš€(Project)

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
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"]
  }
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"
  }
}
Enter fullscreen mode Exit fullscreen mode

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
}

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You should see:

Init image
Validate the configuration:

terraform validate
Enter fullscreen mode Exit fullscreen mode

Plan the infrastructure:

terraform plan
Enter fullscreen mode Exit fullscreen mode

Apply the configuration:

terraform apply
Enter fullscreen mode Exit fullscreen mode

You should see:
apply image

And after that you can copy the the EIP and check on the browser if everything is successful

success image
Destroy Infrastructure

terraform destroy
Enter fullscreen mode Exit fullscreen mode

Destroy image

Wondering why i used tf on my terminal?๐Ÿค”๐Ÿค” you should create an alias for terraform like so

alias tf="terraform"
Enter fullscreen mode Exit fullscreen mode

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! ๐Ÿš€

Ref:
Terraform
Nginx
AWS VPC

Top comments (0)