Introduction
Tutorial ini adalah kelanjutan dari https://blog.igunawan.com/setup-gcp-untuk-connect-cli-dengan-service-account-impersonation/ yang membahas setup awal kredensial GCP. Anggap kita sudah:
- ✅ Punya service account
learn-devops-engineer@PROJECT_ID.iam.gserviceaccount.com - ✅ Akun Google kita sudah punya role
Service Account Token Creator+Service Account Userdi SA tersebut - ✅
gcloud auth application-default login --impersonate-service-account=…sukses print token
Jika Belum silahkan baca artikel sebelumnya https://blog.igunawan.com/setup-gcp-untuk-connect-cli-dengan-service-account-impersonation/
Result
VPC dev-hub-vpc (region asia-southeast2) ├─ hub-subnet-public (10.30.0.0/24) — VM jump host di sini └─ hub-subnet-private (10.30.16.0/24) — VM app private di sini Cloud Router + Cloud NAT — outbound internet untuk private subnet Firewall: ├─ allow-internal — intra-VPC semua protokol (10.0.0.0/8) ├─ allow-iap-ssh — SSH lewat IAP dari 35.235.240.0/20 ├─ allow-http — HTTP (80) untuk VM tag 'http-server' ├─ allow-https — HTTPS (443) untuk VM tag 'https-server' └─ allow-ssh-internet — SSH langsung dari IP whitelist (DEV ONLY) Compute Engine: ├─ vm-public-jump (e2-micro, Ubuntu 22.04, external IP) — SSH entry point ├─ vm-private-app (e2-micro, Ubuntu 22.04, no external IP) └─ vm-private-app-2 (e2-micro, Ubuntu 22.04, no external IP) SSH access: ├─ ssh jump — langsung ke jump host └─ ssh private-app — chained via jump host ke private VM

Struktur Project
days-6-gcp-terragrunt/
├── modules/gcp/
│ ├── vpc/
│ │ ├── main.tf ← VPC + subnets + Cloud Router + NAT + 5 firewall rules
│ │ ├── variables.tf ← input flags (enable_nat, enable_firewall, dll)
│ │ └── outputs.tf ← network_id, subnet self_links, NAT id
│ └── compute/
│ ├── main.tf ← google_compute_instance (for_each VMs)
│ ├── variables.tf ← list of VMs (flexible)
│ └── outputs.tf ← vm_summary map (internal_ip, external_ip, dll)
└── live/gcp/
├── root.hcl ← provider + impersonation
├── dev/
│ ├── vpc/terragrunt.hcl ← input VPC dev
│ └── compute/terragrunt.hcl ← input VM dev (2 VMs)
└── prod/
├── vpc/terragrunt.hcl ← input VPC prod (mirror dev)
└── compute/ ← (opsional, mirror dev)
Step 1 — Provisioning VPC + Subnets + NAT + Firewall
1.1 Cek file live/gcp/dev/vpc/terragrunt.hcl
Pastikan isinya seperti ini:
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "${get_terragrunt_dir()}/../../../../modules/gcp/vpc"
}
inputs = {
name = "dev-hub-vpc"
region = "asia-southeast2"
subnets = [
{
name = "hub-subnet-public"
cidr = "10.30.0.0/24"
},
{
name = "hub-subnet-private"
cidr = "10.30.16.0/24"
},
]
# Cloud NAT hanya untuk subnet private
subnets_private = ["hub-subnet-private"]
# Enable semua fitur
enable_nat = true
enable_firewall = true
enable_public_web_firewall = true
# SSH langsung dari internet — DEV ONLY
enable_ssh_internet = true
ssh_internet_source_ranges = ["xx.xx.xx.xx/32"] # GANTI dengan IP rumah kita
}
Cara cek IP yang kita gunakan entah itu thetering internet rumah:
curl -s https://api.ipify.org && echo
1.2 Inisialisasi & plan
cd live/gcp/dev/vpc terragrunt init # download module + provider terragrunt plan # review: akan create 9 resource (VPC + 2 subnet + router + NAT + 5 firewall)
Expected plan output:
Plan: 9 to add, 0 to change, 0 to destroy. Resources: + google_compute_network.this "dev-hub-vpc" + google_compute_subnetwork.this["hub-subnet-public"] + google_compute_subnetwork.this["hub-subnet-private"] + google_compute_router.this[0] "dev-hub-vpc-router" + google_compute_router_nat.this[0] "dev-hub-vpc-nat" + google_compute_firewall.allow_internal[0] "dev-hub-vpc-allow-internal" + google_compute_firewall.allow_iap_ssh[0] "dev-hub-vpc-allow-iap-ssh" + google_compute_firewall.allow_http[0] "dev-hub-vpc-allow-http" + google_compute_firewall.allow_https[0] "dev-hub-vpc-allow-https" + google_compute_firewall.allow_ssh_internet[0] "dev-hub-vpc-allow-ssh-internet"
1.3 Apply
terragrunt apply # Ketik "yes" saat prompt
Tunggu ±30 detik sampai apply selesai.
1.4 Verifikasi
# VPC & subnet gcloud compute networks list --project=$PROJECT_ID gcloud compute networks subnets list --project=$PROJECT_ID --regions=asia-southeast2 # NAT gcloud compute routers list --project=$PROJECT_ID gcloud compute routers nats list --project=$PROJECT_ID --router=dev-hub-vpc-router --region=asia-southeast2 # Firewall (semua rule dev-hub-vpc-*) gcloud compute firewall-rules list --project=$PROJECT_ID --filter="network:dev-hub-vpc"
Step 2 — Provisioning Compute Engine VMs
2.1 Cek file live/gcp/dev/compute/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "${get_terragrunt_dir()}/../../../../modules/gcp/compute"
}
dependency "vpc" {
config_path = "../vpc"
mock_outputs = {
subnets = {
"hub-subnet-public" = { name = "mock", cidr = "10.0.0.0/24", region = "asia-southeast2", self_link = "projects/mock/regions/asia-southeast2/subnetworks/public" }
"hub-subnet-private" = { name = "mock", cidr = "10.0.16.0/24", region = "asia-southeast2", self_link = "projects/mock/regions/asia-southeast2/subnetworks/private" }
}
}
mock_outputs_allowed_terraform_commands = ["init", "validate", "plan", "destroy"]
}
inputs = {
default_zone = "asia-southeast2-a"
vpc_subnets = dependency.vpc.outputs.subnets
vms = [
# ----- Jump host (public subnet, external IP, tag ssh-iap + ssh-internet) -----
{
name = "vm-public-jump"
subnet_name = "hub-subnet-public"
machine_type = "e2-micro"
zone = "asia-southeast2-a"
image = "ubuntu-2204-lts"
external_ip = true
tags = ["ssh-iap", "ssh-internet"]
},
# ----- Private VM #1 -----
{
name = "vm-private-app"
subnet_name = "hub-subnet-private"
machine_type = "e2-micro"
zone = "asia-southeast2-a"
image = "ubuntu-2204-lts"
external_ip = false
tags = ["ssh-iap"]
},
# ----- Private VM #2 -----
{
name = "vm-private-app-2"
subnet_name = "hub-subnet-private"
machine_type = "e2-micro"
zone = "asia-southeast2-a"
image = "ubuntu-2204-lts"
external_ip = false
tags = ["ssh-iap"]
},
]
}
2.2 Inisialisasi & plan
cd live/gcp/dev/compute terragrunt init terragrunt plan
Expected plan output:
Plan: 3 to add, 0 to change, 0 to destroy.
Resources:
+ google_compute_instance.this["vm-public-jump"]
zone: asia-southeast2-a, machine_type: e2-micro, tags: [ssh-iap, ssh-internet]
+ google_compute_instance.this["vm-private-app"]
zone: asia-southeast2-a, machine_type: e2-micro, tags: [ssh-iap]
+ google_compute_instance.this["vm-private-app-2"]
zone: asia-southeast2-a, machine_type: e2-micro, tags: [ssh-iap]
2.3 Apply
terragrunt apply # Ketik "yes" saat prompt
Tunggu ±1–2 menit (booting 3 VM Ubuntu pertama kali).
2.4 Verifikasi
gcloud compute instances list --project=$PROJECT_ID \ --format='table(name,EXTERNAL_IP,INTERNAL_IP,status)' # Expected: # NAME EXTERNAL_IP INTERNAL_IP STATUS # vm-public-jump 34.128.99.159 10.30.0.2 RUNNING # vm-private-app 10.30.16.2 RUNNING # vm-private-app-2 10.30.16.3 RUNNING
Catat IP-ini, akan dipakai di Step 4:
vm-public-jumpexternal IP =34.128.99.1vm-private-appinternal IP =10.30.16.2vm-private-app-2internal IP =10.30.16.3
Step 3 — SSH Keypair + Register ke GCP
3.1 Generate SSH keypair (kalau belum punya)
# Kalau belum ada, generate (pakai nama apapun, ini contoh pakai id_rsa): ssh-keygen -t ed25519 -f id_rsa -C "gunawan-gcp-dev" # Enter passphrase (atau kosongkan)
3.2 Copy isi public key
cat /id_rsa
3.3 Register ke GCP Project Metadata
Buka GCP –> Copmute engine –> metadata –> ssh Keys

- Klik EDIT (kanan atas)
- Klik + ADD ITEM
- Paste dengan format:
gunawan:ssh- - Klik Save → confirm popup.
Tunggu ~30 detik untuk propagasi metadata ke VM.
3.4 Verifikasi key sudah masuk VM
# SSH ke jump host (akan auto-handle auth pakai GCP-managed key pertama kali) gcloud compute ssh vm-public-jump --tunnel-through-iap --zone=asia-southeast2-a --project=$PROJECT_ID # Begitu masuk shell VM, cek authorized_keys: cat /authorized_keys # Harus muncul entry gunawan... # Exit exit
Step 4 — Testing Remote SSH to Jump Host

SSH dari local laptop kita karena IP public kita sudah di whitelist untuk khusus PORT 22 :
ssh -i id_rsa user@34.128.99.1

Ketika sudah di Jump Host anggap saja kita ada 2 instance atau VM private dibelakang seperti pada gambar diatas, setup jump host seperti berikut pada file
config
Host private-app
Hostname 10.30.16.2
User gunawan
IdentityFile ~/.ssh/gunawan.pem
IdentitiesOnly yes
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Host private-app-2
Hostname 10.30.16.3
User gunawan
IdentityFile ~/.ssh/gunawan.pem
IdentitiesOnly yes
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Jika ingin akses Private-app-1 : ssh private-app-1

Jika ingin akses Private-app-2 : ssh-private-app-2

Cara Destroy ya jika sudah selesai praktiknya
Cara Destroy (urutan penting!)
# Compute dulu (VMs reference VPC), baru VPC cd live/gcp/dev/compute terragrunt destroy cd ../vpc terragrunt destroy # Bersihin cache: rm -rf ../compute/.terragrunt-cache/ rm -rf ../vpc/.terragrunt-cache/

Admin website igunawan.com, System Administrator, DevOps Engineer