Back to All Articles
#Terraform#IaC#AWS

Terraform: Stop Clicking Around in the Console

•8 min read•By Shuja Ahmed (DevOps Engineer)

Why infrastructure as code matters, how to get started without overengineering, and the common pitfalls beginners fall into. Practical code samples included.

We have all done it at some point in our careers. You log into the AWS Management Console, click through three different configuration tabs, create a security group, attach an elastic IP, and spin up a database. It takes twenty minutes. The application works. You feel productive.

Then three months pass. A junior engineer accidentally deletes the security group rule. Your production traffic goes black. You open the AWS console to fix it, but nobody remembers whether the database was running on port 5432 or 5433, or which subnet mask was assigned to the private routing table. The original documentation consists of a vague two-line note in Notion.

This practice is known as Click-Ops. Click-Ops is the fastest way to accumulate technical debt in cloud infrastructure.

Infrastructure as Code (IaC) with HashiCorp Terraform or OpenTofu eliminates this fragility entirely. Here is why it matters, how to organize your configuration, and how to avoid the mistakes that derail beginners.

#What Infrastructure as Code Really Gives You

When you codify your infrastructure in declarative configuration files, you gain three critical superpowers:

  1. 1Version History & Accountability: Every VPC change, IAM permission addition, and database resize is documented in a git pull request. You know exactly who changed a resource, when they changed it, and why.
  2. 2Environment Parity: Spinning up an identical staging environment takes one command: terraform apply. You eliminate the classic developer excuse: "Well, it works fine in staging, so production must be configured differently."
  3. 3Disaster Recovery: If your entire primary cloud region goes offline tomorrow, you can point your Terraform state to an alternate region and recreate your full infrastructure stack in under twenty minutes.

#A Clean, Real-World Terraform Example

Beginners often get overwhelmed by massive open-source Terraform modules with two hundred configurable variables. Start small and keep your resources readable.

Here is a clean example of defining an isolated AWS Virtual Private Cloud (VPC) with a public subnet, internet gateway, and automated tagging:

hcl
# main.tf
terraform {
  required_version = ">= 1.8.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.50"
    }
  }

  backend "s3" {
    bucket         = "shuja-terraform-state-prod"
    key            = "networking/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-state-locks"
    encrypt        = true
  }
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Environment = "Production"
      ManagedBy   = "Terraform"
      Project     = "CoreInfrastructure"
    }
  }
}

# Isolated VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "production-vpc"
  }
}

# Internet Gateway for Public Outbound Routing
resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "production-igw"
  }
}

# Public Subnet
resource "aws_subnet" "public_1" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-1a"
  }
}

#Handling Secrets and Sensitive Variables

A common mistake when beginning with Terraform is writing database passwords, API tokens, or private keys directly in terraform.tfvars files and accidentally committing them to GitHub.

Instead of hardcoding credentials, integrate Terraform directly with AWS Secrets Manager or HashiCorp Vault. Let Terraform generate random cryptographic passwords and store them securely in the cloud:

hcl
# Generate a secure random password for RDS
resource "random_password" "db_password" {
  length  = 24
  special = false
}

# Store the generated credential inside AWS Secrets Manager
resource "aws_secretsmanager_secret" "db_secret" {
  name                    = "production/database/master-credentials"
  recovery_window_in_days = 0
}

resource "aws_secretsmanager_secret_version" "db_secret_val" {
  secret_id     = aws_secretsmanager_secret.db_secret.id
  secret_string = jsonencode({
    username = "dbadmin"
    password = random_password.db_password.result
  })
}

Your application containers read the credentials at runtime using IAM Task Roles, and no human engineer ever needs to view or copy the plaintext password.

#Three Fatal Mistakes Beginners Make With Terraform

1. Storing State Locally on Your Laptop

Your Terraform state file (terraform.tfstate) contains the mapping between your code and actual cloud resources. It also contains sensitive configuration variables in plaintext. Never commit your state file to git, and never leave it on a developer laptop. Always configure a remote S3 backend with AES-256 encryption and a DynamoDB table for state locking to prevent concurrent apply conflicts.

2. Creating One Giant "God" State File

Do not put your networking, Kubernetes clusters, database, DNS records, and IAM policies into a single directory with 5,000 lines of code. When you run terraform plan on a monolithic state, it can take ten minutes just to refresh all resources, and a syntax error in your DNS records will block database updates. Split your state by lifecycle:

  • 01-networking (changes once a year)
  • 02-database (changes rarely)
  • 03-compute (changes with new services)
  • 04-applications (changes frequently)

3. Making Manual Console Edits on Terraform-Managed Resources

The moment someone opens the AWS console and manually modifies a security group that is managed by Terraform, you introduce state drift. The next time an engineer runs terraform apply, Terraform will detect the drift and overwrite the manual change. Enforce a strict team policy: if a resource is managed in Terraform, all changes must flow through a git pull request.

Treat your infrastructure with the same discipline and version control you apply to your application code. Your future self will thank you.

SA
Shuja AhmedDevOps Engineer
More Articles
Direct Engineering Consultation

Need help implementing this in your own stack?

Book a complimentary 30-minute discovery call. We will audit your current bottlenecks, evaluate your cloud architecture, and give you concrete recommendations with zero sales pressure.