Infrastructure as Code with Terraform: Why Your Servers Should Be Defined in Files

Last year, a coworker accidentally deleted a production database while clicking around in the AWS console. It took us 14 hours to restore everything. That was the day we switched to Infrastructure as Code. The tool we chose was Terraform, and I haven’t logged into a cloud console for infrastructure changes since.

What Is Infrastructure as Code?

Instead of manually creating servers, databases, and networks through a web interface, you define them in configuration files. These files are checked into Git, reviewed in pull requests, and applied through automation. No more “who changed the firewall rules?” moments.

Terraform Basics

Terraform uses its own language called HCL (HashiCorp Configuration Language). Here’s what a basic web server setup looks like:

# Define the cloud provider
provider "aws" {
  region = "us-east-1"
}

# Create a virtual server
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  
  tags = {
    Name        = "web-server"
    Environment = "production"
  }
}

# Create a database
resource "aws_db_instance" "main" {
  engine         = "postgres"
  engine_version = "15"
  instance_class = "db.t3.micro"
  
  db_name  = "myapp"
  username = "admin"
  password = var.db_password  # Never hardcode passwords
}

The Workflow

# Initialize (downloads provider plugins)
terraform init

# See what will change (dry run)
terraform plan

# Apply changes
terraform apply

# Destroy everything (careful!)
terraform destroy

The plan step is critical. It shows you exactly what Terraform will create, modify, or destroy before it does anything. Review this output carefully.

State Management

Terraform tracks what it’s managing in a state file. For team use, store this remotely:

terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

Never edit the state file manually. Never store it in Git (it can contain secrets). Always use a remote backend for team projects.

Variables and Modules

# variables.tf
variable "environment" {
  type    = string
  default = "staging"
}

variable "instance_count" {
  type    = number
  default = 2
}

# Use variables
resource "aws_instance" "web" {
  count         = var.instance_count
  instance_type = var.environment == "production" ? "t3.large" : "t3.micro"
}

Why This Matters

  • Reproducibility: Spin up an exact copy of production for testing
  • Documentation: The code IS the documentation of your infrastructure
  • Version control: See exactly what changed and when, with Git history
  • Code review: Infrastructure changes go through the same PR process as application code
  • Disaster recovery: If something breaks, terraform apply rebuilds everything

Start small. Take one manually created resource and define it in Terraform. Then do another. Within a month, you’ll never want to go back to clicking through consoles.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top