Remote #
Remote state memindahkan file terraform.tfstate dari mesin lokalmu ke penyimpanan terpusat yang bisa diakses oleh semua anggota tim dan CI/CD pipeline. Ini bukan sekadar “state di tempat lain” — remote backend biasanya datang dengan fitur tambahan yang krusial: enkripsi at rest, versioning otomatis, dan state locking. Artikel ini membahas cara mengkonfigurasi backend yang paling umum digunakan dan kapan memilih yang mana.
Konsep Backend #
Backend adalah komponen Terraform yang bertanggung jawab menyimpan state dan menjalankan operasi tertentu. Secara default, backend adalah local. Mengkonfigurasi remote backend mengubah di mana state disimpan.
LOCAL BACKEND (default):
State → terraform.tfstate (di mesinmu)
Locking → tidak ada
Versioning → terraform.tfstate.backup (1 versi saja)
REMOTE BACKEND (S3, GCS, Terraform Cloud, dll.):
State → bucket/container di cloud
Locking → DynamoDB / GCS locks / built-in
Versioning → S3 versioning / built-in history
Enkripsi → at rest + in transit
Audit → access log tersedia
flowchart TD
A["terraform apply"] --> B{"Backend?"}
B -->|"Default\n(local)"| C["terraform.tfstate"]
B -->|"Remote"| D["S3 / GCS /\nTerraform Cloud"]
C --> E["⚠️ Tidak ada locking"]
C --> F["1 file backup saja"]
C --> G["Tidak ter-encrypt"]
D --> H["✅ State locking"]
D --> I["✅ Versioning otomatis"]
D --> J["✅ Enkripsi at rest"]
D --> K["✅ Audit log"]
style A fill:#e3f2fd,stroke:#1565c0
style C fill:#fff3e0,stroke:#e65100
style D fill:#e8f5e9,stroke:#2e7d32Backend S3 (AWS) #
S3 adalah pilihan paling umum untuk tim yang bekerja di AWS. Kombinasi S3 untuk storage dan DynamoDB untuk locking adalah pola standar industri.
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state-prod"
key = "production/terraform.tfstate"
region = "ap-southeast-1"
# Enkripsi at rest
encrypt = true
# State locking menggunakan DynamoDB
dynamodb_table = "terraform-state-lock"
# Opsional: gunakan IAM role untuk akses
# role_arn = "arn:aws:iam::123456789:role/TerraformStateRole"
}
}
# Buat resource S3 bucket dan DynamoDB table untuk state backend
# (biasanya dikerjakan terpisah sebelum konfigurasi utama)
resource "aws_s3_bucket" "terraform_state" {
bucket = "my-terraform-state-prod"
# Mencegah penghapusan bucket yang berisi state
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled" # Wajib — memungkinkan recovery state lama
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_dynamodb_table" "terraform_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
flowchart TD
A["Terraform\nKonfigurasi"] --> B["S3 Bucket\n(state storage)"]
A --> C["DynamoDB Table\n(locking)"]
B --> D["Versioning\naktif"]
B --> E["Enkripsi\nAES256"]
B --> F["prevent_destroy\nlifecycle"]
style A fill:#e3f2fd,stroke:#1565c0
style B fill:#e8f5e9,stroke:#2e7d32
style C fill:#fff3e0,stroke:#e65100Backend GCS (Google Cloud) #
Untuk tim yang bekerja di Google Cloud, GCS backend sudah mendukung locking secara native tanpa perlu resource tambahan.
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "production"
# GCS backend sudah built-in locking — tidak perlu resource tambahan
}
}
Terraform Cloud / HCP Terraform #
Terraform Cloud (sekarang bernama HCP Terraform) adalah opsi managed yang menyertakan state storage, locking, versioning, run history, dan UI untuk review plan — semua dalam satu paket.
terraform {
cloud {
organization = "my-org"
workspaces {
name = "production"
}
}
}
# Login ke Terraform Cloud
terraform login
# Akan membuka browser untuk autentikasi
# Setelah login, init akan setup workspace di Terraform Cloud
terraform init
Struktur Key yang Baik untuk S3 #
Saat menggunakan S3 backend untuk beberapa environment atau proyek, struktur key yang konsisten memudahkan navigasi.
STRUKTUR KEY YANG DIREKOMENDASIKAN:
s3://my-terraform-state/
├── production/
│ ├── networking/terraform.tfstate
│ ├── compute/terraform.tfstate
│ └── database/terraform.tfstate
├── staging/
│ ├── networking/terraform.tfstate
│ └── compute/terraform.tfstate
└── dev/
└── terraform.tfstate
Konfigurasi per environment:
key = "production/networking/terraform.tfstate"
key = "production/compute/terraform.tfstate"
key = "staging/networking/terraform.tfstate"
Remote State Output: Membaca State dari Workspace Lain #
Salah satu fitur powerful remote state adalah kemampuan membaca output dari workspace Terraform lain. Ini memungkinkan infrastruktur di-modularisasi ke beberapa workspace yang terpisah tapi bisa saling berbagi data.
# Workspace "networking" membuat VPC dan meng-output VPC ID
# outputs.tf di workspace networking:
output "vpc_id" {
value = aws_vpc.main.id
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
# Workspace "compute" membaca output dari workspace "networking"
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "production/networking/terraform.tfstate"
region = "ap-southeast-1"
}
}
# Gunakan output dari workspace networking
resource "aws_instance" "web" {
ami = var.ami_id
subnet_id = data.terraform_remote_state.networking.outputs.private_subnet_ids[0]
}
terraform_remote_state membuat coupling langsung antara dua workspace — perubahan output di workspace networking bisa berdampak ke workspace compute. Pertimbangkan menggunakan variable input dan mengoper nilainya secara eksplisit jika coupling yang erat ini tidak diinginkan.sequenceDiagram
participant C as Workspace Compute
participant B as Backend S3
participant N as Workspace Networking
Note over N: terraform apply selesai
N->>B: Tulis state + outputs
Note over B: State tersimpan<br/>vpc_id = vpc-abc123<br/>subnet_ids = [subnet-x, subnet-y]
Note over C: terraform plan dimulai
C->>B: data "terraform_remote_state" "networking"
B-->>C: Return outputs
C->>C: Gunakan vpc_id, subnet_ids
Note over C: Plan selesai
style N fill:#e8f5e9,stroke:#2e7d32
style B fill:#fff3e0,stroke:#e65100
style C fill:#e3f2fd,stroke:#1565c0flowchart LR
A["Workspace\nNetworking"] -->|outputs:\nvpc_id, subnet_ids| B["terraform_remote_state\ndata source"]
B -->|baca output| C["Workspace\nCompute"]
C -->|"subnet_id =\ndata.terraform_remote_state...\n.outputs.private_subnet_ids[0]"| D["aws_instance.web"]
style A fill:#e8f5e9,stroke:#2e7d32
style B fill:#fff3e0,stroke:#e65100
style C fill:#e3f2fd,stroke:#1565c0Multi-Backend Failover #
Terraform tidak mendukung failover backend secara native — jika backend S3 down, terraform apply akan gagal. Tapi ada pola yang bisa diterapkan untuk meningkatkan resilience.
# PROBLEM: S3 backend unavailable → pipeline stuck
$ terraform plan
# Error: failed to retrieve state from S3: RequestError...
# → Seluruh pipeline CI/CD terhenti
# SOLUSI 1: Cross-region replication pada S3 bucket
# Aktifkan cross-region replication pada S3 state bucket
resource "aws_s3_bucket_replication_configuration" "terraform_state" {
role = aws_iam_role.replication.arn
bucket = aws_s3_bucket.terraform_state.id
rule {
id = "replicate-state"
status = "Enabled"
destination {
bucket = aws_s3_bucket.terraform_state_replica.arn
storage_class = "STANDARD"
}
}
}
# Bucket replica di region berbeda
resource "aws_s3_bucket" "terraform_state_replica" {
provider = aws.replica_region
bucket = "my-terraform-state-prod-replica"
}
# BACKEND TIDAK BISA OTOMATIS FAILOVER
# Tapi jika S3 primary down, kamu bisa temporary switch backend:
# LANGKAH EMERGENCY: Switch ke backup bucket
# 1. Update backend.tf ke bucket replica
# 2. Jalankan terraform init untuk reconfigure
terraform init -migrate-state -force-copy
# 3. Setelah primary kembali, switch kembali dan re-migrate
# SOLUSI 2: Backend configuration dengan workspace
# Simpan konfigurasi backend di Terraform Cloud/Enterprise
# yang hosted oleh HashiCorp → availability lebih tinggi
State Encryption Deep Dive #
# AWS S3 SSE-S3 (default encryption, basic)
# Setiap object di-encrypt dengan S3-managed key
# Tidak perlu konfigurasi — aktif otomatis di bucket baru
# AWS S3 SSE-KMS (recommended untuk production)
# Enkripsi menggunakan KMS key yang bisa di-manage sendiri
# Memungkinkan audit trail siapa yang mengakses key
# SSE-KMS encryption untuk state bucket
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
kms_key_id = aws_kms_key.terraform_state.arn
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true # Mengurangi KMS API costs
}
}
resource "aws_kms_key" "terraform_state" {
description = "KMS key untuk Terraform state encryption"
deletion_window_in_days = 30
enable_key_rotation = true # Auto-rotate key setiap tahun
}
resource "aws_kms_alias" "terraform_state" {
name = "alias/terraform-state"
target_key_id = aws_kms_key.terraform_state.key_id
}
PERBANDINGAN ENCRYPTION OPTIONS:
SSE-S3 (AES256):
Keamanan: Standar
Key management: S3-managed (tidak bisa diatur)
Audit: Tidak bisa track siapa yang decrypt
Cost: Gratis
Cocok untuk: Dev, staging, proyek personal
SSE-KMS:
Keamanan: Tinggi
Key management: Customer-managed key (CMK)
Audit: CloudTrail log semua key usage
Cost: $1/key/month + API call charges
Cocok untuk: Production, compliance requirements
Customer-provided key (SSE-C):
Keamanan: Sangat tinggi
Key management: Customer supplies key di setiap request
Audit: Full control
Cost: Gratis (tapi management overhead tinggi)
Cocok untuk: Extreme security requirements (jarang dipakai)
Remote State Data Lifecycle #
Memahami lifecycle remote state membantu merencanakan strategy penanganan state dari pembuatan hingga penghapusan.
flowchart TD
A["terraform init\n(setup backend)"] --> B["State kosong"]
B --> C["terraform apply #1\n(buat resource pertama)"]
C --> D["State v1\n(serial: 1)"]
D --> E["terraform apply #2\n(tambah resource)"]
E --> F["State v2\n(serial: 2)"]
F --> G["S3 Versioning:\nv1 tetap tersimpan"]
G --> H["terraform destroy\n(hapus semua resource)"]
H --> I["State vN\n(serial: N, resources: [])"]
I --> J["State tetap di S3\n(empty tapi ada)"]
J --> K["Manual cleanup\ndiperlukan"]
style A fill:#e3f2fd,stroke:#1565c0
style D fill:#e8f5e9,stroke:#2e7d32
style G fill:#fff3e0,stroke:#e65100
style K fill:#ffebee,stroke:#c62828# State setelah terraform destroy TIDAK otomatis terhapus dari S3
# State berisi {"resources":[]} tapi file tetap ada
# Plus semua versi lama tetap ada di S3 versioning
# Cleanup state yang sudah tidak dipakai:
# 1. Hapus current state version
aws s3 rm s3://my-terraform-state/production/terraform.tfstate
# 2. Hapus semua versi lama (termasuk delete markers)
aws s3api list-object-versions \
--bucket my-terraform-state \
--prefix production/terraform.tfstate \
--query 'Versions[*].[VersionId,Key]' \
--output text | while read vid key; do
aws s3api delete-object --bucket my-terraform-state --key "$key" --version-id "$vid"
done
# 3. Hapus DynamoDB lock entry (jika masih ada)
aws dynamodb delete-item \
--table-name terraform-state-lock \
--key '{"LockID":{"S":"my-terraform-state/production/terraform.tfstate"}}'
# MONITORING STATE BUCKET:
# Ukuran state file biasanya kecil (KB-MB), tapi versioning bisa
# mengakumulasi storage jika sering apply
# Cek jumlah versi per state file
aws s3api list-object-versions \
--bucket my-terraform-state \
--query 'length(Versions)'
# Set lifecycle policy untuk auto-cleanup versi lama
# (jika tidak ingin simpan semua history)
# Lifecycle rule untuk menghapus versi lama
resource "aws_s3_bucket_lifecycle_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
id = "cleanup-old-versions"
status = "Enabled"
noncurrent_version_expiration {
noncurrent_days = 90 # Hapus versi lama setelah 90 hari
}
noncurrent_version_transition {
noncurrent_days = 30
storage_class = "GLACIER" # Pindah ke Glacier setelah 30 hari
}
}
}
Ringkasan #
- Remote backend memindahkan state ke penyimpanan terpusat dengan fitur tambahan: enkripsi, versioning otomatis, dan locking.
- S3 + DynamoDB adalah kombinasi standar industri untuk AWS — S3 untuk storage, DynamoDB untuk locking.
- GCS backend sudah built-in locking — tidak butuh resource tambahan seperti DynamoDB.
- Terraform Cloud adalah opsi managed lengkap — state storage, locking, run history, dan UI dalam satu paket.
- Struktur key yang konsisten di S3 (
<env>/<component>/terraform.tfstate) memudahkan navigasi untuk proyek multi-environment.terraform_remote_statememungkinkan workspace lain membaca output — powerful tapi menciptakan coupling, gunakan dengan pertimbangan.- Multi-backend failover tidak didukung native — gunakan S3 cross-region replication dan reconfigure backend saat darurat.
- SSE-KMS direkomendasikan untuk production — menyediakan audit trail melalui CloudTrail dan key rotation otomatis.
- State tetap ada di S3 setelah
terraform destroy— lakukan manual cleanup untuk menghapus file kosong dan versi lama.- S3 lifecycle policy bisa otomatis memindahkan versi lama ke Glacier dan menghapus setelah 90 hari.