HCL: providers, resources & references
The core building blocks of a config.
You write Terraform in HCL (HashiCorp Configuration Language) — a readable, declarative language purpose-built for describing resources. Three concepts are the whole foundation: providers (plugins that talk to a platform’s API), resources (the things you want to exist), and the .tf files that declare them. Get these three and you can read most Terraform in the wild.
terraform {required_providers {aws = { source = "hashicorp/aws", version = "~> 5.0" } # which provider, pinned}}provider "aws" {region = "us-east-1" # configure the provider}resource "aws_instance" "web" { # resource TYPE "local name"ami = "ami-0abc123"instance_type = "t3.micro"tags = { Name = "web-server" }}
Providers: plugins for platforms
A provider is a plugin that knows how to talk to one platform’s API — AWS, Azure, Google Cloud, Kubernetes, GitHub, and hundreds more. You declare which providers you need and pin their versions, Terraform downloads them on terraform init, and each provider exposes a set of resource types you can then declare. The provider is what makes Terraform universal: the same workflow manages anything with a provider.
Resources, arguments & references
A resource block declares one thing that should exist. Inside, arguments set its properties. The powerful part is that resources reference each other’s attributes — aws_security_group.web_sg.id — and from those references Terraform builds a dependency graph and creates things in the correct order automatically. You describe the resources and how they relate; Terraform works out the order of operations.
resource "aws_security_group" "web_sg" {name = "web-sg"ingress { from_port = 443, to_port = 443, protocol = "tcp", cidr_blocks = ["0.0.0.0/0"] }}resource "aws_instance" "web" {ami = "ami-0abc123"instance_type = "t3.micro"vpc_security_group_ids = [aws_security_group.web_sg.id] # reference → SG created first}