DEV Community

Cover image for Create Apache Web Server in AWS Using Terraform
Saravanan Gnanaguru
Saravanan Gnanaguru

Posted on • Edited on

20 3 1 1 1

Create Apache Web Server in AWS Using Terraform

Table of Contents

Terraform Introduction

  • Terraform is an Infrastructure as Code (IaC) software tool created by HashiCorp.
  • Users define and provide data center infrastructure using a declarative configuration language known as HashiCorp Configuration Language (HCL).
  • Terraform manages external resources (such as public cloud infrastructure, private cloud infrastructure, network appliances, software as a service, and platform as a service) with "providers"
  • HashiCorp maintains an extensive list of official providers, and can also integrate with community-developed providers.
  • Terraform supports a number of cloud infrastructure providers such as Amazon Web Services, Microsoft Azure, IBM Cloud, Google Cloud Platform, DigitalOcean, Oracle Cloud Infrastructure, VMware vSphere, and OpenStack
  • Terraform is one of the extensively used IaC tool in the Cloud DevOps Infra automation space

Install and Configure AWS CLI

  • Install AWS CLI
  • Configure AWS CLI
  • Please note, Configuring AWS using aws configure CLI command, will write the AWS secret and access key to ~/$USER_HOME/.aws/credentials file and it will used to authenticate the terraform infra creation in AWS.

Install and Configure Terraform

Terraform setup in Linux based systems



wget https://releases.hashicorp.com/terraform/0.12.24/terraform_0.12.24_linux_amd64.zip
unzip terraform_0.12.24_linux_amd64.zip -d terraform /usr/local/bin/


Enter fullscreen mode Exit fullscreen mode

If terraform executable stored in another path, make sure the path is added in $PATH variable permanently.

AWS Infrastructure Automation

  • We will see How to automate the AWS infrastructure creation using Terraform
  • As part of the demo code, we will create a Apache webserver and run a sample website
  • Architecture of this server follows the single tier method, wherein we will create only a simple Webserver for demo purpose

Basic Terminologies in Terraform

  • Providers
    • It should be cloud provider or on-premise provider on which we will create our infrastructure and resources
  • Resources
    • This indicates the resources like virtual machines, network components, containers we spin-up on the providers
  • Tfstate file
    • This is the state of terraform infrastructure created when we run the commands terraform plan and terraform apply
    • This state file can be stored locally or in a network storage for multi developer environments

Source Code Details

  • Full source code of this tutorial available in GitHub
  • main.tf contains the beginning section of terraform code
  • So we have to define terraform with required_providers and we have mentioned aws since we are going to create infra in AWS


terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}


Enter fullscreen mode Exit fullscreen mode
  • We have already installed and configured aws cli authentication details pointing to the destination AWS account on which the infrastructure will be created
  • The configured credentials stored in the file ~/.aws.credentials
  • We need to provide the reference for the above path in shared_credentials_file value using the creds variable ```hcl

Configure the AWS Provider

provider "aws" {
region = var.region
shared_credentials_file = var.creds
profile = "default"
}

- Rest of the `main.tf` should have the resource definition required for creating a `AWS EC2` instance
- We need to have below resources for creating an EC2 instance
  1. VPC
  2. Internet Gateway
  3. Subnet
  4. Route table
  5. Security Group
and then,
  5. EC2 instance definition

```hcl


# Create a VPC
resource "aws_vpc" "app_vpc" {
  cidr_block = var.vpc_cidr

  tags = {
    Name = "app-vpc"
  }
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.app_vpc.id

  tags = {
    Name = "vpc_igw"
  }
}

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.app_vpc.id
  cidr_block        = var.public_subnet_cidr
  map_public_ip_on_launch = true
  availability_zone = "us-west-2a"

  tags = {
    Name = "public-subnet"
  }
}

resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.app_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }

  tags = {
    Name = "public_rt"
  }
}

resource "aws_route_table_association" "public_rt_asso" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_rt.id
}


Enter fullscreen mode Exit fullscreen mode

Cloud Init and User Data

  • Objective of the EC2 instance is to have the Apache Web Server installed on it, when the instance is created
  • So we are providing a shell script in user_data section to install the apache server
  • The script added in user_data section will be invoked via Cloud Init functionality when the AWS server gets created
  • So what ever the commands added in user_data section gets executed whenever the instance getting initialized
  • We can provide any kind scripts in user_data like the example below,
    1. Shell script in Unix based systems
    2. Powershell script in Windows based system
  • Terraform AWS Provider has a syntax to pass the user_data as part of aws_instance resource declaration ```hcl

resource "aws_instance" "web" {
ami = "ami-005e54dee72cc1d00"
instance_type = var.instance_type
key_name = var.instance_key
subnet_id = aws_subnet.public_subnet.id
security_groups = [aws_security_group.sg.id]

user_data = <<-EOF
#!/bin/bash
echo "*** Installing apache2"
sudo apt update -y
sudo apt install apache2 -y
echo "*** Completed Installing apache2"
EOF

tags = {
Name = "web_instance"
}

volume_tags = {
Name = "web_instance"
}
}

- `variables.tf` file should have the customised variables, a user wanted to provide before running the infra creation
- User can also define default value for each variable in the file

```hcl


variable "region" {
default = "us-west-2"
}
variable "instance_type" {}
variable "creds" {}
variable "instance_key" {}
variable "vpc_cidr" {}
variable "public_subnet_cidr" {}


Enter fullscreen mode Exit fullscreen mode
  • It is recommended to create separate tf files for separating various resources
  • So we have crreated sg.tf file for adding resource for AWS VPC security group
  • sg.tf ```hcl

resource "aws_security_group" "sg" {
name = "allow_ssh_http"
description = "Allow ssh http inbound traffic"
vpc_id = aws_vpc.app_vpc.id

ingress {
description = "SSH from VPC"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}

ingress {
description = "HTTP from VPC"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}

tags = {
Name = "allow_ssh_http"
}
}

- We can define `output.tf` file to see expected output values like `ipaddress` of instances and `hostname` etc.

- output.tf
```hcl


output "web_instance_ip" {
    value = aws_instance.web.public_ip
}


Enter fullscreen mode Exit fullscreen mode
  • Since we have the custom variables defined in our terraform file, we have provide the values for those custom variables
  • So we have to create a tfvars files and provide the custom variable values
  • User has to provide the EC2 instance pem file key name in instance_key value
  • aws.tfvars ```hcl

region = "us-west-2"
instance_type = "t2.micro"
instance_key = "aws_ec2_pem_filename"
creds = "~/.aws/credentials"
vpc_cidr = "178.0.0.0/16"
public_subnet_cidr = "178.0.10.0/24"


## *Steps to run Terraform*
- Now we will see how to run the above created terraform infrastructure automation
Enter fullscreen mode Exit fullscreen mode

terraform init
terraform plan -var-file=aws.tfvars
terraform apply -var-file=aws.tfvars -auto-approve

- Once the `terrform apply` completed successfully it will show the `public ipaddress` of the apache server as `output`

Enter fullscreen mode Exit fullscreen mode

aws_instance.web: Creation complete after 33s [id=i-07f19000878a6ec11]

Apply complete! Resources: 7 added, 0 changed, 0 destroyed.

Outputs:

web_instance_ip = "34.220.248.140"

## *Access the Webserver*
- We can access the webserver using the public IP
- Screenshot Below,

![Apache WebServer Page](https://github.com/chefgs/repo_images/blob/master/apache2page.png?raw=true)

## *Cleanup* 
- As part of learning we will also cleanup the server using the command,
Enter fullscreen mode Exit fullscreen mode

terraform destroy -var-file=aws.tfvars -auto-approve

- It shows the destruction completed console log
Enter fullscreen mode Exit fullscreen mode

Changes to Outputs:

  • web_instance_ip = "34.220.248.140" -> null aws_route_table_association.public_rt_asso: Destroying... [id=rtbassoc-085573ee447b7d0d1] aws_instance.web: Destroying... [id=i-07f19000878a6ec11] aws_route_table_association.public_rt_asso: Destruction complete after 0s aws_route_table.public_rt: Destroying... [id=rtb-04025de8f9149983a] aws_route_table.public_rt: Destruction complete after 0s aws_internet_gateway.igw: Destroying... [id=igw-06269b7b96264af8f] aws_instance.web: Still destroying... [id=i-07f19000878a6ec11, 10s elapsed] aws_internet_gateway.igw: Still destroying... [id=igw-06269b7b96264af8f, 10s elapsed] aws_internet_gateway.igw: Destruction complete after 19s aws_instance.web: Still destroying... [id=i-07f19000878a6ec11, 20s elapsed] aws_instance.web: Still destroying... [id=i-07f19000878a6ec11, 30s elapsed] aws_instance.web: Destruction complete after 30s aws_subnet.public_subnet: Destroying... [id=subnet-06304b3b7eb727669] aws_security_group.sg: Destroying... [id=sg-098709b525d3553b7] aws_security_group.sg: Destruction complete after 0s aws_subnet.public_subnet: Destruction complete after 0s aws_vpc.app_vpc: Destroying... [id=vpc-05f7555059de86cf6] aws_vpc.app_vpc: Destruction complete after 0s

Destroy complete! Resources: 7 destroyed.

.
## *Bibliography*
- [AWS Terraform Workshop](https://hashicorp.github.io/field-workshops-terraform/slides/aws/terraform-oss/index.html#1)
Enter fullscreen mode Exit fullscreen mode

Billboard image

Deploy and scale your apps on AWS and GCP with a world class developer experience

Coherence makes it easy to set up and maintain cloud infrastructure. Harness the extensibility, compliance and cost efficiency of the cloud.

Learn more

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay