MAISON CODE .
/ Tech · DevOps · Terraform · IaC · AWS

Terraform: Infrastructure as Actual Code

ClickOps is dangerous. CloudFormation is verbose. Terraform is the industry standard for defining repeatable, version-controlled infrastructure.

AB
Alex B.
Terraform: Infrastructure as Actual Code

The “Snowflake” Server and the ClickOps Disaster

In the old days of SysAdmin culture, a server was a pet. You named it “Gandalf” or “Zeus”. A developer would SSH into the server, run apt-get install nginx, edit a config file using vi, restart the service, and maybe tweak a kernel parameter (sysctl.conf) to optimize network throughput. They would do this for 5 years. The server became a Snowflake. Unique. Beautiful. Fragile. If “Gandalf” died (hardware failure), panic ensued. “How do we rebuild it?” “I don’t know, Bob set it up in 2018 and he left the company.” “What was the config?” “It was on the hard drive that just burned.” This is ClickOps (configuring via Console/GUI) and manual administration. It is a disaster waiting to happen. In the cloud era, servers are cattle, not pets. You name them web-worker-01, web-worker-02. If one gets sick, you shoot it and spawn a new one. Infrastructure as Code (IaC) is the methodology that enables this. You define your infrastructure in text files (.tf). You commit them to Git. You review them. You apply them using a CLI. The machine builds the server. Ideally, no human ever SSHs into a machine again.

Why Maison Code Discusses This

At Maison Code, we manage infrastructure for multiple high-growth clients. One client handles Flash Sales (100x traffic spikes). Another handles Medical Data (HIPAA compliance, strict encryption). We cannot rely on human memory to ensure these environments are correct. “Did I enable Encryption on that S3 bucket?” If you rely on memory, the answer is “Maybe”. We use Terraform to ensure the answer is “Yes, it is in line 42 of storage.tf”. We build reusable Modules. We have a standard “Maison Code Safe Bucket” module that enforces encryption, logging, and versioning. We use this for every client. This ensures Standardization and Security at Scale. We don’t solve the same problem twice. We solve it once in Terraform, and deploy it everywhere.

The Tool: HashiCorp Terraform

Terraform is the gold standard because it is Cloud Agnostic. You can use it to manage AWS, Google Cloud, Azure, Cloudflare, GitHub, and even your Domino’s Pizza order (yes, there is a provider). Compare this to CloudFormation (AWS only) or ARM Templates (Azure only). Learning Terraform gives you a superpower across the entire industry. It uses HCL (HashiCorp Configuration Language). It is declarative. You describe the destination, not the journey. “I want 5 servers.” (Terraform figures out how to get from 2 to 5). Instead of “Create 3 servers.” (Imperative).

Example: Creating an S3 Bucket

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "assets" {
  bucket = "maison-code-assets-prod"
  
  tags = {
    Environment = "Production"
    Project     = "Maison"
    ManagedBy   = "Terraform"
  }
}

resource "aws_s3_bucket_public_access_block" "block" {
  bucket = aws_s3_bucket.assets.id
  
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.assets.id
  versioning_configuration {
    status = "Enabled"
  }
}

This code is Documentation. Anyone reading it knows: “We have a bucket. It is explicitly private. Versioning is enabled (so we can recover deleted files).” This is better than a 50-page Word document describing the server setup (which is always outdated).

The State File: The Brain of Terraform

Terraform tracks what it created in a file called terraform.tfstate. This is a JSON file that maps your code resources (resource "aws_instance" "app") to real-world identifiers (i-0a1b2c3d4e5f). Current State vs Desired State. When you run terraform plan, Terraform:

  1. Reads your code (Desired State).
  2. Reads the State File (Last known state).
  3. Refreshes the State (checks AWS APIs to see if things changed).
  4. Calculates the “Delta” (Diff). Then it tells you: “I plan to add 1 resource, change 2 resources, and destroy 0 resources.” Danger: The State File contains secrets (passwords, private keys) in plain text. Best Practice: Never commit terraform.tfstate to Git. Use a Remote Backend. Store the state in an S3 Bucket with Server-Side Encryption enabled. Use a DynamoDB Table for State Locking. This prevents two developers from running terraform apply at the same time and corrupting the state.

Modules: The DON’T REPEAT YOURSELF (DRY) Principle

If you copy-paste the aws_instance block 10 times for 10 servers, you are doing it wrong. Create a Module.

Module Definition (modules/web-server/main.tf):

variable "size" { 
  type    = string
  default = "t2.micro" 
}
variable "name" { type = string }

resource "aws_instance" "app" {
  ami           = "ami-12345678"
  instance_type = var.size
  tags = {
    Name = var.name
  }
}

Usage (main.tf):

module "frontend" {
  source = "./modules/web-server"
  size   = "t3.small"
  name   = "Frontend-01"
}

module "backend" {
  source = "./modules/web-server"
  size   = "m5.large"
  name   = "Backend-API"
}

If you decide to change the AMI ID (upgrade Ubuntu version), you change it in one place (the module), and it updates all servers.

Drift Detection: The Reality Check

What if a rogue developer logs into the AWS Console and manually changes the Security Group to open Port 22 (SSH) to the world? This is Configuration Drift. The Reality no longer matches the Code. Next time you run terraform plan, Terraform will see this. “Output: Security Group ingress rule changed from port 22 (0.0.0.0/0) to NULL.” It will propose to fix the environment back to the state defined in the code. This enforces discipline. “ClickOps” changes are temporary and will be wiped out by the next deployment.

Terraform Workspaces: Multi-Environment

You need Dev, Staging, and Production. Do not replicate folder structures (/dev, /prod). Use Workspaces. terraform workspace new staging. terraform workspace new prod. You use the same .tf files, but different state files (terraform.tfstate.d/staging, terraform.tfstate.d/prod). In your code, you can use logic: count = terraform.workspace == "prod" ? 5 : 1. Prod gets 5 servers. Dev gets 1.

Policy as Code (Sentinel / OPA)

In large organizations, you want to prevent developers from making mistakes. “No one can create a public S3 bucket.” “No one can provision an instance larger than large (too expensive).” You can use Open Policy Agent (OPA) or HashiCorp Sentinel. It runs before terraform apply. If the plan violates the policy, it blocks the deployment. This is Automated Governance.

The Skeptic’s View

“It’s too much boilerplate. I can just click the button faster.” Counter-Point: Clicking is faster once. But you have to maintain it forever. If you need to replicate the environment in another region (Disaster Recovery), clicking takes days and is error-prone. Terraform takes minutes (region = "eu-west-1"). Also, “ClickOps” cannot be code-reviewed. You can’t open a Pull Request for a mouse click. You can’t revert a mouse click (easily). Code is auditability. Code is sanity.

FAQ

Q: Terraform vs Ansible? A: Terraform provisions infrastructure (The Hardware: VPC, EC2, RDS). Ansible configures software (The Software: Apache, MySQL Config, Users). In the modern “Immutable Infrastructure” world (Docker), Ansible is less needed. We bake the software into the Docker Image. Terraform deploys the container service (ECS/EKS). Use Terraform for the Cloud. Use Ansible for the OS (if you aren’t using Containers).

Q: What is main.tf, variables.tf, outputs.tf? A: It is a convention. Terraform reads all .tf files in the directory.

  • main.tf: The resources.
  • variables.tf: Input arguments.
  • outputs.tf: What to print at the end (e.g., Load Balancer URL).

Q: Terraform Cloud vs Jenkins / GitHub Actions? A: Terraform Cloud offers nice features:

  • Remote State Management (Built-in).
  • Private Module Registry.
  • Cost Estimation (“This change will increase your bill by $50”). However, you can run Terraform CLI inside GitHub Actions using an S3 Backend for free. Terraform Cloud is paid (per user). We usually start with GitHub Actions and upgrade if needed.

Conclusion

Infrastructure as Code turns “Ops” into “Dev”. It brings the discipline of software engineering (Version Control, Code Review, Testing, CI/CD) to the world of hardware. If it’s not in git, it doesn’t exist. Stop building Snowflakes. Start building Legos.

Clicking Buttons manually?

If your infrastructure is a delicate snowflake that you are afraid to touch, Maison Code can terraform it. We reverse-engineer your existing “ClickOps” setup and codify it into robust, reusable Terraform modules. We implement State Locking, Drift Detection, and Disaster Recovery workflows.



Managing Cloud via Console?

We implement Infrastructure as Code (Terraform) to ensure security compliance and disaster recovery. Hire our Architects.