{"id":18914085,"url":"https://github.com/aws-devops-projects/terraform-3tier-architecture-aws","last_synced_at":"2025-04-09T11:10:57.092Z","repository":{"id":41459666,"uuid":"454262721","full_name":"AWS-Devops-Projects/Terraform-3tier-architecture-AWS","owner":"AWS-Devops-Projects","description":"This repository contains code to deploy 3 tier architecture to AWS using Terraform","archived":false,"fork":false,"pushed_at":"2024-05-27T15:49:14.000Z","size":130,"stargazers_count":68,"open_issues_count":3,"forks_count":220,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-02T09:06:53.236Z","etag":null,"topics":["aws","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AWS-Devops-Projects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-01T04:37:59.000Z","updated_at":"2025-03-22T04:18:37.000Z","dependencies_parsed_at":"2024-12-24T19:10:47.391Z","dependency_job_id":"7b70d90e-1ae6-44c8-a144-09c50fb310f3","html_url":"https://github.com/AWS-Devops-Projects/Terraform-3tier-architecture-AWS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWS-Devops-Projects%2FTerraform-3tier-architecture-AWS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWS-Devops-Projects%2FTerraform-3tier-architecture-AWS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWS-Devops-Projects%2FTerraform-3tier-architecture-AWS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWS-Devops-Projects%2FTerraform-3tier-architecture-AWS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AWS-Devops-Projects","download_url":"https://codeload.github.com/AWS-Devops-Projects/Terraform-3tier-architecture-AWS/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248027407,"owners_count":21035594,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","terraform"],"created_at":"2024-11-08T10:09:58.635Z","updated_at":"2025-04-09T11:10:57.041Z","avatar_url":"https://github.com/AWS-Devops-Projects.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to deploy a three-tier architecture in AWS using Terraform?\n\n### What is Terraform?\n\nTerraform is an open-source infrastructure as a code (IAC) tool that allows to create, manage \u0026 deploy the production-ready environment. Terraform codifies cloud APIs into declarative configuration files. Terraform can manage both existing service providers and custom in-house solutions.\n\n![1](https://github.com/DhruvinSoni30/Terraform-AWS-3tier-Architecture/blob/main/1.png)\n\nIn this tutorial, I will deploy a three-tier application in AWS using Terraform.\n\n![2](https://github.com/DhruvinSoni30/Terraform-AWS-3tier-Architecture/blob/main/2.png)\n\n### Prerequisites:\n\n* Basic knowledge of AWS \u0026 Terraform\n* AWS account\n* AWS Access \u0026 Secret Key\n\n\u003e In this project, I have used some variables also that I will discuss later in this article.\n\n**Step 1:- Create a file for the VPC**\n\n* Create vpc.tf file and add the below code to it\n\n  ```\n  # Creating VPC\n  resource \"aws_vpc\" \"demovpc\" {\n    cidr_block       = \"${var.vpc_cidr}\"\n    instance_tenancy = \"default\"\n  tags = {\n    Name = \"Demo VPC\"\n  }\n  }\n  ```\n  \n**Step 2:- Create a file for the Subnet**\n\n* For this project, I will create total 6 subnets for the front-end tier and back-end tier with a mixture of public \u0026 private subnet\n* Create subnet.tf file and add the below code to it\n\n  ```\n  # Creating 1st web subnet \n  resource \"aws_subnet\" \"public-subnet-1\" {\n    vpc_id                  = \"${aws_vpc.demovpc.id}\"\n    cidr_block             = \"${var.subnet_cidr}\"\n    map_public_ip_on_launch = true\n    availability_zone = \"us-east-1a\"\n  tags = {\n    Name = \"Web Subnet 1\"\n  }\n  }\n  # Creating 2nd web subnet \n  resource \"aws_subnet\" \"public-subnet-2\" {\n    vpc_id                  = \"${aws_vpc.demovpc.id}\"\n    cidr_block             = \"${var.subnet1_cidr}\"\n    map_public_ip_on_launch = true\n    availability_zone = \"us-east-1b\"\n  tags = {\n    Name = \"Web Subnet 2\"\n  }\n  }\n  # Creating 1st application subnet \n  resource \"aws_subnet\" \"application-subnet-1\" {\n    vpc_id                  = \"${aws_vpc.demovpc.id}\"\n    cidr_block             = \"${var.subnet2_cidr}\"\n    map_public_ip_on_launch = false\n    availability_zone = \"us-east-1a\"\n  tags = {\n    Name = \"Application Subnet 1\"\n  }\n  }\n  # Creating 2nd application subnet \n  resource \"aws_subnet\" \"application-subnet-2\" {\n    vpc_id                  = \"${aws_vpc.demovpc.id}\"\n    cidr_block             = \"${var.subnet3_cidr}\"\n    map_public_ip_on_launch = false\n    availability_zone = \"us-east-1b\"\n  tags = {\n    Name = \"Application Subnet 2\"\n  }\n  }\n  # Create Database Private Subnet\n  resource \"aws_subnet\" \"database-subnet-1\" {\n    vpc_id            = \"${aws_vpc.demovpc.id}\"\n    cidr_block        = \"${var.subnet4_cidr}\"\n    availability_zone = \"us-east-1a\"\n  tags = {\n    Name = \"Database Subnet 1\"\n  }\n  }\n  # Create Database Private Subnet\n  resource \"aws_subnet\" \"database-subnet-2\" {\n    vpc_id            = \"${aws_vpc.demovpc.id}\"\n    cidr_block        = \"${var.subnet5_cidr}\"\n    availability_zone = \"us-east-1a\"\n  tags = {\n    Name = \"Database Subnet 1\"\n  }\n  }\n  ```\n  \n**Step 3:- Create a file for the Internet Gateway**\n\n* Create igw.tf file and add the below code to it\n\n  ```\n  # Creating Internet Gateway \n  resource \"aws_internet_gateway\" \"demogateway\" {\n    vpc_id = \"${aws_vpc.demovpc.id}\"\n  }\n  ```\n\n**Step 4:- Create a file for the Route table**\n\n* Create route_table_public.tf file and add the below code to it\n\n  ```\n  # Creating Route Table\n  resource \"aws_route_table\" \"route\" {\n    vpc_id = \"${aws_vpc.demovpc.id}\"\n  route {\n        cidr_block = \"0.0.0.0/0\"\n        gateway_id = \"${aws_internet_gateway.demogateway.id}\"\n    }\n  tags = {\n        Name = \"Route to internet\"\n    }\n  }\n  # Associating Route Table\n  resource \"aws_route_table_association\" \"rt1\" {\n    subnet_id = \"${aws_subnet.demosubnet.id}\"\n    route_table_id = \"${aws_route_table.route.id}\"\n  }\n  # Associating Route Table\n  resource \"aws_route_table_association\" \"rt2\" {\n    subnet_id = \"${aws_subnet.demosubnet1.id}\"\n    route_table_id = \"${aws_route_table.route.id}\"\n  }\n  ```\n* In the above code, I am creating a new route table and forwarding all the requests to the 0.0.0.0/0 CIDR block.\n* I am also attaching this route table to the subnet created earlier. So, it will work as the Public Subnet\n\n**Step 5:- Create a file for EC2 instances**\n\n* Create ec2.tf file and add the below code to it\n\n  ```\n  # Creating 1st EC2 instance in Public Subnet\n  resource \"aws_instance\" \"demoinstance\" {\n    ami                         = \"ami-087c17d1fe0178315\"\n    instance_type               = \"t2.micro\"\n    count                       = 1\n    key_name                    = \"tests\"\n    vpc_security_group_ids      = [\"${aws_security_group.demosg.id}\"]\n    subnet_id                   = \"${aws_subnet.demoinstance.id}\"\n    associate_public_ip_address = true\n    user_data                   = \"${file(\"data.sh\")}\"\n  tags = {\n    Name = \"My Public Instance\"\n  }\n  }\n  # Creating 2nd EC2 instance in Public Subnet\n  resource \"aws_instance\" \"demoinstance1\" {\n    ami                         = \"ami-087c17d1fe0178315\"\n    instance_type               = \"t2.micro\"\n    count                       = 1\n    key_name                    = \"tests\"\n    vpc_security_group_ids      = [\"${aws_security_group.demosg.id}\"]\n    subnet_id                   = \"${aws_subnet.demoinstance.id}\"\n    associate_public_ip_address = true\n    user_data                   = \"${file(\"data.sh\")}\"\n  tags = {\n    Name = \"My Public Instance 2\"\n  }\n  }\n  ```\n\n* I have used the userdata to configure the EC2 instance, I will discuss data.sh file later in the article\n\n**Step 6:- Create a file for Security Group for the FrontEnd tier**\n\n* Create web_sg.tf file and add the below code to it\n\n  ```\n  # Creating Security Group \n  resource \"aws_security_group\" \"demosg\" {\n    vpc_id = \"${aws_vpc.demovpc.id}\"\n  # Inbound Rules\n  # HTTP access from anywhere\n  ingress {\n    from_port   = 80\n    to_port     = 80\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n  # HTTPS access from anywhere\n  ingress {\n    from_port   = 443\n    to_port     = 443\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n  # SSH access from anywhere\n  ingress {\n    from_port   = 22\n    to_port     = 22\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n  # Outbound Rules\n  # Internet access to anywhere\n  egress {\n    from_port   = 0\n    to_port     = 0\n    protocol    = \"-1\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n  tags = {\n    Name = \"Web SG\"\n  }\n  }\n  ```\n\n* I have opened 80,443 \u0026 22 ports for the inbound connection and I have opened all the ports for the outbound connection\n\n**Step 7:- Create a file for Security Group for the Database tier**\n\n* Create database_sg.tf file and add the below code to it\n\n  ```\n  # Create Database Security Group\n  resource \"aws_security_group\" \"database-sg\" {\n    name        = \"Database SG\"\n    description = \"Allow inbound traffic from application layer\"\n    vpc_id      = aws_vpc.demovpc.id\n  ingress {\n    description     = \"Allow traffic from application layer\"\n    from_port       = 3306\n    to_port         = 3306\n    protocol        = \"tcp\"\n    security_groups = [aws_security_group.demosg.id]\n  }\n  egress {\n    from_port   = 32768\n    to_port     = 65535\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0/0\"]\n  }\n  tags = {\n    Name = \"Database SG\"\n  }\n  }\n  ```\n* I have opened 3306 ports for the inbound connection and I have opened all the ports for the outbound connection.\n\n**Step 8:- Create a file Application Load Balancer**\n\n* Create alb.tf file and add the below code to it\n\n  ```\n  # Creating External LoadBalancer\n  resource \"aws_lb\" \"external-alb\" {\n    name               = \"External LB\"\n    internal           = false\n    load_balancer_type = \"application\"\n    security_groups    = [aws_security_group.demosg.id]\n    subnets            = [aws_subnet.public-subnet-1.id, aws_subnet.public-subnet-1.id]\n  }\n  resource \"aws_lb_target_group\" \"target-elb\" {\n    name     = \"ALB TG\"\n    port     = 80\n    protocol = \"HTTP\"\n    vpc_id   = aws_vpc.demovpc.id\n  }\n  resource \"aws_lb_target_group_attachment\" \"attachment\" {\n    target_group_arn = aws_lb_target_group.external-alb.arn\n    target_id        = aws_instance.demoinstance.id\n    port             = 80\n  depends_on = [\n    aws_instance.demoinstance,\n  ]\n  }\n  resource \"aws_lb_target_group_attachment\" \"attachment\" {\n    target_group_arn = aws_lb_target_group.external-alb.arn\n    target_id        = aws_instance.demoinstance1.id\n    port             = 80\n  depends_on = [\n    aws_instance.demoinstance1,\n  ]\n  }\n  resource \"aws_lb_listener\" \"external-elb\" {\n    load_balancer_arn = aws_lb.external-alb.arn\n    port              = \"80\"\n    protocol          = \"HTTP\"\n  default_action {\n    type             = \"forward\"\n    target_group_arn = aws_lb_target_group.external-alb.arn\n  }\n  }\n  ```\n* The above load balancer is of type external\n* Load balancer type is set to application\n* The aws_lb_target_group_attachment resource will attach our instances to the Target Group.\n* The load balancer will listen requests on port 80\n\n**Step 9:- Create a file for the RDS instance**\n\n* Create a rds.tf file and add the below code to it\n\n  ```\n  # Creating RDS Instance\n  resource \"aws_db_subnet_group\" \"default\" {\n    name       = \"main\"\n    subnet_ids = [aws_subnet.database-subnet-1.id, aws_subnet.database-subnet-1.id]\n  tags = {\n    Name = \"My DB subnet group\"\n  }\n  }\n  resource \"aws_db_instance\" \"default\" {\n    allocated_storage      = 10\n    db_subnet_group_name   = aws_db_subnet_group.default.id\n    engine                 = \"mysql\"\n    engine_version         = \"8.0.20\"\n    instance_class         = \"db.t2.micro\"\n    multi_az               = true\n    name                   = \"mydb\"\n    username               = \"username\"\n    password               = \"password\"\n    skip_final_snapshot    = true\n    vpc_security_group_ids = [aws_security_group.database-sg.id]\n  }\n  ```\n* In the above code, you need to change the value of username \u0026 password\n* multi-az is set to true for the high availability\n\n**Step 10:- Create a file for outputs**\n\n* Create outputs.tf file and add the below code to it\n\n  ```\n  # Getting the DNS of load balancer\n  output \"lb_dns_name\" {\n    description = \"The DNS name of the load balancer\"\n    value       = \"${aws_lb.external-alb.dns_name}\"\n  }\n  ```\n  \n* From the above code, I will get the DNS of the application load balancer.\n\n**Step 11:- Create a file for variable**\n\n* Create vars.tf file and add the below code to it\n\n  ```\n  # Defining CIDR Block for VPC\n  variable \"vpc_cidr\" {\n    default = \"10.0.0.0/16\"\n  }\n  # Defining CIDR Block for 1st Subnet\n  variable \"subnet_cidr\" {\n    default = \"10.0.1.0/24\"\n  }\n  # Defining CIDR Block for 2nd Subnet\n  variable \"subnet1_cidr\" {\n    default = \"10.0.2.0/24\"\n  }\n  # Defining CIDR Block for 3rd Subnet\n  variable \"subnet2_cidr\" {\n    default = \"10.0.3.0/24\"\n  }\n  # Defining CIDR Block for 3rd Subnet\n  variable \"subnet2_cidr\" {\n    default = \"10.0.4.0/24\"\n  }\n  # Defining CIDR Block for 3rd Subnet\n  variable \"subnet2_cidr\" {\n    default = \"10.0.5.0/24\"\n  }\n  # Defining CIDR Block for 3rd Subnet\n  variable \"subnet2_cidr\" {\n    default = \"10.0.6.0/24\" \n  }\n  ```\n\n**Step 12:- Create a file for user data**\n\n* Create data.sh file and add the below code to it\n\n  ```\n  #!/bin/bash\n  yum update -y\n  yum install -y httpd.x86_64\n  systemctl start httpd.service\n  systemctl enable httpd.service\n  echo \"Hello World from $(hostname -f)\" \u003e /var/www/html/index.html\n  ```\n  \n* The above code will install an apache webserver in the EC2 instances\n\nSo, now our entire code is ready. We need to run the below steps to create infrastructure.\n\n* terraform init is to initialize the working directory and downloading plugins of the provider\n* terraform plan is to create the execution plan for our code\n* terraform apply is to create the actual infrastructure. It will ask you to provide the Access Key and Secret Key in order to create the infrastructure. So, instead of hardcoding the Access Key and Secret Key, it is better to apply at the run time.\n\n\n**Step 13:- Verify the resources**\n\n* Terraform will create below resources\n\n  * VPC\n  * Application Load Balancer\n  * Public \u0026 Private Subnets\n  * EC2 instances\n  * RDS instance\n  * Route Table\n  * Internet Gateway\n  * Security Groups for Web \u0026 RDS instances\n  * Route Table\n\nOnce the resource creation finishes you can get the DNS of a load balancer and paste it into the browser and you can see load balancer will send the request to two instances.\n\nThat’s it now, you have learned how to create various resources in AWS using Terraform.\n\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faws-devops-projects%2Fterraform-3tier-architecture-aws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faws-devops-projects%2Fterraform-3tier-architecture-aws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faws-devops-projects%2Fterraform-3tier-architecture-aws/lists"}