Terraform Basics: Providers, State, and Plan
Start with Terraform by wiring a provider, declaring resources, and learning how plan plus state turn infrastructure changes into a safe diff.
Netbay Engineering
Netbay Engineering
Terraform is the tool teams reach for when they want to treat infrastructure itself as code that can be reviewed, diffed, and rolled back, rather than the result of a string of API clicks. It is declarative: you write the end state, and Terraform figures out the steps to reach it. This post walks the three core pieces — providers, state, and the plan command — using a cloud server as the running example.
Providers: The Bridge to an API
A provider is the plugin that translates Terraform's generic resource vocabulary into calls against a real API. Each cloud provider ships one, and you declare which you need and roughly which version:
terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.40"
}
}
}
resource "hcloud_ssh_key" "deploy" {
name = "deploy key"
public_key = file("~/.ssh/id_ed25519.pub")
}
resource "hcloud_server" "web" {
name = "web01"
server_type = "cx21"
image = "ubuntu-24.04"
location = "fsn1"
ssh_keys = [hcloud_ssh_key.deploy.id]
}Two things stand out. First, resources reference each other by symbolic name — the server pulls the ssh key's id via hcloud_ssh_key.deploy.id — so Terraform can order creation automatically. Second, everything is data plus references; there is no step-by-step procedure here, only the shape of the world you want. Before the first resource exists you will also need API credentials in environment variables, which the provider documentation spells out.
State: Terraform's Memory
After you apply for the first time, Terraform writes a state file recording what actually exists and its resource IDs. That file is the bridge between your code and reality: plan compares the configuration against state, not against a fresh API query. This is why deleting the state file is effectively forgetting you own infrastructure — the running resources still bill you while Terraform thinks they never existed. Treat state as precious data, and keep it out of git, a topic covered fully in the next post.
Plan and Apply
The workflow is deliberately small and safe:
terraform init
terraform plan -out plan.tfplan
terraform apply plan.tfplan
terraform show plan.tfplaninit downloads the provider plugin; plan computes a diff between configuration and state and writes it to a file; apply executes exactly that diff; show renders the recorded diff for later review. The plan shows, in plain text, what will be created, changed, or destroyed, with a count at the end — the reviewable artifact that lets a colleague approve an infrastructure change the way they would approve a code change. If the plan surprises you, destroy nothing: just run terraform plan again after fixing the configuration, which is exactly how you experiment without breaking anything.
Takeaway
Learn the trio as a unit: provider declares the API, state remembers reality, plan makes change reviewable. Everything else — workspaces, modules, backends — builds on these three, and most problems beginners hit trace back to one of them. To get real API responses into your practice session, pair this with a provider you can afford to create and destroy repeatedly; for plain VPS territory, Netbay's own API and dashboard on netbayhosts.in let you keep a scratch instance alive for exactly that kind of experimenting.
Keep reading
Follow along on a real VPS
Deploy Linux in under 60 seconds
These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.
Deploy an instance