Apa yang terjadi ketika state file corrupt atau hilang? Di episode ini kita membangun fondasi DR dengan backup & versioning remote storage, serta menguasai operasi penyelamatan: terraform state pull, perbaikan JSON manual, dan terraform state push yang aman.

Setelah di episode 18 sebelumnya kita membahas infrastructure drift dan refactoring — menjaga agar kode, state, dan cloud tetap selaras — pada episode kali ini kita akan menghadapi skenario yang paling menegangkan dalam seluruh perjalanan IaC: state file corrupt atau hilang.
Bayangkan ini. Kamis malam, pukul 23.40. Ada insiden produksi, dan kalian perlu segera memperbaiki infrastruktur. Kalian membuka terminal, menjalankan terraform init, lalu terraform plan. Dan yang muncul bukan rencana perubahan — melainkan satu baris yang membuat jantung berhenti sejenak:
Error: Unmarshal tfstate: failed to unmarshal state file
json: cannot unmarshal object into Go struct field State.terraform_version of type string
Terraform state file is invalid and cannot be read. If this is unexpected,
please contact your support provider for assistance.Atau lebih buruk lagi: terraform init berhasil, tapi terraform plan menampilkan Plan: 78 to add — padahal infrastruktur sudah berdiri. Artinya state file hilang atau kosong, dan Terraform mengira tidak ada apa pun yang sedang ia kelola. Seluruh resource produksi kalian dianggap "baru". Satu terraform apply naif akan membuat duplikat atau menghancurkan semuanya.
Mengapa topik ini penting? Karena di dalam pekerjaan SRE/DevOps, "berapa cepat kalian pulih" lebih menentukan reputasi tim daripada "berapa baik kalian menulis kode". State file adalah memori jangka panjang Terraform — kehilangannya tidak menghancurkan infrastruktur, tapi membuatnya tidak bisa dikelola. Di episode inilah kalian akan belajar membangun fondasi disaster recovery yang benar, memulihkan state dari backup, melakukan operasi terraform state pull dan terraform state push secara aman, hingga re-import manual ketika state sudah tidak bisa diselamatkan.
Sejak episode 5, kita tahu bahwa state file berisi mapping antara resource block di kode dan ID objek riil di cloud. Di dalamnya tercatat apa yang dimiliki Terraform: bucket mana, instance mana, database mana — lengkap dengan seluruh atribut dan kunci rahasianya.
Konsekuensinya logis: jika state hilang, Terraform buta. Ia masih tahu apa yang diinginkan kode, tapi tidak tahu apa yang sudah ada di cloud. Akibatnya:
terraform plan menampilkan seluruh resource sebagai "to be created" (karena tidak ada catatan kepemilikan).terraform apply akan membuat duplikat resource (karena tidak tahu resource lama masih ada).terraform destroy bahkan lebih berbahaya — tanpa state, ia mungkin menganggap tidak ada yang perlu dihancurkan (itu kabar baik), tapi kalau state korup sebagian, ia bisa menghancurkan resource yang salah.Warning
Ironi yang harus selalu kalian ingat: state yang hilang tidak menghapus resource di cloud — resource tetap hidup dan tetap ditagih. Jadi skenario terburuk bukan "infrastruktur lenyap", melainkan "infrastruktur lenyap dari kendali kalian": duplikasi, kebingungan kepemilikan, dan biaya yang tak terkendali. Itulah mengapa DR di sini benar-benar soal pemulihan kendali.
Analogi yang pas: state file itu seperti surat kepemilikan (BPKB) kendaraan. Mobilnya tetap ada di garasi, tetap bisa dipakai — tapi tanpa suratnya, kalian tidak bisa membuktikan kepemilikan, tidak bisa menjualnya, dan suatu saat bisa berebut dengan orang lain yang mengaku memilikinya.
Kabar baiknya, fondasi DR sudah kalian bangun di episode 5: remote state backend di S3 dengan versioning, enkripsi, dan DynamoDB untuk locking. Mari kita lihat mengapa ketiganya bersama-sama membentuk pertahanan berlapis:
| Lapisan | Mekanisme | Peran dalam DR |
|---|---|---|
| Remote storage | State di S3/GCS, bukan di laptop | State tidak hilang saat laptop rusak/hilang |
| Versioning | Setiap perubahan state tersimpan sebagai versi | Bisa rollback ke versi lama saat state corrupt |
| Enkripsi | SSE-KMS | State berisi secret — harus dilindungi at-rest |
| DynamoDB locking | Lock per eksekusi | Mencegah dua proses menimpa state bersamaan |
Berikut konfigurasi backend yang menjadi fondasi DR di seri ini:
terraform {
backend "s3" {
bucket = "myapp-tfstate-bucket"
key = "production/infrastructure/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true
dynamodb_table = "myapp-tfstate-lock"
}
}Tapi tunggu — ada hal yang mudah terlewat: backend S3 tidak otomatis mengaktifkan versioning. Versioning adalah properti bucket itu sendiri, dan harus diaktifkan sekali — idealnya dengan Terraform (menggunakan backend lokal sementara atau state terpisah) atau lewat console saat pertama kali membuat bucket:
resource "aws_s3_bucket" "tfstate" {
bucket = "myapp-tfstate-bucket"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
resource "aws_s3_bucket_public_access_block" "tfstate" {
bucket = aws_s3_bucket.tfstate.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}Dengan versioning aktif, setiap kali terraform apply menulis state baru, versi lama tetap tersimpan. Jika suatu saat state diambil (misal karena operasi manual yang salah atau korupsi), kalian cukup mengembalikan versi sebelumnya — persis seperti mengembalikan file dari recycle bin, tapi dengan jejak historis yang lengkap.
Tip
Jangan lupa DynamoDB untuk locking (episode 5). Locking tidak hanya mencegah dua apply menimpa state bersamaan — ia juga melindungi operasi manual: jika seseorang sedang menjalankan apply, operasi state pull/state push dari orang lain akan tertahan. DR yang baik dibangun di atas fondasi yang rapi, bukan di atas improvisasi saat panik.
Korupsi state bisa datang dari berbagai arah — file JSON yang rusak saat upload, pemangkasan tidak lengkap oleh operasi manual yang salah, edit JSON oleh manusia (menyalahi aturan episode 8!), atau bug pada versi Terraform tertentu. Gejalanya bervariasi:
Error: Unmarshal tfstate: failed to unmarshal state file — JSON tidak valid.Error: Missing resource instance key atau error address ganjil — struktur rusak sebagian.Plan: N to add padahal infrastruktur sudah ada — state kosong/teroverwrite.Plan: N to change) tanpa alasan — atribut tercorrupt.Urutan diagnosisnya selalu sama:
terraform state list # Apakah daftar resource masih terbaca?
terraform state show <addr> # Apakah atribut resource tertentu masuk akal?Jika state list gagal atau hasilnya tidak masuk akal, jangan lanjut ke apply. Berhenti. Langkah berikutnya adalah pemulihan — dan pemulihan dimulai dari memahami dua perintah penyelamat: terraform state pull dan terraform state push.
terraform state pull: Mengambil & Mencetak State Mentahterraform state pull mengambil state dari backend dan mencetaknya ke stdout dalam format JSON mentah — sama persis dengan apa yang disimpan di S3. Ini adalah cara kalian "membuka mesin" state untuk diperiksa, di-backup, atau dianalisis:
terraform state pullOutputnya adalah dokumen JSON besar yang dimulai kira-kira seperti ini (dipotong demi keterbacaan):
Perhatikan dua field kunci di bagian atas:
serial — nomor urut revisi state. Backend S3 (dan sebagian besar backend remote) menolak overwrite dengan state yang serial-nya lebih rendah dari yang tersimpan. Ini adalah pengaman bawaan agar state lama tidak menimpa state baru secara tidak sengaja.lineage — "sidik jari" unik state. Dua state dari project yang sama harus punya lineage sama; jika berbeda, berarti keduanya berasal dari awal yang berbeda (tanda ada dua state terpisah yang mungkin bentrok).Kegunaan paling umum state pull dalam konteks DR:
Simpan hasil pull ke file:
terraform state pull > backup-tfstate-$(date +%F).json
ls -la backup-tfstate-*.jsonImportant
File hasil terraform state pull berisi secret dalam plaintext — password database, access key, dan lain-lain (episode 15). Perlakukan file ini seperti file kredensial: simpan di lokasi aman (password manager, KMS-encrypted storage), beri permission 600, dan jangan pernah commit ke Git.
terraform state push: Menimpa State — Dengan Seluruh Kewaspadaanterraform state push adalah kebalikannya: mengambil state dari stdin atau file, lalu menimpanya ke backend. Ini adalah operasi yang sangat berbahaya — tanpa pengaman yang cukup, satu push yang salah bisa menimpa state sehat dengan state lama atau rusak.
terraform state push backup-tfstate-2026-08-01.jsonKapan state push sah digunakan?
pull).Dan kapan jangan pernah:
state mv, state rm, dll.).Caution
Backend S3 memblokir push dengan serial lebih rendah, tapi push dengan serial yang sama atau lebih tinggi akan diterima — itulah sebabnya push bisa menimpa state yang lebih baru dengan versi yang lebih lama. Sebelum push: (1) backup state saat ini dengan state pull, (2) pastikan tidak ada apply/plan berjalan di tim, (3) siapkan rencana rollback jika push ternyata salah.
terraform state pull > state-backup.json
python3 -m json.tool state-backup.json # validasi JSON
jq '.resources | length' state-backup.jsonKadang korupsi bersifat parsial — struktur JSON sebagian besar utuh, hanya satu atau dua resource yang rusak. Dalam kasus itu, perbaikan manual dimungkinkan, tapi hanya dengan prosedur yang ketat. Ingat aturan dari episode 8: jangan pernah mengedit state secara manual — itu aturan untuk mencegah kebiasaan buruk. Untuk penyelamatan DR, ada pengecualian terkontrol, dan inilah langkah-langkahnya:
terraform state pull > backup.json, salin juga versi S3 terbaru.state push, lalu state list dan plan untuk memastikan tidak ada resource yang tampak "hilang" atau "baru".# 1. Backup state yang akan diperbaiki
terraform state pull > state-broken.json
# 2. Salin untuk diedit — JANGAN edit file asli
cp state-broken.json state-fixed.json
# 3. Edit state-fixed.json dengan editor (hanya bagian yang benar-benar rusak)
# 4. Validasi struktur JSON
python3 -m json.tool state-fixed.json > /dev/null && echo "JSON valid"
# 5. Push hasil perbaikan
terraform state push state-fixed.json
# 6. Verifikasi akhir
terraform state list
terraform plan -detailed-exitcodeCaution
Jika perbaikannya menyentuh struktur resource (bukan sekadar atribut) — misalnya address resource bergeser atau module berubah — jangan perbaiki JSON. Lebih aman gunakan terraform state mv untuk memindahkan address, dan terraform import (episode 8) untuk membangun kembali resource dari ID cloud. JSON manual hanya untuk perbaikan kecil yang benar-benar kalian pahami.
import BlockSkenario terburuk: backup tidak ada (bucket tanpa versioning, atau bahkan bucket terhapus), dan state benar-benar kosong. Untungnya, ada satu jalur penyelamatan terakhir: membangun kembali state dengan import — persis teknik dari episode 8.
Prinsipnya: resource di cloud masih hidup; kita tinggal memberitahu Terraform siapa mereka. Karena Terraform 1.5+, cara terbersih adalah blok import deklaratif — setiap resource eksisting kita deklarasikan address-nya:
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.medium"
}
resource "aws_db_instance" "primary" {
identifier = "myapp-postgres"
engine = "postgres"
instance_class = "db.r6g.large"
}
import {
to = aws_instance.web
id = "i-0abcd1234efgh5678"
}
import {
to = aws_db_instance.primary
id = "myapp-postgres"
}Alur pemulihan total dari nol:
terraform init # 1. Inisialisasi backend kosong
terraform plan # 2. Verifikasi "Plan: N to import"
terraform apply # 3. Eksekusi import → state terbangun
terraform plan -detailed-exitcode # 4. Verifikasi: exit 0 = tidak ada driftTip
Satu kendala re-import: kalian harus tahu ID cloud setiap resource. Sumbernya adalah console cloud atau perintah CLI (aws ec2 describe-instances, aws rds describe-db-instances, aws s3api list-buckets, dan setara GCP/Azure). Inilah alasan mengapa dokumentasi inventory resource (daftar resource beserta ID-nya) adalah aset DR yang nyata — siapkan di awal, bukan saat insiden.
Checklist ini adalah runbook yang harus dipraktikkan — bukan sekadar dibaca. Simpan sebagai dokumen tim, dan latih (tabletop exercise) minimal tiap kuartal:
| No | Langkah DR | Tool / Perintah | Catatan |
|---|---|---|---|
| 1 | Pastikan bucket state punya versioning | aws s3api get-bucket-versioning | Tanpa ini, tidak ada rollback dari S3 |
| 2 | Pastikan lock DynamoDB aktif | terraform plan saat orang lain apply | Akan tertahan menunggu lock |
| 3 | Backup berkala state ke lokasi kedua | terraform state pull > backup.json | Cron mingguan + simpan di storage terpisah |
| 4 | Deteksi korupsi lebih awal | terraform state list terjadwal | Drift detection (episode 18) bisa diperluas |
| 5 | Pulihkan dari versi S3 bila korup | aws s3api get-object + restore versi | Paling cepat, paling aman |
| 6 | Pulihkan dari backup file bila perlu | terraform state push backup.json | Validasi JSON dulu |
| 7 | Re-import bila state hilang total | import block + apply | Siapkan inventory ID resource |
| 8 | Verifikasi akhir | terraform plan -detailed-exitcode | Exit 0 = pulih sempurna |
state push, state mv massal, atau edit JSON, jalankan terraform state pull > backup.json lebih dulu. Satu perintah murah yang menyelamatkan seluruh tim.state mv, state rm, state replace-provider selalu lebih aman daripada menyentuh JSON mentah.plan bersih.| Kesalahan | Dampak | Solusi |
|---|---|---|
| Bucket state tanpa versioning | Tidak ada rollback saat state corrupt | Aktifkan versioning sejak bootstrap |
| Mengandalkan local state | State hilang saat laptop rusak | Remote state + backup (episode 5) |
state push tanpa backup dulu | Menimpa state sehat dengan versi lama | Selalu pull + backup sebelum push |
Panik → apply saat state kosong | Membuat duplikat resource produksi | Berhenti; diagnosa; pulihkan state dulu |
| Edit JSON tanpa validasi | Korupsi makin parah | python3 -m json.tool + push + verifikasi |
| Tidak tahu ID resource saat re-import | Recovery macet di tengah jalan | Siapkan inventory ID sejak awal |
| Tidak pernah menguji recovery | Prosedur gagal saat insiden nyata | Tabletop exercise rutin per kuartal |
Pada episode 19 ini kalian telah membangun pertahanan terakhir bagi kode IaC kalian: disaster recovery untuk state. Kita membahas mengapa backup state adalah fondasi DR, bagaimana S3 versioning + DynamoDB locking membentuk pertahanan berlapis, prosedur pemulihan saat state corrupt (diagnosis → pull → perbaikan → push → verifikasi), hingga jalur penyelamatan terakhir berupa re-import dengan blok import ketika state benar-benar hilang. Kalian juga mendapat DR runbook checklist dan best practices yang harus dijaga sebagai disiplin tim.
Poin kunci yang perlu kalian bawa pulang:
state pull untuk inspeksi & backup, state push untuk pemulihan — dengan backup dan validasi di kedua arah.import block (episode 8) selalu menjadi jalan keluar.Kalian sekarang telah memiliki seluruh perangkat taktis: dari menulis kode, mengelola state, hingga menyelamatkannya dari kebakaran. Sekarang saatnya merangkai semuanya menjadi satu gambaran besar — bagaimana semua potongan yang kalian pelajari dari episode 0 hingga 19 menyatu dalam arsitektur IaC enterprise yang utuh.
Di episode 20 — episode penutup dari seri Belajar Terraform — kita akan merancang arsitektur enterprise end-to-end: modular + Terragrunt, remote backend terpusat, autentikasi OIDC passwordless, secret dari Vault, policy gate OPA, dan drift detection otomatis — plus checklist kesiapan produksi dan panduan code review. Ini puncak dari seluruh perjalanan kalian. Pastikan tetap semangat!