├── provider.tf ├── ecr.tf ├── ecs.tf ├── acm.tf ├── .gitignore ├── r53.tf ├── Jenkinsfile ├── variables.tf ├── app-sg.tf ├── rds.tf ├── iam.tf ├── vpc.tf ├── eks.tf ├── parameters.tf ├── cdn.tf ├── alb.tf ├── locals.tf ├── sg.tf └── service.tf /provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | } 6 | } 7 | 8 | backend "s3" { 9 | bucket = "timing-backend-s3" 10 | key = "vpc1" 11 | region = "ap-south-1" 12 | dynamodb_table = "timing-lock" 13 | } 14 | } 15 | 16 | provider "aws" { 17 | region = "ap-south-1" 18 | } 19 | 20 | provider "aws" { 21 | region = "us-east-1" 22 | alias = "us-east-1-cdn" 23 | } 24 | 25 | -------------------------------------------------------------------------------- /ecr.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ecr_repository" "web_repo" { 2 | name = var.web_repo 3 | image_tag_mutability = "MUTABLE" 4 | 5 | image_scanning_configuration { 6 | scan_on_push = var.scan_on_push 7 | } 8 | tags = merge(local.tags, { 9 | Name = "node-web" 10 | }) 11 | } 12 | 13 | resource "aws_ecr_repository" "api_repo" { 14 | name = var.api_repo 15 | image_tag_mutability = "MUTABLE" 16 | 17 | image_scanning_configuration { 18 | scan_on_push = var.scan_on_push 19 | } 20 | tags = merge(local.tags, { 21 | Name = "node-api" 22 | }) 23 | } -------------------------------------------------------------------------------- /ecs.tf: -------------------------------------------------------------------------------- 1 | module "ecs" { 2 | source = "terraform-aws-modules/ecs/aws" 3 | cluster_name = local.name 4 | cluster_configuration = { 5 | execute_command_configuration = { 6 | logging = "OVERRIDE" 7 | log_configuration = { 8 | cloud_watch_log_group_name = "/toptal/student" 9 | } 10 | } 11 | } 12 | 13 | fargate_capacity_providers = { 14 | FARGATE = { 15 | default_capacity_provider_strategy = { 16 | weight = 50 17 | } 18 | } 19 | FARGATE_SPOT = { 20 | default_capacity_provider_strategy = { 21 | weight = 50 22 | } 23 | } 24 | } 25 | 26 | tags = local.tags 27 | 28 | } -------------------------------------------------------------------------------- /acm.tf: -------------------------------------------------------------------------------- 1 | module "acm" { 2 | source = "terraform-aws-modules/acm/aws" 3 | 4 | domain_name = "*.techietrainers.com" 5 | zone_id = "Z069840220Z2G1MXQRMAA" 6 | 7 | subject_alternative_names = [ 8 | "*.techietrainers.com" 9 | ] 10 | 11 | wait_for_validation = true 12 | 13 | tags = merge(local.tags, { 14 | Name = "techietrainers.com" 15 | }) 16 | } 17 | 18 | module "web_alb_cdn" { 19 | source = "terraform-aws-modules/acm/aws" 20 | 21 | domain_name = local.web_alb_cdn_fqdn 22 | zone_id = var.zone_id 23 | 24 | subject_alternative_names = [local.web_alb_cdn_fqdn] 25 | 26 | wait_for_validation = true 27 | 28 | tags = merge(local.tags, { 29 | Name = "web-cdn" 30 | }) 31 | providers = { 32 | aws = aws.us-east-1-cdn 33 | } 34 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | crash.*.log 11 | 12 | # Exclude all .tfvars files, which are likely to contain sensitive data, such as 13 | # password, private keys, and other secrets. These should not be part of version 14 | # control as they are data points which are potentially sensitive and subject 15 | # to change depending on the environment. 16 | *.tfvars 17 | *.tfvars.json 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # !example_override.tf 28 | 29 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 30 | # example: *tfplan* 31 | 32 | # Ignore CLI configuration files 33 | .terraformrc 34 | terraform.rc -------------------------------------------------------------------------------- /r53.tf: -------------------------------------------------------------------------------- 1 | module "alb-api-r53" { 2 | source = "terraform-aws-modules/route53/aws//modules/records" 3 | 4 | zone_name = var.zone_name 5 | records = [ 6 | { 7 | name = var.record_name_api 8 | type = "A" 9 | alias = { 10 | name = local.api_alb_dns_name 11 | zone_id = local.api_alb_zone_id 12 | } 13 | } 14 | ] 15 | } 16 | 17 | module "alb-web-r53" { 18 | source = "terraform-aws-modules/route53/aws//modules/records" 19 | 20 | zone_name = var.zone_name 21 | records = [ 22 | { 23 | name = var.record_name_web 24 | type = "A" 25 | alias = { 26 | name = local.web_alb_dns_name 27 | zone_id = local.web_alb_zone_id 28 | } 29 | } 30 | ] 31 | 32 | } 33 | 34 | module "alb_cdn_r53" { 35 | source = "terraform-aws-modules/route53/aws//modules/records" 36 | 37 | zone_name = var.zone_name 38 | records = [ 39 | { 40 | name = var.record_name_web_alb_cdn 41 | type = "A" 42 | alias = { 43 | name = local.cloudfront_distribution_domain_name 44 | zone_id = local.cloudfront_distribution_hosted_zone_id 45 | } 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | stages { 5 | stage('Clone') { 6 | steps{ 7 | script{ 8 | echo "Clone started" 9 | gitInfo = checkout scm 10 | 11 | } 12 | } 13 | } 14 | 15 | stage('Terraform Plan'){ 16 | steps{ 17 | script{ 18 | withAWS(credentials: 'aws-auth', region: "ap-south-1") { 19 | sh """ 20 | terraform init -upgrade 21 | terraform plan 22 | """ 23 | } 24 | } 25 | } 26 | } 27 | stage('Terraform Apply') { 28 | input { 29 | message "Should we continue?" 30 | ok "Yes, we should." 31 | } 32 | steps { 33 | script{ 34 | withAWS(credentials: 'aws-auth', region: "ap-south-1") { 35 | sh """ 36 | terraform apply -auto-approve 37 | """ 38 | } 39 | } 40 | } 41 | } 42 | 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "cidr" { 2 | type = string 3 | default = "10.120.0.0/16" 4 | } 5 | /* variable "private_domain_name" { 6 | default = "ap-south-1.totpal-production.local" 7 | type = string 8 | } */ 9 | 10 | variable "private_subnets" { 11 | type = list(string) 12 | default = ["10.120.1.0/24", "10.120.2.0/24"] 13 | } 14 | 15 | variable "public_subnets" { 16 | type = list(string) 17 | default = ["10.120.11.0/24", "10.120.12.0/24"] 18 | } 19 | 20 | variable "database_subnets" { 21 | type = list(string) 22 | default = ["10.120.21.0/24", "10.120.22.0/24"] 23 | } 24 | 25 | variable "web_repo" { 26 | default = "node-web" 27 | } 28 | 29 | variable "api_repo" { 30 | default = "node-api" 31 | } 32 | 33 | variable "scan_on_push" { 34 | type = bool 35 | default = false 36 | } 37 | 38 | variable "zone_name" { 39 | type = string 40 | default = "techietrainers.com" 41 | } 42 | 43 | variable "zone_id" { 44 | type = string 45 | default = "Z069840220Z2G1MXQRMAA" 46 | } 47 | variable "record_name_api" { 48 | type = string 49 | default = "api" 50 | } 51 | 52 | variable "record_name_web" { 53 | type = string 54 | default = "web" 55 | } 56 | 57 | variable "record_name_web_alb_cdn" { 58 | type = string 59 | default = "web-cdn" 60 | } -------------------------------------------------------------------------------- /app-sg.tf: -------------------------------------------------------------------------------- 1 | # resource "aws_security_group" "ecs_service_api" { 2 | # name = "${local.name}-ecs-service" 3 | # vpc_id = local.vpc_id 4 | 5 | # ingress { 6 | # protocol = "tcp" 7 | # from_port = 3000 8 | # to_port = 3000 9 | # security_groups = [local.api_security_group_id] 10 | # } 11 | # egress { 12 | # protocol = "-1" 13 | # from_port = 0 14 | # to_port = 0 15 | # cidr_blocks = ["0.0.0.0/0"] 16 | 17 | # } 18 | # tags = merge(local.tags, { 19 | # Name = "${local.name}-ecs-service" 20 | # }) 21 | # } 22 | 23 | # resource "aws_security_group" "ecs_service_web" { 24 | # name = "${local.name}-ecs-web-service" 25 | # vpc_id = local.vpc_id 26 | 27 | # ingress { 28 | # protocol = "tcp" 29 | # from_port = 3000 30 | # to_port = 3000 31 | # security_groups = [local.web_security_group_id] 32 | # } 33 | # egress { 34 | # protocol = "-1" 35 | # from_port = 0 36 | # to_port = 0 37 | # cidr_blocks = ["0.0.0.0/0"] 38 | 39 | # } 40 | # tags = merge(local.tags, { 41 | # Name = "${local.name}-ecs-web-service" 42 | # }) 43 | # } 44 | 45 | # resource "aws_security_group_rule" "rds" { 46 | # type = "ingress" 47 | # from_port = 5432 48 | # to_port = 5432 49 | # protocol = "tcp" 50 | # source_security_group_id = aws_security_group.ecs_service_api.id 51 | # security_group_id = local.rds_security_group_id 52 | # } 53 | -------------------------------------------------------------------------------- /rds.tf: -------------------------------------------------------------------------------- 1 | module "db" { 2 | source = "terraform-aws-modules/rds/aws" 3 | identifier = local.name 4 | engine = "postgres" 5 | engine_version = "14" 6 | family = "postgres14" # DB parameter group 7 | major_engine_version = "14" # DB option group 8 | instance_class = "db.t4g.micro" 9 | allocated_storage = 20 10 | max_allocated_storage = 100 11 | 12 | db_name = "node_app" 13 | username = "developer" 14 | port = 5432 15 | multi_az = false 16 | db_subnet_group_name = local.database_subnet_group_name 17 | vpc_security_group_ids = [local.rds_security_group_id] 18 | create_cloudwatch_log_group = true 19 | backup_retention_period = 3 20 | publicly_accessible = true 21 | create_random_password = false 22 | password = random_password.master.result 23 | tags = local.tags 24 | } 25 | 26 | resource "random_password" "master" { 27 | length = 16 28 | special = true 29 | override_special = "_!%^" 30 | } 31 | 32 | resource "aws_secretsmanager_secret" "password" { 33 | name = "totpal/student/rds-password" 34 | recovery_window_in_days = 0 35 | tags = local.tags 36 | } 37 | 38 | resource "aws_secretsmanager_secret_version" "password" { 39 | secret_id = aws_secretsmanager_secret.password.id 40 | secret_string = random_password.master.result 41 | } -------------------------------------------------------------------------------- /iam.tf: -------------------------------------------------------------------------------- 1 | # resource "aws_iam_role" "ecs_task_execution" { 2 | # name = "${local.name}-ECSTaskExecution" 3 | 4 | # assume_role_policy = data.aws_iam_policy_document.ecs_trust.json 5 | # tags = merge(local.tags, { 6 | # Name = "${local.name}-ECSTaskExecution" 7 | # }) 8 | # } 9 | 10 | # resource "aws_iam_role" "ecs_task" { 11 | # name = "${local.name}-ECSTask" 12 | 13 | # assume_role_policy = data.aws_iam_policy_document.ecs_trust.json 14 | # tags = merge(local.tags, { 15 | # Name = "${local.name}-ECSTask" 16 | # }) 17 | # } 18 | 19 | # resource "aws_iam_policy" "toptal_ecs_task_execution" { 20 | # name = "${local.name}-ecs-task-execution" 21 | # description = "Policy that allows Stitcher ECS task to perform action" 22 | 23 | # policy = data.aws_iam_policy_document.rds_secret.json 24 | # tags = merge(local.tags, { 25 | # Name = "${local.name}-ecs-task-execution" 26 | # }) 27 | # } 28 | 29 | # resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy_attachment" { 30 | # role = aws_iam_role.ecs_task_execution.name 31 | # policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" 32 | # } 33 | 34 | # resource "aws_iam_role_policy_attachment" "ecs_task_role_policy_attachment_rds_secret" { 35 | # role = aws_iam_role.ecs_task_execution.name 36 | # policy_arn = aws_iam_policy.toptal_ecs_task_execution.arn 37 | # } 38 | 39 | # resource "aws_cloudwatch_log_group" "ecs-api" { 40 | # name = "/ecs/toptal/api" 41 | 42 | # tags = merge(local.tags, { 43 | # Name = local.name 44 | # }) 45 | # } 46 | 47 | # resource "aws_cloudwatch_log_group" "ecs-web" { 48 | # name = "/ecs/toptal/web" 49 | 50 | # tags = merge(local.tags, { 51 | # Name = local.name 52 | # }) 53 | # } 54 | 55 | -------------------------------------------------------------------------------- /vpc.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | source = "terraform-aws-modules/vpc/aws" 3 | name = local.name 4 | cidr = var.cidr 5 | azs = ["${local.region}a", "${local.region}b"] 6 | private_subnets = var.private_subnets 7 | public_subnets = var.public_subnets 8 | database_subnets = var.database_subnets 9 | 10 | create_database_subnet_group = true 11 | 12 | enable_dns_hostnames = true 13 | enable_dns_support = true 14 | 15 | enable_nat_gateway = true 16 | single_nat_gateway = true 17 | 18 | default_vpc_enable_dns_hostnames = true 19 | enable_dhcp_options = true 20 | #dhcp_options_domain_name = "${local.region}.${var.private_domain_name}" 21 | dhcp_options_domain_name_servers = ["AmazonProvidedDNS"] 22 | 23 | default_network_acl_tags = { Name = "${local.name}-default" } 24 | manage_default_network_acl = true 25 | 26 | manage_default_route_table = true 27 | default_route_table_tags = { Name = "${local.name}-default" } 28 | 29 | manage_default_security_group = true 30 | default_security_group_tags = { Name = "${local.name}-default" } 31 | default_security_group_name = "${local.name}-default" 32 | database_subnet_tags = { Name = "database-subnet-${local.name}" } 33 | # public_subnet_tags = { Name = "public-subnet-${local.name}" } 34 | # private_subnet_tags = { Name = "private-subnet-${local.name}" } 35 | 36 | private_subnet_tags_per_az = { 37 | az1 = { 38 | Name = "${data.aws_availability_zones.available.names[0]}-private-subnet-${local.name}" 39 | 40 | } 41 | az2 = { 42 | Name = "${data.aws_availability_zones.available.names[1]}-private-subnet-${local.name}" 43 | } 44 | } 45 | 46 | public_subnet_tags_per_az = { 47 | az1 = { 48 | Name = "${data.aws_availability_zones.available.names[0]}-public-subnet-${local.name}" 49 | 50 | } 51 | az2 = { 52 | Name = "${data.aws_availability_zones.available.names[1]}-public-subnet-${local.name}" 53 | } 54 | } 55 | 56 | tags = local.tags 57 | } 58 | -------------------------------------------------------------------------------- /eks.tf: -------------------------------------------------------------------------------- 1 | # module "eks" { 2 | # source = "./modules/terraform-aws-eks" 3 | 4 | # cluster_name = "toptal-cluster" 5 | # cluster_version = "1.24" 6 | 7 | # cluster_endpoint_public_access = true 8 | 9 | # cluster_addons = { 10 | # coredns = { 11 | # most_recent = true 12 | # } 13 | # kube-proxy = { 14 | # most_recent = true 15 | # } 16 | # vpc-cni = { 17 | # most_recent = true 18 | # } 19 | # } 20 | 21 | # vpc_id = local.vpc_id 22 | # subnet_ids = local.private_subnets 23 | # control_plane_subnet_ids = local.private_subnets 24 | 25 | # eks_managed_node_groups = { 26 | # blue = {} 27 | # green = { 28 | # min_size = 1 29 | # max_size = 10 30 | # desired_size = 1 31 | 32 | # instance_types = ["t3.large"] 33 | # capacity_type = "SPOT" 34 | # } 35 | # } 36 | 37 | # aws_auth_users = [ 38 | # { 39 | # userarn = "arn:aws:iam::752692907119:user/eks-admin" 40 | # username = "eks-admin" 41 | # groups = ["system:masters"] 42 | # } 43 | # ] 44 | 45 | # tags = merge(local.tags, { 46 | # Name = "toptal-cluster" 47 | # }) 48 | 49 | # } 50 | 51 | /* resource "aws_autoscaling_policy" "example" { 52 | # ... other configuration ... 53 | depends_on 54 | for_each = toset(module.eks.eks_managed_node_groups_autoscaling_group_names) 55 | name = "dynamic-policy-${each.value}" 56 | policy_type = "TargetTrackingScaling" 57 | target_tracking_configuration { 58 | predefined_metric_specification { 59 | predefined_metric_type = "ASGAverageCPUUtilization" 60 | } 61 | 62 | target_value = 40.0 63 | } 64 | autoscaling_group_name = each.value 65 | } */ 66 | 67 | /* module "my_scaling_policy" { 68 | source = "terraform-aws-modules/autoscaling/aws" 69 | 70 | name = "my-scaling-policy" 71 | resource_id = module.my_node_group.node_group_arn 72 | scalable_dimension = "ecs:service:DesiredCount" 73 | min_capacity = 2 74 | max_capacity = 10 75 | target_value = 50 76 | } */ -------------------------------------------------------------------------------- /parameters.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_parameter" "vpc_id" { 2 | name = "/toptal/vpc/vpc_id" 3 | description = "TOPTAL PROD VPC ID" 4 | type = "String" 5 | value = local.vpc_id 6 | tags = local.tags 7 | } 8 | 9 | resource "aws_ssm_parameter" "private_subnets" { 10 | name = "/toptal/vpc/private_subnets" 11 | type = "StringList" 12 | value = join(",", local.private_subnets) 13 | tags = local.tags 14 | } 15 | resource "aws_ssm_parameter" "api_alb_security_group_id" { 16 | name = "/toptal/api-alb/security_group_id" 17 | type = "String" 18 | value = local.api_security_group_id 19 | tags = local.tags 20 | } 21 | 22 | resource "aws_ssm_parameter" "web_alb_security_group_id" { 23 | name = "/toptal/api-web/security_group_id" 24 | type = "String" 25 | value = local.web_security_group_id 26 | tags = local.tags 27 | } 28 | 29 | resource "aws_ssm_parameter" "rds_security_group_id" { 30 | name = "/toptal/rds/security_group_id" 31 | type = "String" 32 | value = local.rds_security_group_id 33 | tags = local.tags 34 | } 35 | 36 | resource "aws_ssm_parameter" "rds_secret_arn" { 37 | name = "/toptal/rds/rds_secret_arn" 38 | type = "String" 39 | value = local.rds_secret_arn 40 | tags = local.tags 41 | } 42 | 43 | resource "aws_ssm_parameter" "rds_endpoint" { 44 | name = "/toptal/rds/rds_endpoint" 45 | type = "String" 46 | value = local.rds_endpoint 47 | tags = local.tags 48 | } 49 | 50 | resource "aws_ssm_parameter" "ecs_cluster_id" { 51 | name = "/toptal/ecs/ecs_cluster_id" 52 | type = "String" 53 | value = local.ecs_cluster_id 54 | tags = local.tags 55 | } 56 | 57 | resource "aws_ssm_parameter" "api_target_group_arn" { 58 | name = "/toptal/alb/api_target_group_arn" 59 | type = "String" 60 | value = local.api_target_group_arn 61 | tags = local.tags 62 | } 63 | 64 | resource "aws_ssm_parameter" "web_target_group_arn" { 65 | name = "/toptal/alb/web_target_group_arn" 66 | type = "String" 67 | value = local.web_target_group_arn 68 | tags = local.tags 69 | } -------------------------------------------------------------------------------- /cdn.tf: -------------------------------------------------------------------------------- 1 | module "cdn" { 2 | source = "terraform-aws-modules/cloudfront/aws" 3 | aliases = ["${local.web_alb_cdn_fqdn}"] 4 | comment = "Cloudfront to server WEB ALB" 5 | origin = { 6 | web-alb = { 7 | domain_name = local.web_alb_dns_name 8 | custom_origin_config = { 9 | http_port = 80 10 | origin_protocol_policy = "http-only" 11 | https_port = 443 12 | origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"] 13 | } 14 | } 15 | } 16 | 17 | default_cache_behavior = { 18 | target_origin_id = "web-alb" 19 | viewer_protocol_policy = "redirect-to-https" 20 | allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] 21 | cached_methods = ["GET", "HEAD", "OPTIONS"] 22 | } 23 | viewer_certificate = { 24 | acm_certificate_arn = local.cdn_certificate_arn 25 | ssl_support_method = "sni-only" 26 | minimum_protocol_version = "TLSv1_2016" 27 | } 28 | enabled = true 29 | is_ipv6_enabled = true 30 | 31 | geo_restriction = { 32 | restriction_type = "none" 33 | } 34 | tags = merge(local.tags, { 35 | Name = "web-cdn" 36 | }) 37 | } 38 | # module "cdn" { 39 | # source = "terraform-aws-modules/cloudfront/aws" 40 | # aliases = ["${var.record_name_web_alb_cdn}.${var.zone_name}"] 41 | # comment = "Cloudfront to server WEB ALB" 42 | # origin = { 43 | # web-alb = { 44 | # domain_name = local.web_alb_dns_name 45 | # custom_origin_config = { 46 | # https_port = 443 47 | # origin_protocol_policy = "https-only" 48 | # origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"] 49 | # } 50 | # } 51 | # } 52 | 53 | # default_cache_behavior = { 54 | # target_origin_id = "web-alb" 55 | # viewer_protocol_policy = "redirect-to-https" 56 | # allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] 57 | # cached_methods = ["GET", "HEAD", "OPTIONS"] 58 | # } 59 | # viewer_certificate = { 60 | # acm_certificate_arn = local.cdn_certificate_arn 61 | # ssl_support_method = "sni-only" 62 | # } 63 | # enabled = true 64 | 65 | # geo_restriction = { 66 | # restriction_type = "none" 67 | # } 68 | # tags = merge(local.tags, { 69 | # Name = "toptal-web-alb" 70 | # }) 71 | # } -------------------------------------------------------------------------------- /alb.tf: -------------------------------------------------------------------------------- 1 | module "alb-api" { 2 | source = "terraform-aws-modules/alb/aws" 3 | name = "toptal-api-alb" 4 | 5 | load_balancer_type = "application" 6 | vpc_id = local.vpc_id 7 | subnets = local.public_subnets 8 | security_groups = ([local.api_security_group_id]) 9 | create_security_group = false 10 | target_groups = [ 11 | { 12 | name_prefix = "api-" 13 | backend_protocol = "HTTP" 14 | backend_port = 80 15 | target_type = "ip" 16 | deregistration_delay = 0 17 | health_check = { 18 | healthy_threshold = 2 19 | unhealthy_threshold = 2 20 | timeout = "5" 21 | path = "/api/status" 22 | protocol = "HTTP" 23 | interval = 10 24 | matcher = "200" 25 | } 26 | } 27 | ] 28 | target_group_tags = merge(local.tags, { 29 | Name = "toptal-api-alb" 30 | }) 31 | 32 | https_listeners = [ 33 | { 34 | port = 443 35 | protocol = "HTTPS" 36 | certificate_arn = local.acm_certificate_arn 37 | target_group_index = 0 38 | } 39 | ] 40 | 41 | tags = local.tags 42 | } 43 | 44 | module "alb-web" { 45 | source = "terraform-aws-modules/alb/aws" 46 | name = "toptal-api-web" 47 | 48 | load_balancer_type = "application" 49 | vpc_id = local.vpc_id 50 | subnets = local.public_subnets 51 | security_groups = ([local.web_security_group_id]) 52 | create_security_group = false 53 | target_groups = [ 54 | { 55 | name_prefix = "web-" 56 | backend_protocol = "HTTP" 57 | backend_port = 80 58 | target_type = "ip" 59 | deregistration_delay = 0 60 | health_check = { 61 | healthy_threshold = 2 62 | unhealthy_threshold = 2 63 | timeout = "5" 64 | path = "/health" 65 | protocol = "HTTP" 66 | interval = 10 67 | matcher = "200" 68 | } 69 | } 70 | ] 71 | target_group_tags = merge(local.tags, { 72 | Name = "toptal-web" 73 | }) 74 | 75 | http_tcp_listeners = [ 76 | { 77 | port = 80 78 | protocol = "HTTP" 79 | target_group_index = 0 80 | } 81 | ] 82 | 83 | https_listeners = [ 84 | { 85 | port = 443 86 | protocol = "HTTPS" 87 | certificate_arn = local.acm_certificate_arn 88 | target_group_index = 0 89 | } 90 | ] 91 | 92 | tags = local.tags 93 | } -------------------------------------------------------------------------------- /locals.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | name = "toptal-student" 3 | region = "ap-south-1" 4 | tags = { 5 | Terraform = "true" 6 | Environment = "PROD" 7 | System = "toptal" 8 | Component = "student" 9 | Type = "infra" 10 | } 11 | } 12 | 13 | locals { 14 | vpc_id = module.vpc.vpc_id 15 | public_subnets = module.vpc.public_subnets 16 | private_subnets = module.vpc.private_subnets 17 | database_subnet_group_name = module.vpc.database_subnet_group_name 18 | rds_security_group_id = module.rds-sg.security_group_id 19 | api_security_group_id = module.alb-api-sg.security_group_id 20 | web_security_group_id = module.alb-web-sg.security_group_id 21 | acm_certificate_arn = module.acm.acm_certificate_arn 22 | cdn_certificate_arn = module.web_alb_cdn.acm_certificate_arn 23 | api_alb_dns_name = module.alb-api.lb_dns_name 24 | web_alb_dns_name = module.alb-web.lb_dns_name 25 | api_alb_zone_id = module.alb-api.lb_zone_id 26 | web_alb_zone_id = module.alb-web.lb_zone_id 27 | rds_secret_arn = aws_secretsmanager_secret.password.arn 28 | rds_endpoint = split(":", module.db.db_instance_endpoint)[0] 29 | ecs_cluster_id = module.ecs.cluster_id 30 | api_target_group_arn = join(",", module.alb-api.target_group_arns) 31 | web_target_group_arn = join(",", module.alb-web.target_group_arns) 32 | cloudfront_distribution_domain_name = module.cdn.cloudfront_distribution_domain_name 33 | cloudfront_distribution_hosted_zone_id = module.cdn.cloudfront_distribution_hosted_zone_id 34 | web_alb_cdn_fqdn = "${var.record_name_web_alb_cdn}.${var.zone_name}" 35 | } 36 | 37 | 38 | # env_vars_web = [ 39 | # { 40 | # "name" : "PORT", 41 | # "value" : "3000" 42 | # }, 43 | # { 44 | # "name" : "API_HOST", 45 | # "value" : "https://api.techietrainers.com" 46 | # } 47 | # ] 48 | # } 49 | 50 | /* output "eks_managed_node_groups_autoscaling_group_names" { 51 | description = "List of the autoscaling group names created by EKS managed node groups" 52 | value = module.eks.eks_managed_node_groups_autoscaling_group_names 53 | } */ 54 | 55 | data "aws_availability_zones" "available" {} 56 | # data "aws_ip_ranges" "cloudfront" { 57 | # services = ["cloudfront"] 58 | # } 59 | 60 | # data "http" "cloudfront_ips" { 61 | # url = "https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips" 62 | # } 63 | 64 | # locals { 65 | # cloudfront_ips = data.http.cloudfront_ips 66 | 67 | # } 68 | 69 | # output "cloudfront_ip" { 70 | # value = local.cloudfront_ips 71 | # } -------------------------------------------------------------------------------- /sg.tf: -------------------------------------------------------------------------------- 1 | 2 | 3 | module "rds-sg" { 4 | source = "terraform-aws-modules/security-group/aws" 5 | name = "totpal-student-rds" 6 | description = "Security group which is used to attach to RDS" 7 | vpc_id = local.vpc_id 8 | use_name_prefix = false 9 | ingress_with_source_security_group_id = [ 10 | 11 | ] 12 | egress_with_cidr_blocks = [ 13 | { 14 | from_port = 0 15 | to_port = 0 16 | protocol = "-1" 17 | description = "Allow all outbound" 18 | cidr_blocks = "0.0.0.0/0" 19 | 20 | }, 21 | ] 22 | tags = merge(local.tags, { 23 | Name = "toptal-rds" 24 | }) 25 | } 26 | 27 | module "alb-api-sg" { 28 | source = "terraform-aws-modules/security-group/aws" 29 | name = "toptal-api-alb" 30 | description = "Security group which is used to attach to API ALB" 31 | vpc_id = local.vpc_id 32 | use_name_prefix = false 33 | 34 | ingress_with_cidr_blocks = [ 35 | { 36 | from_port = 443 37 | to_port = 443 38 | protocol = 6 39 | description = "Allow 443 from internet" 40 | cidr_blocks = "0.0.0.0/0" 41 | } 42 | ] 43 | 44 | egress_with_cidr_blocks = [ 45 | { 46 | from_port = 0 47 | to_port = 0 48 | protocol = "-1" 49 | description = "Allow all outbound" 50 | cidr_blocks = "0.0.0.0/0" 51 | }, 52 | ] 53 | tags = merge(local.tags, { 54 | Name = "toptal-api-alb" 55 | }) 56 | } 57 | 58 | module "alb-web-sg" { 59 | source = "terraform-aws-modules/security-group/aws" 60 | name = "toptal-web-alb" 61 | description = "Security group which is used to attach to Web ALB" 62 | vpc_id = local.vpc_id 63 | use_name_prefix = false 64 | #ingress_cidr_blocks = local.cloudfront_ips 65 | # ingress_rules = [ 66 | # { 67 | # description = "HTTP traffic from CloudFront" 68 | # from_port = 80 69 | # to_port = 80 70 | # protocol = "tcp" 71 | # } 72 | # ] 73 | ingress_with_cidr_blocks = [ 74 | { 75 | from_port = 443 76 | to_port = 443 77 | protocol = 6 78 | description = "Allow 443 from internet" 79 | cidr_blocks = "0.0.0.0/0" 80 | }, 81 | { 82 | from_port = 80 83 | to_port = 80 84 | protocol = 6 85 | description = "Allow 443 from internet" 86 | cidr_blocks = "0.0.0.0/0" 87 | } 88 | ] 89 | egress_with_cidr_blocks = [ 90 | { 91 | from_port = 0 92 | to_port = 0 93 | protocol = "-1" 94 | description = "Allow all outbound" 95 | cidr_blocks = "0.0.0.0/0" 96 | }, 97 | ] 98 | tags = merge(local.tags, { 99 | Name = "toptal-web-alb" 100 | }) 101 | } 102 | 103 | /* module "node-sg" { 104 | source = "./modules/terraform-aws-security-group" 105 | name = "totpal-student-rds" 106 | description = "Security group which is used to attach to EKS n" 107 | vpc_id = local.vpc_id 108 | use_name_prefix = false 109 | ingress_with_source_security_group_id = [ 110 | 111 | ] 112 | egress_with_cidr_blocks = [ 113 | { 114 | from_port = 0 115 | to_port = 0 116 | protocol = "-1" 117 | description = "Allow all outbound" 118 | cidr_blocks = "0.0.0.0/0" 119 | 120 | }, 121 | ] 122 | tags = merge(local.tags, { 123 | Name = "toptal-student-rds" 124 | }) 125 | } */ 126 | 127 | -------------------------------------------------------------------------------- /service.tf: -------------------------------------------------------------------------------- 1 | # resource "aws_ecs_task_definition" "api" { 2 | # family = "${local.name}-api-task-definition" 3 | # network_mode = "awsvpc" 4 | # requires_compatibilities = ["FARGATE"] 5 | # cpu = 1024 6 | # memory = 2048 7 | # execution_role_arn = aws_iam_role.ecs_task_execution.arn 8 | # task_role_arn = aws_iam_role.ecs_task.arn 9 | # container_definitions = <