Terragrunt mengeksekusi engine OpenTofu lewat flag --tofu. Episode ini merancang arsitektur DRY multi-environment Dev, Staging, dan Prod dengan backend serta provider yang dipusatkan di satu terragrunt.hcl root.

Di episode 11 sebelumnya kita memasang tiga lapis pengaman kualitas: tofu fmt, tofu validate, static analysis dengan tflint/Checkov/Trivy, dan framework testing native tofu test. Sekarang bayangkan kode kalian sudah rapi dan teruji — tapi repositori itu punya tiga folder environment (Dev, Staging, Prod), masing-masing dengan backend S3, blok provider, dan konfigurasi yang nyaris identik. Setiap kali tim menambah environment baru, mereka copy-paste puluhan baris. Setiap kali konfigurasi backend berubah, mereka harus menyentuh puluhan file. Inilah masalah yang membuat Terragrunt lahir: duplikasi adalah akar dari drift konfigurasi.
Di episode 12 ini kita akan mengintegrasikan OpenTofu dengan Terragrunt. Kita akan belajar bagaimana Terragrunt menjalankan binary tofu melalui terragrunt --tofu, lalu menyusun arsitektur DRY (Don't Repeat Yourself) untuk multi-environment dengan backend dan provider yang dipusatkan di satu file root. Pada akhirnya, menambah environment baru cukup dengan satu folder kecil berisi nilai-nilai yang spesifik — bukan lagi salinan besar.
Bayangkan tim dengan arsitektur dev/, staging/, dan prod/. Di setiap folder ada blok backend "s3", konfigurasi provider "aws", dan pemanggilan modul yang sama. Konsistensi dipertahankan hanya oleh disiplin manusia — dan disiplin manusia selalu bocor. Seseorang mengubah region di prod tapi lupa di dev, atau menambahkan argumen baru hanya di satu environment. tofu plan baru ketahuan saat masalah sudah menjalar.
Terragrunt adalah thin wrapper yang menjalankan engine IaC di belakangnya dan menawarkan inheritance: konfigurasi yang sama ditulis sekali di root, lalu diwarisi oleh setiap environment. Backend, provider, dan lokasi state cukup didefinisikan satu kali; setiap folder environment hanya berisi yang benar-benar berbeda — nilai-nilai inputs-nya.
Secara default Terragrunt memanggil binary terraform. Untuk memakainya dengan OpenTofu, gunakan flag --tofu — Terragrunt akan mencari binary tofu di PATH dan menjalankan seluruh siklus hidup (init, plan, apply) melaluinya. Semua fitur Terragrunt tetap bekerja penuh: inheritance, run-all untuk mengeksekusi banyak unit sekaligus, hingga dependency untuk referensi antar unit.
# Beritahu Terragrunt memakai binary tofu untuk perintah ini
terragrunt --tofu plan
terragrunt --tofu apply
# Jalankan seluruh environment sekaligus dari folder root
terragrunt run-all plan
# Set default permanen agar tidak perlu flag --tofu terus-menerus
export TERRAGRUNT_TF_PATH=/usr/local/bin/tofuTip
Set TERRAGRUNT_TF_PATH di file ~/.terragruntrc atau environment CI agar setiap anggota tim dan pipeline otomatis memakai OpenTofu — satu sumber kebenaran untuk engine, bukan lagi bergantung pada siapa yang ingat mengetik flag --tofu.
Ini adalah pola yang dipakai ribuan tim produksi. Repositori dibagi menjadi dua bagian: satu root yang memegang semua hal yang sama, dan folder environment yang hanya memegang nilai yang berbeda.
infrastructure-live/
├── terragrunt.hcl # root: backend & provider terpusat
├── dev/
│ └── vpc/
│ └── terragrunt.hcl # hanya inputs spesifik environment
├── staging/
│ └── vpc/
│ └── terragrunt.hcl
└── prod/
└── vpc/
└── terragrunt.hclFile root mendefinisikan remote_state (backend S3 + locking) dan generate "provider" yang menyisipkan blok provider ke setiap unit secara otomatis:
locals {
env = path_relative_to_include()
account = get_aws_account_id()
region = "ap-southeast-1"
}
remote_state {
backend = "s3"
config = {
bucket = "opentofu-state-${local.account}"
key = "${local.env}/terraform.tfstate"
region = local.region
encrypt = true
}
generate = {
path = "backend.tf"
if_exists = "overwrite"
}
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite"
contents = <<EOF
provider "aws" {
region = "${local.region}"
}
EOF
}Perhatikan bagaimana nilai seperti bucket dan key dihitung dari locals — setiap environment otomatis mendapat bucket yang sama tapi key state yang berbeda (dev/, staging/, prod/). Konfigurasi backend ditulis sekali, diterapkan ke mana-mana.
File di setiap environment jauh lebih ramping. Ia mewarisi root dengan include, menunjuk ke modul yang dipakai, dan hanya menyediakan inputs yang spesifik:
include "root" {
path = find_in_parent_folders()
}
terraform {
source = "git::https://github.com/acme/infra-modules.git//vpc?ref=v2.1.0"
}
inputs = {
name = "vpc-${path_relative_to_include()}"
cidr_block = "10.0.0.0/16"
dns_hostnames = true
tags = {
Environment = path_relative_to_include()
}
}Menambah environment staging dan prod kini tinggal menyalin folder dev/, mengganti nilai CIDR dan tag — tanpa menyentuh konfigurasi backend atau provider sama sekali. path_relative_to_include() membuat nama dan tag mengikuti lokasi folder secara otomatis, sehingga konsistensi penamaan tidak lagi bergantung pada ingatan.
Warning
Jangan mengandalkan modul yang selalu mengarah ke cabang main. Pin source ke tag versi seperti ?ref=v2.1.0 — jika tidak, satu push ke main bisa mengubah perilaku seluruh environment di luar sepengetahuan review manusia. Konfigurasi yang deterministik adalah prasyarat dari semua yang akan kita bangun di episode-episode CI/CD berikutnya.
Ketika unit saling membutuhkan — misalnya database mengonsumsi output dari unit vpc — Terragrunt menyediakan blok dependency yang membaca output state unit lain dan menjadwalkan eksekusi secara berurutan. Ditambah terragrunt run-all plan yang menjalankan semua unit dalam urutan yang benar dari satu perintah di root, mengelola puluhan stack multi-environment terasa seperti mengelola satu.
Pada episode 12 ini kita telah:
terragrunt --tofu dan TERRAGRUNT_TF_PATH.terragrunt.hcl root, environment cukup berisi inputs spesifik.path_relative_to_include() dan get_aws_account_id() untuk menghitung nilai tanpa hardcode.dependency dan run-all untuk mengorkestrasi banyak unit.Struktur DRY ini baru terasa kekuatannya ketika digabungkan dengan otomatisasi. Di episode 13 selanjutnya kita akan membangun CI/CD pipeline automation di GitHub Actions dan GitLab CI: action resmi opentofu/setup-opentofu, alur GitOps lengkap dari PR, fmt, validate, security scan, tofu plan dengan komentar di PR, hingga approval gate dan tofu apply melalui OIDC. Sampai jumpa!