Launching WebServer on AWS using Terraform and Jenkins
Amazon Web Service (AWS) is a platform provided by Amazon for on demand Cloud Computing. But creating any infrastructure using CLI or GUI is not a good option.
So, I have created a webserver on top of aws instance with the help of Terraform and Jenkins. Almost every thing is automated.
For understanding the project, you need some prior knowledge.
Before starting with the project, you should have following things
- AWS account
- IAM user created
- AWS CLI tool installed
- Terraform installed
- Environment variable set for Terraform
AWS Configure
aws configure
AWS Access Key ID [****************L4P7]:
AWS Secret Access Key [****************4PEs]:
Default region name [ap-south-1]:
Default output format [None]:
Terraform
provider "aws" {
region = "ap-south-1"
profile = "IAM_username"
}
Here, we provide the region where we want to use the services and we also provide IAM user.
- Creating Key
resource "tls_private_key" "prkey" {
algorithm = "RSA"
}resource "aws_key_pair" "webkey1" {
key_name = "webkey1"
public_key = tls_private_key.prkey.public_key_openssh
}
Here, we create the key pair which will help to login.
2. Creating Security Group
resource "aws_security_group" "allow_80" {
name = "allow_80"
description = "Allow port 80"ingress {
description = "incoming http"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}ingress {
description = "incoming ssh"
from_port = 22
to_port = 22
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"]
}tags = {
Name = "allow_80"
}
}
Here, we will allow different ports for different purpose
- Port 80 for webserver
- Port 22 for remote login i.e. SSH
3. Creating Instance
resource "aws_instance" "webserver" {
ami = "ami-052c08d70def0ac62"
instance_type = "t2.micro"
availability_zone = aws_ebs_volume.web_volume.availability_zone
key_name = "webkey1"
security_groups = ["${aws_security_group.allow_80.name}"]tags = {
Name = "WebOS"
}
}
This will create instance.
4. Creating EBS
resource "aws_ebs_volume" "web_volume" {
availability_zone = "ap-south-1a"
size = 1
tags = {
Name = "web_volume"
}
}
We will create this EBS storage to store web pages permanently
5. Attaching Volume
resource "aws_volume_attachment" "ebs_att" {
device_name = "/dev/sdr"
volume_id = aws_ebs_volume.web_volume.id
instance_id = aws_instance.webserver.id
force_detach = true
}
We attach the volume to out instance
6. Creating S3 Bucket
resource "aws_s3_bucket" "s3bucket" {
bucket = "poiuytrewqlkjhgfdsa"
acl = "private"
tags = {
Name = "s3bucket"
}
}resource "aws_s3_bucket_public_access_block" "s3type" {
bucket = "${aws_s3_bucket.s3bucket.id}"
block_public_acls = true
block_public_policy = true
}resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
depends_on = [aws_s3_bucket.s3bucket]
}data "aws_iam_policy_document" "s3_policy" {
statement {
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.s3bucket.arn}/*"]
principals {
type = "AWS"
identifiers = [ aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn ]
}
}
}resource "aws_s3_bucket_policy" "policy" {
bucket = aws_s3_bucket.s3bucket.id
policy = data.aws_iam_policy_document.s3_policy.json
}
Here, we create S3 bucket for storing images and prohibit users from doing any activity on s3.
By creating policy we only allow CloudFron to read objects from S3.
7. Creating CloudFront
locals {
s3_origin_id = "myS3Origin"
}resource "aws_cloudfront_distribution" "webcloud" {
origin {
domain_name = "${aws_s3_bucket.s3bucket.bucket_regional_domain_name}"
origin_id = "${local.s3_origin_id}"
s3_origin_config{
origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
}
}
enabled = true
is_ipv6_enabled = true
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${local.s3_origin_id}"forwarded_values {
query_string = falsecookies {
forward = "none"
}
}viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}restrictions {
geo_restriction {
restriction_type = "none"
}
}viewer_certificate {
cloudfront_default_certificate = true
}
}resource "null_resource" "wepip" {
provisioner "local-exec" {
command = "echo ${aws_instance.webserver.public_ip} > publicip.txt"
}
}
This will create a CloudFront Service that provides as a CDN.
8. Mounting Volume and Installing required softwares
resource "null_resource" "imp_soft" {
depends_on = [aws_instance.webserver,
aws_volume_attachment.ebs_att]
connection {
type = "ssh"
user = "ec2-user"
private_key =tls_private_key.prkey.private_key_pem
host = aws_instance.webserver.public_ip
}provisioner "remote-exec" {
inline = [
"sudo yum install httpd -y",
"sudo yum install php -y",
"sudo systemctl start httpd",
"sudo systemctl enable httpd",
"sudo yum install git -y",
"sudo setenforce 0"
]
}
}resource "null_resource" "mount" {
depends_on = [aws_volume_attachment.ebs_att,
null_resource.imp_soft]
connection {
type = "ssh"
user = "ec2-user"
private_key =tls_private_key.prkey.private_key_pem
host = aws_instance.webserver.public_ip
}provisioner "remote-exec" {
inline = [
"sudo mkfs.ext4 /dev/xvdr",
"sudo mount /dev/xvdr /var/www/html",
"sudo rm -rf /var/www/html/*",
"sudo git clone https://github.com/Rajnish-TheGreat/web_code.git /var/www/html/"
]
}
}
Remote ssh login is performed and the volume is mount to /var/www/html and the website code is copied to the same folder. Now, our code is ready to be compiled
Terraform With Jenkins
This Job automatically downloads the Terraform code from the GitHub and build the infrastructure.
Uploading image to S3
- Install S3 Publisher plugin
Go to Manage Jenkins and select Configure System. look for Amazon S3 Profiles.
Please provide a profile name, access key and secret access key for your AWS account. also, Create an IAM user with the relevant S3 Permissions.
- Configure job
Website
This is final output of the very basic website which is almost fully automated.
The amount of error, I encountered while making this project was too much. So, I may have missed to explain few steps
In case of any queries or suggestions, DM me or comment below.
Thank You for your valuable time