DEV Community

Cover image for Deploy an Nginx Web Server on an EC2 instance with Terraform
Daniel Favour
Daniel Favour

Posted on • Updated on

Deploy an Nginx Web Server on an EC2 instance with Terraform

In this tutorial, you will learn how to automatically deploy an Nginx Web Server on an EC2 instance, with Terraform.

Prerequisites

  1. An active AWS account with an IAM user already created
  2. Text editor of your choice (VSCode Recommended)
  3. Terraform Installed, you should also have a basic knowldge of how it works.
  4. 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 and deploying an nginx web server on it using bash scripts which will be provided.

Setting up project environment

First step is to create a folder on your device and open it up in VSCode. We will be creating 3 terraform files for this project;

  • terraform.tfvars
  • module.tf
  • userdata.tpl

1. Terraform.tfvars

Run the below command to create your terraform.tfvars file



touch terraform.tfvars


Enter fullscreen mode Exit fullscreen mode

Your terraform.tfvars file is going to contain private information that shouldn't be shared with the public. In the file, copy and paste the below configuration.



# Private information
aws_access_key = ""
aws_secret_key = ""
key_name = "demokey"
private_key_path = "./demokey.pem"


Enter fullscreen mode Exit fullscreen mode
  • Your access and secret key should be filled in. You can get that from the IAM user you created.

  • The key_name is the name of the key which will be used to ssh into your instance. If you have an existing one you can use that. If you don't, lets create one together.

Creating Key
In your AWS console, search for key pair and click on it.

Image description

After selecting it, Click on Create key pair

Image description

Give your key pair a name that way you can always search for it easily when needed. Also, change key file format from ".ppk" to ".pem" because we need it in a ".pem" state. Add a tag if you wish to, but that is optional and proceed to create the key pair.

Image description

Copy the Key
The just created key pair would be automatically downloaded on your device. It needs to be copied to the working directory for ease of use. In your terminal, run the command



cp ~/Downloads/demokey.pem ./


Enter fullscreen mode Exit fullscreen mode

This command basically copies your keypair from its current directory to your working directory.

  • cp is to copy and ~/Downloads/demokey.pem is the directory where my key pair currently is, demokey is the name of my key pair. Be sure to specify the directory of your own key pair and don't forget to add the extension .pem.

  • ./ means your current working directory, or in other words, where you currently are and want to key pair to be copied to.

  • For the private_key_path in the terraform.tfvars file, type in the path of your key. It should look like this ./demokey.pem. Remember to replace the demokey with your key's name.

2. Module.tf

To create your module.tf file, run the below command in your terminal



touch module.tf


Enter fullscreen mode Exit fullscreen mode

Inside the module.tf file, copy and paste the below Terraform configurations



# Variables
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "key_name" {}
variable "private_key_path" {}
variable "region" {
  default = "us-east-1"
}


# Provider
provider "aws" {
  region  = var.region
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
}


# DATA
data "aws_ami" "aws_ubuntu" {
  most_recent = true
  owners      = ["amazon"]

 filter {
    name   = "name"
    values = ["amzn-ami-hvm*"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}


# RESOURCES
# Ami

resource "aws_instance" "aws_ubuntu" {
  instance_type          = "t2.micro"
  ami                    = "ami-052efd3df9dad4825"
  key_name               = var.key_name
  user_data              = file("userdata.tpl")
}  


# Default VPC
resource "aws_default_vpc" "default" {

}

# Security group
resource "aws_security_group" "demo_sg" {
  name        = "demo_sg"
  description = "allow ssh on 22 & http on port 80"
  vpc_id      = aws_default_vpc.default.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"]
  }
}



# OUTPUT
output "aws_instance_public_dns" {
  value = aws_instance.aws_ubuntu.public_dns
}


Enter fullscreen mode Exit fullscreen mode
  • The variable section consists of the variables you created in the terraform.tfvars file
  • The provider section contains information of your provider, region and information which connects terraform to your AWS account. Be sure to specify the region you are making use of in AWS. In my case I am using the N.Virginia region (us-east-1)
  • The data section contains information of your instance. Data sources are like read-only references in Terraform. They aren’t resources in the sense that they create anything, but they can be referenced by actual resources to pull information from AWS where applicable.
  • The resources section contains information of your ami, VPC and security group. You can modify this depending on your use case.
  • The output section is basically what you want to be printed to the screen after your resources have been created. In this case, your instance's public dns would be printed out for you.

3. Userdata.tpl

To create your userdata.tpl file, run the below command in your terminal



touch userdata.tpl


Enter fullscreen mode Exit fullscreen mode

This file will contain the bash script which will install nginx on your instance.



#!/bin/bash
sudo apt update -y &&
sudo apt install -y nginx
echo "Hello World" > /var/www/html/index.html


Enter fullscreen mode Exit fullscreen mode

The above bash script will be automatically ran immediately the instance is created and it starts running. We are basically updating "apt", configuring NGINX to be installed on boot of the instance and instructing it to echo an "Hello World" message to us by overwriting NGINX's index.html file. var/www/html/index.html is the path to the NGINX's index.html file.

Keep in mind that you can modify the echo output to what you want. It could be echo "Hi, how are you doing?", anything of your choice.

Also, if you notice in the module.tf file, under the resources ami section, the user data file was defined. This basically links your user data file to the instance you are creating so that nginx would be installed on the instance.

Run the terraform files

Save your files and run



terraform init


Enter fullscreen mode Exit fullscreen mode

This will initialize your directory and install necessary plugins needed. It is the first command that has to be run after writing a new terraform configuration.

Image description

After initialization run



terraform validate


Enter fullscreen mode Exit fullscreen mode

The above commands checks your terraform configuration files for errors.

terraform validate

Next command to run is the terraform plan



terraform plan


Enter fullscreen mode Exit fullscreen mode

This would show you the steps or execution plan that terraform wants to take.

Image description

Next, run



terraform apply


Enter fullscreen mode Exit fullscreen mode

This command carries out the plan and creates your infrastructure for you.

Image description

Image description

You can see the output dns which you asked terraform to print to your screen.

Copy and paste the output dns on a webpage and you should see your echo output message from the bashcript you wrote earlier on.

Image description

NB: It might take a while since all the scripts have to be executed "one by one"

Running checks

Navigate to your AWS account and check under ec2 instance, your instance should be running.

Image description

If your echo message/ NGINX doesn't load when paste your instance's DNS on the web, proceed to check if Nginx is running.

In your AWS Console under instances, select your running instance

Image description
Click on the "Connect" button

Image description
Copy and paste the "example" link into your terminal

Image description

Now you're logged in, run the command



systemctl status nginx


Enter fullscreen mode Exit fullscreen mode

and you should get the below output

Image description

This verifies that nginx is running.

To exit from your instance, run the below command



exit


Enter fullscreen mode Exit fullscreen mode

Image description

And that's it!!

You can delete your resources with the below command



terraform destroy -auto-approve

Enter fullscreen mode Exit fullscreen mode




Conclusion

In this article, we deployed an Nginx web server on an ec2 instance immediately it was created, all automatically with Terraform.

Top comments (10)

Collapse
 
opshack profile image
Pooria A

Thanks, great point about user_data.

Collapse
 
kamaravichow profile image
Aravind Chowdary

This is outdated, here is the updated guide Nginx web server on EC2 instance with Terraform

Collapse
 
cloudistinct profile image
CloudistinctAB

LOL

Collapse
 
moe443 profile image
Moe

Hi, great article!
I could be wrong but I think your Terraform file misses attaching the security group to the aws_ubuntu instance, no? :)

Collapse
 
husseinalamutu profile image
Hussein Alamutu

What connects the security group and the instance is the vpc_id, an ec2 instance or any resource in aws, needs to be created in a vpc, in this case default vpc was used and a security group was created that allows ssh etc. in the same vpc to be used by the ec2 instance.

Collapse
 
cloudistinct profile image
CloudistinctAB

"ec2 instance or any resource in AWS, needs to be created in a vpc..." - Not all resources in AWS need to be created in a VPC

Thread Thread
 
husseinalamutu profile image
Hussein Alamutu • Edited

For such resources, it’s desirable to have a vpc, even when it seems like is not needed. Plus without the VPC, most times an alternative is used i.e., AWS private link

Collapse
 
barnyvic profile image
Barny victor

thanks for this

Collapse
 
cloudimole profile image
Daniel Sanya

Thanks so much for this clear and concise guideline Favour, I've just become your biggest fan. Is there a way to connect with you?

Collapse
 
cloudimole profile image
Daniel Sanya

Also, I tried this and noticed the filters under the data section really made it difficult for terraform to find the infrastructures and apply them so i removed them to make the range wider.