Local #

Local state adalah mode default Terraform — state disimpan dalam file terraform.tfstate di direktori yang sama dengan konfigurasimu. Tidak ada konfigurasi tambahan yang diperlukan. Untuk seorang developer yang bekerja sendiri di proyek kecil atau sedang belajar, ini sepenuhnya cukup. Tapi begitu ada anggota tim kedua atau begitu konfigurasi menyentuh resource production, local state mulai memperlihatkan keterbatasannya.

flowchart TD
    A["terraform init"] --> B["terraform plan"]
    B --> C["terraform apply"]
    C --> D["terraform.tfstate\ndibuat/diupdate"]
    D --> B

    style A fill:#e3f2fd,stroke:#1565c0
    style C fill:#e8f5e9,stroke:#2e7d32
    style D fill:#fff3e0,stroke:#e65100

Struktur File terraform.tfstate #

State file adalah JSON yang menyimpan pemetaan lengkap antara resource di konfigurasi Terraform dan resource yang ada di cloud.

{
  "version": 4,
  "terraform_version": "1.6.3",
  "serial": 12,
  "lineage": "a3b4c5d6-e7f8-9012-abcd-ef1234567890",
  "outputs": {
    "instance_public_ip": {
      "value": "54.123.45.67",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "ami": "ami-0abcdef1234567890",
            "id": "i-0abcdef1234567890",
            "instance_type": "t3.micro",
            "private_ip": "10.0.1.42",
            "public_ip": "54.123.45.67",
            "subnet_id": "subnet-0abcdef1234",
            "tags": {
              "Name": "web-server",
              "Environment": "production"
            }
          }
        }
      ]
    }
  ]
}

Beberapa field penting yang perlu dipahami:

  • serial — nomor urut yang bertambah setiap kali state dimodifikasi. Terraform menggunakan ini untuk mendeteksi konflik.
  • lineage — UUID unik yang dibuat saat state pertama kali dibuat. Digunakan untuk memverifikasi state file berasal dari workspace yang sama.
  • mode: "managed" — resource yang dikelola Terraform. Bisa juga "data" untuk data source.
flowchart TD
    A["terraform.tfstate\n(JSON)"] --> B["serial: 12"]
    A --> C["lineage: UUID"]
    A --> D["outputs"]
    A --> E["resources"]
    D --> D1["instance_public_ip\n= 54.123.45.67"]
    E --> E1["aws_instance.web\nami, id, ip, tags"]
    E --> E2["aws_subnet.public\nid, cidr, az"]

    style A fill:#e3f2fd,stroke:#1565c0
    style E fill:#fff3e0,stroke:#e65100
    style D fill:#e8f5e9,stroke:#2e7d32

File-file State yang Muncul #

Setelah terraform apply pertama kali:

direktori-proyek/
  ├── main.tf
  ├── variables.tf
  ├── outputs.tf
  ├── terraform.tfstate          ← state aktif
  ├── terraform.tfstate.backup   ← backup otomatis state sebelumnya
  └── .terraform/
      └── ...

terraform.tfstate.backup dibuat otomatis setiap kali state diupdate.
Ini memberikan satu level undo jika terjadi kesalahan.

Mengapa Local State Tidak Cukup untuk Tim #

Local state menyimpan segalanya di satu file di mesinmu. Ini menciptakan masalah struktural saat bekerja dalam tim.

flowchart TD
    A["terraform.tfstate\n(satu file lokal)"] --> B["Developer A\nmesin lokal"]
    A --> C["Developer B\nmesin lain"]
    C --> D["State kosong\n(tidak bisa akses)"]
    D --> E["Plan: buat semua\ndari awal! ❌"]
    A --> F["A & B apply\nbersamaan"]
    F --> G["State conflict\natau corrupt ❌"]

    style A fill:#ffebee,stroke:#c62828
    style E fill:#ffebee,stroke:#c62828
    style G fill:#ffebee,stroke:#c62828
MASALAH LOCAL STATE DALAM TIM:

1. TIDAK BISA DIBAGI
   State hanya ada di mesin developer A.
   Developer B menjalankan terraform plan → state kosong
   → Plan menampilkan "akan membuat semua resource dari awal"
   → Catastrophic jika dilanjutkan dengan apply

2. TIDAK ADA LOCKING
   Developer A sedang apply sementara developer B juga apply.
   Keduanya membaca state yang sama (versi lama), lalu keduanya
   menulis state baru — salah satu akan menimpa yang lain.
   → State corrupt atau resource duplikat

3. MENGANDUNG INFORMASI SENSITIF
   State bisa mengandung password, private key, API token
   dalam plaintext — bergantung pada resource yang dikelola.
   Jika state di-commit ke Git, semua secret bocor ke semua
   yang punya akses ke repository.

4. TIDAK ADA VERSIONING
   terraform.tfstate.backup hanya menyimpan satu versi sebelumnya.
   Jika terjadi kesalahan dua langkah ke belakang, tidak ada recovery.

State Sensitif — Jangan Di-commit ke Git #

# Contoh isi state yang mengandung data sensitif:

# aws_db_instance menyimpan password dalam state:
# "password": "super-secret-db-password-123"

# aws_iam_access_key menyimpan secret key:
# "secret": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

# tls_private_key menyimpan private key:
# "private_key_pem": "-----BEGIN RSA PRIVATE KEY-----\n..."
# Pastikan .gitignore sudah mengecualikan state files:
cat .gitignore

# Local .terraform directories
**/.terraform/*

# State files
*.tfstate
*.tfstate.*

Kapan Local State Masih Tepat #

Meskipun punya keterbatasan, local state masih tepat digunakan dalam beberapa situasi.

LOCAL STATE MASIH TEPAT UNTUK:

  ✓ Belajar dan eksperimen — proyek pribadi tanpa kolaborator
  ✓ Proyek disposable — environment yang sering dibuat dan dihapus
  ✓ CI/CD pipeline yang stateless — setiap run dimulai dari state baru
    (misalnya: pipeline yang hanya membuat ephemeral environment)
  ✓ Terraform module development — testing module secara lokal

SUDAH BUTUH REMOTE STATE JIKA:
  ✗ Lebih dari satu orang mengerjakan infrastruktur yang sama
  ✗ Resource menyentuh production atau data yang penting
  ✗ CI/CD pipeline perlu akses ke state yang sama
  ✗ Ada kekhawatiran tentang recovery jika state hilang

Perintah State untuk Local State #

Meskipun menggunakan local state, semua operasi state management bisa dilakukan melalui Terraform CLI — bukan dengan mengedit file JSON secara manual.

# Lihat semua resource
terraform state list

# Lihat detail resource tertentu
terraform state show aws_instance.web

# Hapus resource dari state (tanpa destroy resource di cloud)
terraform state rm aws_instance.web

# Pindahkan/rename resource di state
terraform state mv aws_instance.web aws_instance.web_server

# Pull state ke stdout (berguna untuk backup atau inspeksi)
terraform state pull > backup-$(date +%Y%m%d).tfstate

# Push state dari file (hati-hati — bisa overwrite state aktif)
terraform state push backup-20240101.tfstate

Mendalami Serial dan Lineage #

Dua field di state file — serial dan lineage — adalah mekanisme keamanan yang sering diabaikan, padahal keduanya sangat penting untuk mencegah konflik dan memverifikasi integritas state.

# Serial: nomor urut yang bertambah setiap state dimodifikasi
# Kamu bisa melihat serial dari state file:
cat terraform.tfstate | jq '.serial'
# Output: 12

# Setiap terraform apply yang berhasil akan menambah serial:
# apply pertama → serial: 1
# apply kedua   → serial: 2
# dst.

# Jika dua orang apply bersamaan (tanpa locking), keduanya
# membaca serial 12. Yang pertama menulis → serial 13.
# Yang kedua juga menulis → serial 13 (menimpa yang pertama).
# Data dari apply pertama hilang.
# Lineage: UUID yang dibuat sekali saat state pertama kali diinisialisasi
cat terraform.tfstate | jq '.lineage'
# Output: "a3b4c5d6-e7f8-9012-abcd-ef1234567890"

# Lineage digunakan saat terraform state push untuk memverifikasi
# bahwa file yang di-push berasal dari workspace yang sama:
terraform state push wrong-state.tfstate
# Error: lineage mismatch — state berasal dari workspace berbeda

# Ini mencegah insiden: developer tidak sengaja push state
# dari environment staging ke environment production

Menganalisis State File Secara Manual #

Terkadang kamu perlu melihat isi state file untuk debugging — misalnya, resource di cloud berubah tapi terraform plan tidak mendeteksinya.

# Cari resource tertentu dalam state file
cat terraform.tfstate | jq '.resources[] | select(.name=="web")'
# Menampilkan seluruh data aws_instance.web yang tersimpan

# Cek atribut spesifik dari sebuah resource
cat terraform.tfstate | jq '.resources[]
  | select(.type=="aws_instance" and .name=="web")
  | .instances[0].attributes.public_ip'
# Output: "54.123.45.67"

# Hitung jumlah resource yang dikelola
cat terraform.tfstate | jq '[.resources[].instances[]] | length'
# Output: 7 (artinya 7 resource instance di state)

# Daftar semua tipe resource yang ada di state
cat terraform.tfstate | jq '[.resources[].type] | unique'
# Output: ["aws_instance", "aws_security_group", "aws_subnet", ...]

# Cek resource yang mengandung data sensitif
cat terraform.tfstate | jq '.. | .password? // .secret? // .private_key_pem?
  | select(. != null)' 2>/dev/null
# Output: daftar nilai sensitif yang tersimpan dalam plaintext
# INILAH mengapa state tidak boleh di-commit ke Git

Migrasi dari Local ke Remote State #

Saat proyekmu berkembang dari eksperimen pribadi menjadi proyek tim, kamu perlu memindahkan local state ke remote backend. Proses ini harus dilakukan dengan hati-hati karena kesalahan bisa menyebabkan Terraform “lupa” resource yang sudah ada.

# LANGKAH 1: Backup state sebelum migrasi
cp terraform.tfstate terraform.tfstate.backup.before-migration

# LANGKAH 2: Buat remote backend (misalnya S3)
# Tambahkan konfigurasi backend ke main.tf atau backend.tf:
terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "project/terraform.tfstate"
    region         = "ap-southeast-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"
  }
}
# LANGKAH 3: Jalankan terraform init untuk migrasi
terraform init
# Terraform mendeteksi bahwa backend berubah dari local ke S3
# dan menawarkan untuk memindahkan state:
#
# "Do you want to copy existing state to the new backend?
#   Pre-existing state was found while migrating the previous
#   "local" backend to the newly configured "s3" backend."
#
# Pilih "yes" — Terraform akan:
# 1. Membaca local state
# 2. Meng-upload ke S3
# 3. Menghapus local state (setelah berhasil)

# LANGKAH 4: Verifikasi state berhasil dipindahkan
terraform state list
# Semua resource harus muncul — jika kosong, ada masalah

# LANGKAH 5: Verifikasi plan tidak menunjukkan perubahan
terraform plan
# "No changes" — state sudah sinkron dengan remote

Common Pitfalls dengan Local State #

# PITFALL 1: Menghapus .terraform/ directory
rm -rf .terraform/
terraform plan
# Error: Backend not initialized
# Solusi: terraform init (akan re-download provider dan re-init backend)

# PITFALL 2: Memindahkan state file ke komputer lain tanpa .terraform/
# → Developer lain tidak tahu backend apa yang digunakan
# → Selalu sertakan instruksi: "Jalankan terraform init dulu"

# PITFALL 3: Dua terminal menjalankan terraform apply bersamaan
# Terminal 1: terraform apply → membaca state serial 10
# Terminal 2: terraform apply → membaca state serial 10 (sama!)
# Terminal 1: selesai → menulis state serial 11
# Terminal 2: selesai → menulis state serial 11 (menimpa terminal 1!)
# → State milik terminal 1 hilang
# → Tidak ada locking di local state untuk mencegah ini

# PITFALL 4: State file ter-corrupt karena disk penuh atau kill process
# Jika terraform apply ter-kill di tengah proses tulis state:
cat terraform.tfstate
# Output: incomplete JSON — Terraform error saat membaca
# Solusi: restore dari terraform.tfstate.backup

# PITFALL 5: Workspace switching yang membingungkan
terraform workspace new staging
# State staging terpisah, tapi disimpan di .terraform.tfstate.d/
# Developer sering lupa mereka di workspace mana
# Solusi: tampilkan workspace di shell prompt (lihat artikel workspace)

Ringkasan #

  • Local state adalah default — tidak butuh konfigurasi, cocok untuk belajar dan eksperimen pribadi.
  • terraform.tfstate adalah file JSON yang menyimpan pemetaan lengkap antara konfigurasi dan resource aktual di cloud, termasuk semua atribut yang digenerate provider.
  • serial dan lineage digunakan Terraform untuk mendeteksi konflik dan memverifikasi asal state.
  • State bisa mengandung secret (password, API key, private key) — jangan pernah di-commit ke Git.
  • Tiga masalah utama local state dalam tim: tidak bisa dibagi, tidak ada locking, dan tidak ada versioning yang memadai.
  • Pindah ke remote state begitu ada kolaborasi tim, resource production, atau kebutuhan CI/CD yang mengakses state yang sama.

← Sebelumnya: Locking   Berikutnya: Remote State →

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