In this tutorial, you will learn how to automatically deploy an Nginx Web Server on an EC2 instance, with Terraform.
Prerequisites
- An active AWS account with an IAM user already created
- Text editor of your choice (VSCode Recommended)
- Terraform Installed, you should also have a basic knowldge of how it works.
- 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
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"
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.
After selecting it, Click on Create key pair
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.
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 ./
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 theterraform.tfvars file
, type in the path of your key. It should look like this./demokey.pem
. Remember to replace thedemokey
with your key's name.
2. Module.tf
To create your module.tf
file, run the below command in your terminal
touch module.tf
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
}
- 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
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
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
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.
After initialization run
terraform validate
The above commands checks your terraform configuration files for errors.
Next command to run is the terraform plan
terraform plan
This would show you the steps or execution plan that terraform wants to take.
Next, run
terraform apply
This command carries out the plan and creates your infrastructure for you.
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.
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.
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
Copy and paste the "example" link into your terminal
Now you're logged in, run the command
systemctl status nginx
and you should get the below output
This verifies that nginx is running.
To exit from your instance, run the below command
exit
And that's it!!
You can delete your resources with the below command
terraform destroy -auto-approve
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)
Thanks, great point about user_data.
This is outdated, here is the updated guide Nginx web server on EC2 instance with Terraform
LOL
Hi, great article!
I could be wrong but I think your Terraform file misses attaching the security group to the aws_ubuntu instance, no? :)
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.
"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
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
thanks for this
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?
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.