Don't memorize syntax. Understand the flow. For syntax, always check the official docs. Terraform docs: https://registry.terraform.io/providers/hashicorp/aws/latest/docs
When I started, I put everything in one big file. It worked but it was a mess. The right way is to make a folder and split everything into separate files based on what they do.
Terraform doesn't care how many files you have. When you run terraform apply, it reads ALL the .tf files in the folder together automatically. So splitting them is just for your own sanity.
Here is the folder structure I follow:
terraform-ec2/
├── provider.tf # tells Terraform which cloud (AWS) and which region
├── variables.tf # all the values I might want to change later
├── vpc.tf # the network my EC2 will live inside
├── subnet.tf # smaller section inside the VPC where EC2 actually sits
├── networking.tf # internet gateway + route table so EC2 can reach internet
├── security_group.tf # firewall rules — who can talk to my EC2
├── key_pair.tf # SSH key so I can log into EC2
├── ec2.tf # the actual server — brings everything together
└── outputs.tf # prints useful info after apply (like the public IP)
Each file has one job. If someone asks you "where is the firewall stuff?" — you say security_group.tf. Clean and simple.
The first thing Terraform needs to know is — which cloud are we working with? I put this in provider.tf.
provider "aws" {
region = var.region
}
Nothing gets created here. This just says: "hey Terraform, go talk to AWS, specifically in this region."
Instead of hardcoding values like "ap-south-1" or "t2.micro" everywhere, I put them all in one place. Then I reference them anywhere using var.variable_name.
variable "region" {
default = "ap-south-1"
}
variable "instance_type" {
default = "t2.micro"
}
variable "ami_id" {
default = "ami-0f5ee92e2d63afc18"
}
If I ever want to change the region, I change it in one place — not in 5 different files.