> ## Documentation Index
> Fetch the complete documentation index at: https://docs.skanesgalab.my.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Praktik Produksi: VPC, 3 EC2, ALB & Secret Management

> Praktik tingkat lanjut Terraform: manajemen variabel, rahasia (.tfvars), pemisahan modul berkas, dan membuat VPC lengkap dengan 3 EC2 Instance di balik Application Load Balancer (ALB).

Di lingkungan enterprise, kode Terraform tidak pernah ditaruh dalam satu file tunggal. Standar industri membagi arsitektur menjadi beberapa berkas:

* `main.tf`: Berisi resource inti arsitektur.
* `variables.tf`: Deklarasi tipe variabel input.
* `terraform.tfvars`: Nilai konkret variabel lokal (berisi konfigurasi non-sensitif).
* `outputs.tf`: Nilai output penting yang diekspos ke publik (seperti DNS Load Balancer).

***

## 1. Manajemen Variabel & Kunci Rahasia (Secrets)

Jangan pernah menulis kunci rahasia (*secret variables*) langsung di dalam kode `main.tf`!

### Deklarasi Variabel (`variables.tf`)

```hcl theme={null}
variable "aws_region" {
  type    = string
  default = "ap-southeast-1"
}

variable "instance_count" {
  type    = number
  default = 3
}

variable "db_password" {
  type        = string
  description = "Kata sandi basis data"
  sensitive   = true # Mencegah nilai terekspos di log terminal saat plan/apply
}
```

### Menyimpan Nilai Rahasia

Ada 3 cara aman menginjeksi variabel sensitif:

1. **Menggunakan berkas `terraform.tfvars` lokal:**
   Tambahkan `terraform.tfvars` dan `*.auto.tfvars` ke dalam file `.gitignore` agar tidak pernah terunggah ke repositori GitHub!
2. **Menggunakan Environment Variable:**
   Awali variabel dengan prefix `TF_VAR_`:
   ```bash theme={null}
   export TF_VAR_db_password="SuperSecretPassword123"
   terraform apply
   ```

***

## 2. Arsitektur Proyek: VPC + 3 EC2 di Balik Application Load Balancer

Berikut topologi infrastruktur yang akan kita bangun secara otomatis:

```mermaid theme={null}
flowchart TD
    Internet["Pengguna di Internet (HTTP Port 80)"] --> ALB["AWS Application Load Balancer (ALB)\n(Tersebar di 2 Public Subnets)"]
    
    subgraph VPC["Kustom AWS VPC (10.0.0.0/16)"]
        subgraph SubnetA["Subnet Publik 1A (ap-southeast-1a)"]
            EC2_1["EC2 Instance 1 (Web 1)"]
            EC2_2["EC2 Instance 2 (Web 2)"]
        end
        subgraph SubnetB["Subnet Publik 1B (ap-southeast-1b)"]
            EC2_3["EC2 Instance 3 (Web 3)"]
        end
    end

    ALB -->|Mendistribusikan Trafik| EC2_1
    ALB -->|Mendistribusikan Trafik| EC2_2
    ALB -->|Mendistribusikan Trafik| EC2_3
```

***

## 3. Implementasi Berkas Konfigurasi

### Berkas `main.tf` (Infrastruktur Utama)

```hcl theme={null}
terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

# 1. Custom Virtual Private Cloud (VPC)
resource "aws_vpc" "custom_vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = { Name = "terraform-vpc" }
}

# 2. Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.custom_vpc.id
  tags   = { Name = "terraform-igw" }
}

# 3. Dua Subnet Publik di Availability Zone Berbeda (Syarat Mutlak AWS ALB)
resource "aws_subnet" "public_1a" {
  vpc_id                  = aws_vpc.custom_vpc.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-southeast-1a"
  map_public_ip_on_launch = true
  tags = { Name = "public-subnet-1a" }
}

resource "aws_subnet" "public_1b" {
  vpc_id                  = aws_vpc.custom_vpc.id
  cidr_block              = "10.0.2.0/24"
  availability_zone       = "ap-southeast-1b"
  map_public_ip_on_launch = true
  tags = { Name = "public-subnet-1b" }
}

# 4. Route Table Mengarah ke Internet
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.custom_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" "a" {
  subnet_id      = aws_subnet.public_1a.id
  route_table_id = aws_route_table.public_rt.id
}

resource "aws_route_table_association" "b" {
  subnet_id      = aws_subnet.public_1b.id
  route_table_id = aws_route_table.public_rt.id
}

# 5. Security Group untuk EC2 Instances
resource "aws_security_group" "ec2_sg" {
  name        = "ec2-web-sg"
  description = "Izinkan akses HTTP dari Load Balancer"
  vpc_id      = aws_vpc.custom_vpc.id

  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"]
  }
}

# 6. Membuat 3 Instance EC2 Menggunakan Fitur 'count'
resource "aws_instance" "web_servers" {
  count                  = var.instance_count
  ami                    = "ami-0df7a207adb9748c7" # Ubuntu 22.04 LTS (ap-southeast-1)
  instance_type          = "t2.micro"
  subnet_id              = count.index % 2 == 0 ? aws_subnet.public_1a.id : aws_subnet.public_1b.id
  vpc_security_group_ids = [aws_security_group.ec2_sg.id]

  # User data: Menginstal web server Nginx otomatis saat booting
  user_data = <<-EOF
              #!/bin/bash
              apt-get update -y
              apt-get install -y nginx
              echo "<h1>Halo dari Web Server Instance ke-${count.index + 1}</h1>" > /var/www/html/index.html
              systemctl start nginx
              systemctl enable nginx
              EOF

  tags = {
    Name = "web-server-${count.index + 1}"
  }
}

# 7. Application Load Balancer (ALB)
resource "aws_lb" "app_alb" {
  name               = "web-application-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.ec2_sg.id]
  subnets            = [aws_subnet.public_1a.id, aws_subnet.public_1b.id]

  tags = { Name = "production-alb" }
}

# 8. Target Group & Healthcheck
resource "aws_lb_target_group" "alb_tg" {
  name     = "web-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.custom_vpc.id

  health_check {
    path                = "/"
    healthy_threshold   = 2
    unhealthy_threshold = 3
    timeout             = 5
    interval            = 15
  }
}

# 9. Mendaftarkan ke-3 EC2 ke dalam Target Group
resource "aws_lb_target_group_attachment" "attach_instances" {
  count            = var.instance_count
  target_group_arn = aws_lb_target_group.alb_tg.arn
  target_id        = aws_instance.web_servers[count.index].id
  port             = 80
}

# 10. Listener HTTP Port 80
resource "aws_lb_listener" "http_listener" {
  load_balancer_arn = aws_lb.app_alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.alb_tg.arn
  }
}
```

***

### Berkas `outputs.tf` (Mengekspos URL Domain ALB)

```hcl theme={null}
output "load_balancer_dns_url" {
  description = "Akses website melalui DNS publik Application Load Balancer:"
  value       = "http://${aws_lb.app_alb.dns_name}"
}
```

***

## 4. Eksekusi & Pengujian Nyata

Jalankan perintah berikut:

```bash theme={null}
terraform init
terraform plan
terraform apply -auto-approve
```

Ketika proses pembuatan selesai (sekitar 2-3 menit), terminal akan mencetak URL output:

```text theme={null}
Outputs:
load_balancer_dns_url = "http://web-application-alb-xxxx.ap-southeast-1.elb.amazonaws.com"
```

Buka URL tersebut di peramban dan lakukan *refresh* beberapa kali. Kamu akan melihat tampilan bergantian secara dinamis antara:

* *"Halo dari Web Server Instance ke-1"*
* *"Halo dari Web Server Instance ke-2"*
* *"Halo dari Web Server Instance ke-3"*

Ini membuktikan bahwa seluruh jaringan VPC, perutean internet, 3 server EC2, dan Application Load Balancer telah berhasil dirakit secara 100% otomatis berbasis kode!


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.