DevOps & Cloud

OpenTofu: Terraform Alternative

GRATIS

Kuasai OpenTofu — alternatif open-source Terraform dengan state encryption, removed block, dynamic provider configuration, dan full backward compatibility

1. OpenTofu vs Terraform

OpenTofu adalah fork open-source (Linux Foundation) dari Terraform yang dibuat sebagai respons terhadap perubahan lisensi Terraform dari MPL 2.0 ke BSL 1.1. OpenTofu 100% kompatibel dengan Terraform HCL dan menambahkan fitur-fitur baru yang tidak ada di Terraform.

1.1 Mengapa OpenTofu?

FiturOpenTofuTerraform
LisensiApache 2.0 (open-source)BSL 1.1 (non-open-source)
State Encryption✅ Native support❌ Tidak ada
Removed Block✅ Ya❌ Tidak ada
Dynamic Provider Config✅ Ya❌ Tidak ada
State File Encryption✅ NativeButuh external wrapper
Community GovernanceLinux FoundationHashiCorp (IBM)
Backend CompatibilityS3, GCS, Azure, K8s, HTTP, localSama
Provider Ecosystem100% kompatibel dengan Terraform RegistryNative
OpenTofu Workflow
📝
HCL Configuration
.tf files
Modules, Providers
Variables, Outputs
→ Plan →
📋
tofu plan
Diff: actual vs desired
Preview changes
No modifications
→ Apply →
🚀
tofu apply
Create/Update/Delete
Execute changes
Update state
→ Store →
🔒
Encrypted State
S3 + encryption
Lock via DynamoDB
Version history

2. Instalasi & Setup

Terminal — Install OpenTofu
# Method 1: Official installer (Linux/macOS)
curl -fsSL https://get.opentofu.org/install.sh | bash -s -- --install-method standalone

# Method 2: Package manager (Homebrew)
brew install opentofu

# Method 3: Binary download
# Download dari https://github.com/opentofu/opentofu/releases
wget https://github.com/opentofu/opentofu/releases/download/v1.8.0/tofu_1.8.0_linux_amd64.zip
unzip tofu_1.8.0_linux_amd64.zip
sudo mv tofu /usr/local/bin/

# Verifikasi instalasi
tofu version
# OpenTofu v1.8.0

# Migration dari Terraform — sangat mudah!
# 1. Backup state
cp terraform.tfstate terraform.tfstate.backup

# 2. Jalankan migrate command
tofu init -migrate-state

# 3. Done! Semua .tf file langsung bekerja
# Perintah terraform → tofu (drop-in replacement)
# terraform init → tofu init
# terraform plan → tofu plan
# terraform apply → tofu apply

2.1 Project Structure

Directory structure
# Struktur project OpenTofu yang baik
infra/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   ├── backend.tf
│   │   └── terraform.tfvars
│   ├── staging/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   ├── backend.tf
│   │   └── terraform.tfvars
│   └── production/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf
│       ├── backend.tf
│       └── terraform.tfvars
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── eks-cluster/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── rds/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
└── README.md

3. State Management

OpenTofu mendukung native state encryption — fitur yang tidak ada di Terraform. State bisa dienkripsi baik saat remote storage maupun local.

backend.tf — Remote state dengan encryption
# Remote backend: S3 dengan DynamoDB locking
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "ap-southeast-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

# OpenTofu: State encryption dengan passphrase
terraform {
  encryption {
    key_provider "pbkdf2" "my_key" {
      passphrase = var.state_encryption_passphrase
    }
    state {
      method = method.aes_gcm.my_key
    }
    plan {
      method = method.aes_gcm.my_key
    }
  }
}

# OpenTofu: State encryption dengan AWS KMS
terraform {
  encryption {
    key_provider "aws_kms" "my_kms_key" {
      kms_key_id = "arn:aws:kms:ap-southeast-1:123456789:key/abc-123"
      region     = "ap-southeast-1"
    }
    state {
      method = method.aes_gcm.my_kms_key
    }
  }
}

# OpenTofu: State encryption dengan GCP KMS
terraform {
  encryption {
    key_provider "gcp_kms" "my_key" {
      kms_encryption_key = "projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key"
    }
    state {
      method = method.aes_gcm.my_key
    }
  }
}
💡 State Encryption adalah Game Changer

Dengan OpenTofu, Anda tidak perlu lagi mengandalkan backend encryption yang terbatas. State file dienkripsi secara native — bahkan jika seseorang mendapatkan akses ke S3 bucket, mereka tidak bisa membaca state tanpa key. Ini termasuk plan files yang sebelumnya selalu plaintext.

4. Providers

main.tf — Provider configuration
# OpenTofu menggunakan Terraform Registry yang sama
terraform {
  required_version = ">= 1.6.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.25"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.12"
    }
  }
}

# AWS Provider
provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "opentofu"
      Project     = var.project_name
    }
  }
}

# Assume role untuk multi-account
provider "aws" {
  alias  = "production"
  region = "ap-southeast-1"
  assume_role {
    role_arn = "arn:aws:iam::${var.prod_account_id}:role/DeployRole"
  }
}

# Kubernetes Provider
provider "kubernetes" {
  host                   = module.eks.cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks.cluster_ca_certificate)
  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    args        = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
  }
}

5. Modules

modules/vpc/main.tf — Reusable VPC module
# modules/vpc/main.tf
variable "environment" {
  type = string
}

variable "vpc_cidr" {
  type    = string
  default = "10.0.0.0/16"
}

variable "availability_zones" {
  type    = list(string)
  default = ["ap-southeast-1a", "ap-southeast-1b", "ap-southeast-1c"]
}

variable "enable_nat_gateway" {
  type    = bool
  default = true
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "${var.environment}-vpc"
  }
}

resource "aws_subnet" "private" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, count.index)
  availability_zone = var.availability_zones[count.index]

  tags = {
    Name = "${var.environment}-private-${var.availability_zones[count.index]}"
  }
}

resource "aws_subnet" "public" {
  count                   = length(var.availability_zones)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = cidrsubnet(var.vpc_cidr, 8, count.index + 100)
  availability_zone       = var.availability_zones[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.environment}-public-${var.availability_zones[count.index]}"
  }
}

output "vpc_id" {
  value = aws_vpc.main.id
}

output "private_subnet_ids" {
  value = aws_subnet.private[*].id
}

output "public_subnet_ids" {
  value = aws_subnet.public[*].id
}

---
# Menggunakan module
module "vpc" {
  source = "../../modules/vpc"

  environment = var.environment
  vpc_cidr    = "10.0.0.0/16"
  enable_nat_gateway = true
}

module "eks" {
  source = "../../modules/eks-cluster"

  environment     = var.environment
  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnet_ids
  cluster_version = "1.29"
}

# Module dari registry
module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "20.0.0"
  # ...
}

6. Workspaces

Terminal — Workspaces management
# List workspaces
tofu workspace list

# Buat workspace baru
tofu workspace new development
tofu workspace new staging
tofu workspace new production

# Switch workspace
tofu workspace select development

# Gunakan workspace di configuration
# environments/dev/main.tf
locals {
  env_config = {
    development = {
      instance_type = "t3.micro"
      min_size      = 1
      max_size      = 2
    }
    staging = {
      instance_type = "t3.small"
      min_size      = 2
      max_size      = 4
    }
    production = {
      instance_type = "t3.large"
      min_size      = 3
      max_size      = 10
    }
  }
  config = local.env_config[terraform.workspace]
}

resource "aws_instance" "web" {
  instance_type = local.config.instance_type
  # ...
}

7. Drift Detection

Drift detection scripts
# Drift detection — cek apakah ada perubahan di cloud
# yang tidak tercatat di state
tofu plan -detailed-exitcode
# Exit code: 0 = no changes, 2 = changes detected, 1 = error

# Script CI/CD untuk drift detection
#!/bin/bash
set -euo pipefail

echo "Running drift detection..."
tofu plan -detailed-exitcode -out=drift.tfplan 2>&1 | tee plan_output.txt
EXIT_CODE=${PIPESTATUS[0]}

case $EXIT_CODE in
  0)
    echo "✅ No drift detected"
    exit 0
    ;;
  2)
    echo "⚠️ Drift detected!"
    tofu show -json drift.tfplan | jq '.resource_changes[] | select(.change.actions != ["no-op"])'
    # Kirim notifikasi
    curl -X POST "$SLACK_WEBHOOK" -d "{\"text\":\"Drift detected in ${ENVIRONMENT}\"}"
    exit 1
    ;;
  *)
    echo "❌ Error during drift detection"
    exit $EXIT_CODE
    ;;
esac

# OpenTofu: removed block — hapus dari state tanpa destroy
# Berguna saat ingin me-"lepaskan" resource dari management
removed {
  from = aws_instance.legacy_server

  lifecycle {
    destroy = false  # Jangan destroy, hanya lepas dari state
  }
}

8. Fitur Baru OpenTofu

OpenTofu-exclusive features
# 1. State Encryption (sudah dibahas di section 3)

# 2. Removed block — lepaskan resource tanpa destroy
removed {
  from = aws_s3_bucket.legacy
  lifecycle {
    destroy = false
  }
}

# 3. Dynamic provider configuration
# Provider yang bergantung pada variable/for_each
provider "aws" {
  for_each = toset(var.regions)
  alias    = each.key
  region   = each.value
}

# 4. Client-side state encryption
terraform {
  encryption {
    key_provider "pbkdf2" "my_key" {
      passphrase = var.encryption_passphrase
    }
    state {
      method = method.aes_gcm.my_key
      # Enkripsi hanya specific fields
      enforced = true
    }
  }
}

# 5. Loop over providers
module "regional_infra" {
  source   = "./modules/regional"
  for_each = toset(var.regions)
  providers = {
    aws = aws[each.key]
  }
  region = each.key
}

# 6. Moved block (sama dengan Terraform 1.1+)
moved {
  from = aws_instance.old_name
  to   = aws_instance.new_name
}

# 7. Import block (declarative import)
import {
  to = aws_s3_bucket.existing
  id = "my-existing-bucket"
}
⚠️ Migrasi dari Terraform

Migrasi dari Terraform ke OpenTofu sangat mudah — cukup jalankan tofu init -migrate-state. Namun, pastikan untuk backup state sebelumnya. Jika Anda menggunakan encryption block (fitur OpenTofu), state tidak bisa dibaca lagi oleh Terraform. Lakukan migrasi secara bertahap dan test di environment non-production terlebih dahulu.

9. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut:

Pertanyaan 1: Apa keunggulan utama OpenTofu dibandingkan Terraform?

a) OpenTofu lebih cepat dari Terraform
b) OpenTofu open-source (Apache 2.0) dengan native state encryption dan fitur baru seperti removed block
c) OpenTofu mendukung lebih banyak cloud provider
d) OpenTofu tidak membutuhkan state file

Pertanyaan 2: Apa fungsi removed block di OpenTofu?

a) Menghapus resource dari state tanpa menghapus resource aktual di cloud
b) Menghapus module dari konfigurasi
c) Menghapus provider dari project
d) Menghapus output values

Pertanyaan 3: Bagaimana cara melakukan drift detection di OpenTofu?

a) tofu drift check
b) tofu plan -detailed-exitcode — exit code 2 menandakan drift
c) tofu validate --drift
d) Drift detection otomatis setiap jam

Pertanyaan 4: Apa fungsi tofu init -migrate-state?

a) Menginstal OpenTofu untuk pertama kali
b) Meng-migrate state dari Terraform ke OpenTofu dan mengupdate backend configuration
c) Menghapus state lama
d) Menginstall providers baru

Pertanyaan 5: Mengapa state encryption di OpenTofu penting untuk security?

a) Karena state file sering berisi secrets (password, API keys) dan dengan encryption, file tidak bisa dibaca tanpa key meskipun diakses oleh pihak tidak berwenang
b) Karena encryption membuat state file lebih kecil
c) Karena encryption diperlukan oleh cloud provider
d) Karena encryption mempercepat tofu plan
← Sebelumnya Crossplane: Infrastructure as Code Selanjutnya → Backstage Developer Portal
🔍 Zoom
100%
🎨 Tema