1. What is Infrastructure as Code (IaC)?#
Infrastructure as Code (IaC) is the process of managing and provisioning computing infrastructure—such as virtual machines, networks, load balancers, and databases—through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools.
Before IaC, System Administrators had to physically rack servers, plug in network cables, and manually install operating systems. As the industry shifted to the Cloud (AWS, GCP, Azure), “ClickOps” became the norm. Engineers would log into a web portal and click buttons to deploy resources.
However, imagine you are tasked with deploying a complex microservices architecture consisting of 50 microservices, 10 databases, 3 load balancers, and intricate networking rules. Clicking through a web console to configure this would take days. What if you need to replicate this exact environment for a Staging environment? It is a nightmare.
The Terraform Solution#
Terraform, created by HashiCorp, solves this by allowing you to write your infrastructure in a declarative programming language called HashiCorp Configuration Language (HCL).
You simply write code declaring what you want (e.g., “I want 5 AWS EC2 instances in the US-East region”). Terraform figures out how to make that happen by making the necessary API calls to the cloud provider on your behalf.
Imperative vs. Declarative IaC#
It is crucial to understand the difference between Imperative and Declarative paradigms.
| Paradigm | How it works | Analogy | Example Tools |
|---|---|---|---|
| Imperative | You define the exact steps required to achieve a goal. | “Get in the car, drive 5 miles north, turn left, stop at the red house.” | Bash Scripts, Python scripts (Boto3). |
| Declarative | You define the final desired state. The tool figures out the steps. | “Take me to the red house.” (Like an Uber driver). | Terraform, Kubernetes YAML, Crossplane. |
If you run a Bash script that says aws ec2 run-instances twice, you will get 2 servers.
If you run a Terraform file that says instances: 1 twice, you will only get 1 server. Terraform knows the server already exists and does nothing on the second run. This is called Idempotence.
2. The Core Concept: The Terraform State File (.tfstate)#
The most critical, yet frequently misunderstood, component of Terraform is the State File.
How does Terraform know that a specific AWS EC2 instance belongs to your code? How does it know that running the code a second time shouldn’t create a duplicate instance?
The answer is terraform.tfstate.
When Terraform successfully creates a resource in the cloud, it records the unique ID of that physical resource (e.g., i-0abcd1234efgh5678) into a local JSON file called terraform.tfstate. This file acts as a mapping database between your HCL code and the real world.
The Reconciliation Loop#
Whenever you run terraform plan or terraform apply, Terraform performs a reconciliation loop:
- Read: It reads your HCL code (Desired State).
- Fetch: It looks at the
.tfstatefile to see what it thinks exists. - Refresh: It makes API calls to AWS to verify if the resources in the
.tfstatefile actually still exist in the physical cloud. - Compare: It calculates the “Delta” (difference) between your HCL code and the physical cloud.
- Execute: It creates, updates, or deletes resources to make the physical cloud perfectly match your HCL code.
Never edit the .tfstate file manually!
It is a highly sensitive JSON file generated strictly by Terraform. Manually altering it will corrupt the mapping, causing Terraform to lose track of your cloud resources, potentially resulting in accidental mass deletions.
3. Practice: Your First Terraform Execution#
We will not use AWS in this first episode to avoid complex authentication setups. Instead, we will use the local provider to create a simple text file on your laptop. This perfectly demonstrates the Terraform workflow without requiring a cloud account.
Step 3.1: Writing the HCL Configuration#
Create a new directory named terraform-basics and navigate into it:
mkdir terraform-basics
cd terraform-basicsCreate a file named main.tf and paste the following code:
# main.tf
# 1. Declare the Provider
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.4.0"
}
}
}
# 2. Declare a Resource
resource "local_file" "my_first_file" {
filename = "${path.module}/hello-world.txt"
content = "Welcome to the TotalTypeScript paradigm of Terraform!"
}Step 3.2: Initialize the Directory (terraform init)#
Before Terraform can do anything, it needs to download the local provider plugin from the internet.
terraform initExpected Terminal Output:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/local versions matching "~> 2.4.0"...
- Installing hashicorp/local v2.4.0...
- Installed hashicorp/local v2.4.0 (signed by HashiCorp)
Terraform has been successfully initialized!If you list the files in your directory (ls -la), you will notice a new hidden .terraform/ folder. This is where Terraform stores the downloaded plugins.
Step 3.3: Previewing the Changes (terraform plan)#
The golden rule of Terraform is: Never apply without planning.
The plan command tells you exactly what Terraform intends to do, without actually doing it.
terraform planExpected Terminal Output:
Terraform will perform the following actions:
# local_file.my_first_file will be created
+ resource "local_file" "my_first_file" {
+ content = "Welcome to the TotalTypeScript paradigm of Terraform!"
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./hello-world.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.The + symbol means Terraform will create this resource.
Step 3.4: Executing the Changes (terraform apply)#
Now, let’s execute the plan.
terraform apply -auto-approve(Note: We use -auto-approve to bypass the interactive “yes” prompt).
Expected Terminal Output:
local_file.my_first_file: Creating...
local_file.my_first_file: Creation complete after 0s [id=a1b2c3d4e5f6g7h8i9j0]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Check your directory. You should see a new file named hello-world.txt. Open it, and you will see the content we defined in main.tf.
4. Observing the State File#
Remember the .tfstate file we discussed earlier? Let’s prove it exists. Look inside your directory, and you will find terraform.tfstate.
Let’s read its contents using standard terminal commands:
cat terraform.tfstateExpected Terminal Output (Truncated for brevity):
{
"version": 4,
"terraform_version": "1.5.7",
"serial": 1,
"lineage": "abc-123-def-456",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "local_file",
"name": "my_first_file",
"provider": "provider[\"registry.terraform.io/hashicorp/local\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"content": "Welcome to the TotalTypeScript paradigm of Terraform!",
"filename": "./hello-world.txt",
"id": "a1b2c3d4e5f6g7h8i9j0"
}
}
]
}
]
}Terraform has recorded the exact state of the text file in JSON format. This is the ultimate source of truth for your infrastructure.
5. Destroying Infrastructure (terraform destroy)#
To clean up your environment, simply tell Terraform to destroy everything it created. It knows exactly what to delete because it reads the .tfstate file!
terraform destroy -auto-approveExpected Terminal Output:
local_file.my_first_file: Refreshing state... [id=a1b2c3d4e5f6g7h8i9j0]
local_file.my_first_file: Destroying... [id=a1b2c3d4e5f6g7h8i9j0]
local_file.my_first_file: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.The hello-world.txt file has been cleanly removed from your system.
Troubleshooting & Common Errors#
Provider "registry.terraform.io/hashicorp/local" not found- Root Cause: You attempted to run
terraform planorapplywithout runningterraform initfirst. - Solution: Always run
terraform initin a new directory or when adding a new provider.
- Root Cause: You attempted to run
Error: Missing required argument- Root Cause: In your
main.tf, you forgot a required parameter (e.g., you wrote thelocal_fileblock but forgot to include thefilenameargument). - Solution: Check the official Terraform Registry documentation for the specific resource to see which arguments are marked as
(Required).
- Root Cause: In your
State File Locking Errors (
Error acquiring the state lock)- Root Cause: Another process (or teammate) is currently running
terraform applyon the same state file, and Terraform has locked the file to prevent corruption. - Solution: Wait for the other process to finish. If you are 100% sure no one else is running Terraform, you can force-unlock it (Advanced topic covered in later episodes).
- Root Cause: Another process (or teammate) is currently running
Conclusion & Next Steps#
You have successfully written HCL, initialized a provider, generated an execution plan, and deployed your very first declarative resource. You also verified the existence of the critical .tfstate file.
However, creating local text files is not why you learn Terraform. In Episode 2: Providers, Plugins, and Secure Authentication, we will connect Terraform to a real cloud provider (AWS) and learn how to authenticate securely without leaking your secret access keys to GitHub!

