File & Environment #

Mendeklarasikan variable hanyalah separuh pekerjaan. Separuh lainnya adalah strategi bagaimana nilai variable itu dikelola — di file mana, oleh siapa, bagaimana yang sensitif diamankan, dan bagaimana memastikan setiap environment mendapat nilai yang tepat tanpa duplikasi konfigurasi yang berlebihan. Tanpa strategi yang jelas, proyek multi-environment cepat menjadi kumpulan file tfvars yang saling membingungkan.

flowchart TD
    A["šŸ“‹ Default value\ndi deklarasi variable"] -->|prioritas naik| B["šŸ“„ terraform.tfvars"]
    B -->|prioritas naik| C["šŸ“„ *.auto.tfvars\ndibaca otomatis"]
    C -->|prioritas naik| D["šŸ”§ TF_VAR_*\nenvironment variable"]
    D -->|prioritas naik| E["⚔ -var-file flag"]
    E -->|prioritas tertinggi| F["⚔ -var flag"]

    style A fill:#6b7280,stroke:#4b5563,color:#fff
    style B fill:#3b82f6,stroke:#1e40af,color:#fff
    style C fill:#3b82f6,stroke:#1e40af,color:#fff
    style D fill:#f59e0b,stroke:#d97706,color:#fff
    style E fill:#f97316,stroke:#ea580c,color:#fff
    style F fill:#ef4444,stroke:#dc2626,color:#fff

Hierarki File tfvars #

Terraform membaca file variable dalam urutan tertentu. Memahami hierarki ini mencegah kebingungan tentang nilai mana yang akhirnya digunakan.

URUTAN PEMBACAAN FILE VARIABLE (dari terendah ke tertinggi):

1. default di deklarasi variable
2. terraform.tfvars          (auto-loaded, jika ada)
3. terraform.tfvars.json     (auto-loaded, jika ada)
4. *.auto.tfvars             (auto-loaded, diurutkan alphabetically)
5. *.auto.tfvars.json        (auto-loaded, diurutkan alphabetically)
6. -var-file="file.tfvars"   (via flag, urutan flag menentukan prioritas)
7. -var="key=value"          (via flag, prioritas tertinggi)

Nilai yang dibaca lebih akhir MENIMPA nilai sebelumnya.
flowchart LR
    A["terraform.tfvars\nšŸ“Œ Selalu dibaca"] --> C["Terraform\nEngine"]
    B["production.auto.tfvars\nšŸ“Œ Dibaca otomatis\nberdasarkan abjad"] --> C
    D["custom.tfvars\n⚔ Harus di-flag\n-var-file"] --> C

    style A fill:#3b82f6,stroke:#1e40af,color:#fff
    style B fill:#10b981,stroke:#059669,color:#fff
    style C fill:#f59e0b,stroke:#d97706,color:#fff
    style D fill:#8b5cf6,stroke:#6d28d9,color:#fff

Struktur File tfvars untuk Multi-Environment #

Pola yang paling bersih untuk multi-environment adalah satu file per environment, dipilih saat apply dengan flag -var-file.

environments/
  ā”œā”€ā”€ dev.tfvars
  ā”œā”€ā”€ staging.tfvars
  └── production.tfvars
# environments/dev.tfvars
environment    = "dev"
instance_type  = "t3.micro"
instance_count = 1

database_config = {
  instance_class    = "db.t3.micro"
  allocated_storage = 20
  multi_az          = false
  backup_retention  = 1
}

tags = {
  Environment = "dev"
  CostCenter  = "engineering"
  ManagedBy   = "terraform"
}
# environments/production.tfvars
environment    = "production"
instance_type  = "t3.medium"
instance_count = 3

database_config = {
  instance_class    = "db.r5.large"
  allocated_storage = 500
  multi_az          = true
  backup_retention  = 30
}

tags = {
  Environment = "production"
  CostCenter  = "engineering"
  ManagedBy   = "terraform"
}
# Gunakan saat apply
terraform apply -var-file="environments/dev.tfvars"
terraform apply -var-file="environments/production.tfvars"

File terraform.tfvars untuk Nilai Default Tim #

terraform.tfvars dibaca otomatis dan cocok untuk nilai yang berlaku di semua environment — nilai default yang tidak perlu dioverride per environment.

# terraform.tfvars — nilai default, di-commit ke Git
# (jangan simpan secret di sini)

region   = "ap-southeast-1"
owner    = "platform-team"

common_tags = {
  Project   = "my-app"
  ManagedBy = "terraform"
  Repository = "github.com/org/infrastructure"
}

# Nilai yang sama di semua environment
enable_monitoring  = true
log_retention_days = 30

Environment Variable TF_VAR_* #

Environment variable dengan prefix TF_VAR_ adalah cara yang tepat untuk mengoper nilai yang berbeda-beda di setiap konteks — terutama di CI/CD pipeline dan untuk secret.

# Terraform membaca TF_VAR_<nama_variable> otomatis
# Nama variable harus EXACT MATCH (case-sensitive)

export TF_VAR_environment="production"
export TF_VAR_instance_type="t3.medium"

# Untuk variable dengan tipe kompleks, gunakan format HCL/JSON
export TF_VAR_database_config='{"instance_class":"db.r5.large","allocated_storage":500,"multi_az":true}'

terraform apply
# Terraform membaca TF_VAR_* dan menggunakannya sebagai nilai variable
# Contoh penggunaan di GitHub Actions CI/CD
name: Terraform Apply Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production

    steps:
      - uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        run: terraform init

      - name: Terraform Apply
        env:
          # Nilai non-sensitif dari tfvars file
          TF_VAR_environment: "production"
          # Secret dari GitHub Secrets — tidak pernah masuk ke kode
          TF_VAR_db_password: ${{ secrets.DB_PASSWORD }}
          TF_VAR_api_key: ${{ secrets.API_KEY }}
          # AWS credentials
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: terraform apply -auto-approve -var-file="environments/production.tfvars"

Memisahkan Secret dari Konfigurasi Biasa #

Secret tidak boleh di-commit ke Git, bahkan di file .tfvars sekalipun. Ada dua pendekatan utama.

# PENDEKATAN 1: Baca secret dari AWS Secrets Manager via data source
# Secret dikelola di luar Terraform, Terraform hanya membacanya

data "aws_secretsmanager_secret_version" "db_credentials" {
  secret_id = "production/database/credentials"
}

locals {
  db_credentials = jsondecode(
    data.aws_secretsmanager_secret_version.db_credentials.secret_string
  )
}

resource "aws_db_instance" "main" {
  username = local.db_credentials.username
  password = local.db_credentials.password
  # ... atribut lainnya
}
# PENDEKATAN 2: Variable sensitive diisi via TF_VAR_* environment variable
# Secret dikelola di secrets manager CI/CD (GitHub Secrets, HashiCorp Vault)
# dan dioper ke Terraform sebagai environment variable

variable "db_password" {
  type      = string
  sensitive = true
  # Tidak ada default — Terraform akan error jika TF_VAR_db_password tidak di-set
}

resource "aws_db_instance" "main" {
  password = var.db_password
}

Anti-Pattern yang Harus Dihindari #

# ANTI-PATTERN 1: Secret di file .tfvars yang di-commit ke Git
# production.tfvars
db_password = "super-secret-password"  # āœ— Bocor ke semua yang akses repo
api_key     = "sk-prod-abc123def456"   # āœ— Tersimpan di Git history selamanya

# ANTI-PATTERN 2: Satu file tfvars untuk semua environment
# all-environments.tfvars
dev_instance_type  = "t3.micro"        # āœ— File jadi besar dan membingungkan
prod_instance_type = "t3.medium"
dev_db_class       = "db.t3.micro"
prod_db_class      = "db.r5.large"
# Lebih baik: file terpisah per environment

# ANTI-PATTERN 3: Nilai hardcode di konfigurasi padahal seharusnya variable
resource "aws_instance" "web" {
  instance_type = "t3.micro"   # āœ— Hardcode — tidak bisa berbeda per environment
}
# Lebih baik: instance_type = var.instance_type


Menggunakan terraform.tfvars.json #

Selain format HCL, Terraform juga mendukung format JSON untuk variable files.

// terraform.tfvars.json
{
  "environment": "production",
  "instance_type": "t3.medium",
  "instance_count": 3,
  "tags": {
    "Project": "MyApp",
    "ManagedBy": "Terraform"
  }
}
# terraform.tfvars.json otomatis dibaca, sama seperti terraform.tfvars
terraform plan

# Urutan loading untuk JSON sama dengan HCL:
# 1. terraform.tfvars.json (jika ada, bersama terraform.tfvars)
# 2. *.auto.tfvars.json (alphabetical)
# 3. -var-file flag

Environment-Specific Variable Files #

# Pola umum: satu file tfvars per environment
# environments/
#   ā”œā”€ā”€ dev.tfvars
#   ā”œā”€ā”€ staging.tfvars
#   └── production.tfvars

terraform plan -var-file="environments/production.tfvars"
terraform apply -var-file="environments/staging.tfvars"

# Di CI/CD, pilih file berdasarkan branch atau parameter
if [ "$ENVIRONMENT" == "production" ]; then
  terraform apply -var-file="environments/production.tfvars" -auto-approve
elif [ "$ENVIRONMENT" == "staging" ]; then
  terraform apply -var-file="environments/staging.tfvars" -auto-approve
fi

Variable Precedence Deep Dive #

Terraform memiliki urutan prioritas yang spesifik untuk menentukan nilai variable.

VARIABLE PRIORITY (dari rendah ke tinggi):

1. Default value di deklarasi variable
   variable "x" { default = "low" }

2. terraform.tfvars (dan terraform.tfvars.json)
   x = "medium-low"

3. *.auto.tfvars (dan *.auto.tfvars.json) — alphabetical
   config.auto.tfvars: x = "medium"

4. -var-file flag
   terraform plan -var-file="custom.tfvars"
   x = "medium-high"

5. -var flag dan TF_VAR_ environment variable
   terraform plan -var="x=high"
   TF_VAR_x="high" terraform plan

6. Input di prompt (jika tidak ada default)
   Terraform akan minta input interaktif
# Contoh: override dalam CI/CD
# Default: terraform.tfvars → environment = "dev"
# CI/CD override:
terraform plan -var="environment=staging"
# Ini meng-override nilai di terraform.tfvars

# Environment variable override:
export TF_VAR_instance_type="t3.large"
terraform plan
# TF_VAR_instance_type meng-override semua sumber lain


---

## tfvars Security

```bash
# JANGAN commit tfvars yang berisi secret ke Git!

# .gitignore:
*.tfvars
*.tfvars.json
!terraform.tfvars.example

# Untuk shared values (non-sensitive):
# Commit terraform.tfvars.example dengan placeholder
# terraform.tfvars.example (commit ini)
# environment = "dev"
# instance_type = "t3.micro"
# db_password = "CHANGE_ME"

# terraform.tfvars (JANGAN commit)
environment  = "production"
instance_type = "m5.large"
db_password   = "actually-secret-password"

# Alternatif: gunakan environment variables untuk secret
# export TF_VAR_db_password="secret"
# Terraform akan baca dari TF_VAR_ prefix

Hierarchical Variable Loading #

TERRAFORM VARIABLE LOADING ORDER:

1. Environment variables (TF_VAR_*)
   └── Loaded automatically from shell

2. terraform.tfvars
   └── Auto-loaded jika ada di working directory

3. *.auto.tfvars
   └── Auto-loaded, alphabetical order

4. -var-file=explicit.tfvars
   └── Explicit, bisa specify multiple

5. -var="key=value"
   └── Command line, highest priority

NAMING CONVENTION:
common.tfvars       → Shared values across all envs
dev.tfvars          → Dev-specific values
staging.tfvars      → Staging-specific values
production.tfvars   → Production-specific values
secrets.tfvars      → NEVER commit (in .gitignore)
# Combine multiple var files
terraform apply   -var-file="common.tfvars"   -var-file="environments/dev.tfvars"   -var-file="regions/ap-southeast-1.tfvars"

Ringkasan #

  • Satu file tfvars per environment (dev.tfvars, staging.tfvars, production.tfvars) yang dipilih dengan -var-file adalah pola multi-environment yang paling bersih.
  • terraform.tfvars untuk nilai default tim yang berlaku di semua environment — di-commit ke Git, tidak mengandung secret.
  • TF_VAR_* environment variable untuk nilai yang berbeda per context di CI/CD dan untuk semua secret.
  • Secret tidak masuk ke file tfvars yang di-commit ke Git — gunakan TF_VAR_* dari secrets manager atau baca langsung dari AWS Secrets Manager via data source.
  • Hierarki prioritas: flag CLI > tfvars file > auto-loaded tfvars > env var > default — nilai yang lebih spesifik selalu menang.
  • Variable sensitive tanpa default memaksa nilai selalu diberikan secara eksplisit — Terraform akan error jika tidak ada nilai, mencegah lupa mengisi secret.

← Sebelumnya: Type & Validation Ā  Berikutnya: Apa itu Output? →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact