Terraform (and its open-source fork OpenTofu) lets you describe servers, networks and DNS records in code, then creates and updates them through each platform's API. This guide covers the Terraform basics you need to provision VMs reproducibly instead of clicking through panels.
Before you start
- An account on a platform with a Terraform provider: most clouds, Proxmox VE (community providers), libvirt, and many DNS and CDN services.
- An API token with limited permissions.
- Terraform or OpenTofu installed from the official releases.
Core concepts
| Term | Meaning |
|---|---|
| Provider | Plugin that talks to a platform's API |
| Resource | Something to create: a VM, disk, firewall, DNS record |
| Variable / output | Inputs and returned values |
| State | Terraform's record of what it created, mapping code to real objects |
| Module | Reusable group of resources |
A minimal configuration
The structure is the same for every provider; resource names and arguments differ, so check the provider's documentation. A generic example:
terraform {
required_providers {
example = {
source = "example/cloud"
}
}
}
variable "api_token" {
type = string
sensitive = true
}
provider "example" {
token = var.api_token
}
resource "example_server" "web" {
name = "web01"
image = "ubuntu-24.04"
size = "small"
region = "de"
user_data = file("cloud-init.yaml")
}
output "web_ip" {
value = example_server.web.ipv4_address
}The user_data file bootstraps the VM; see cloud-init user-data.
The workflow
terraform initterraform plan -out tfplanterraform apply tfplaninit downloads providers, plan shows exactly what will be created, changed or destroyed, and apply executes it. To remove everything: terraform destroy.
Pass secrets safely
Provide tokens through environment variables (TF_VAR_api_token) or a secrets manager, never in committed files. Add *.tfvars containing secrets and .terraform/ to .gitignore.
Protect your state
- State can contain IPs, passwords and keys. Do not commit
terraform.tfstateto Git. - For teams, use a remote backend with locking (for example an S3-compatible bucket; see object storage).
- Never edit state by hand; use
terraform statecommands.
Terraform and Ansible together
Terraform creates the VM and DNS records; Ansible configures software inside. See Ansible for VPS configuration.
Troubleshooting
- Plan wants to replace a server: you changed an argument that forces recreation (such as image). Read the plan carefully.
- State lock errors: another run is in progress, or a crashed run left a lock; release it only when sure.
- Resource exists outside Terraform: bring it in with
terraform importor an import block.
Frequently asked questions
Terraform or OpenTofu?
OpenTofu is an open-source fork compatible with most Terraform configurations. Choose based on licensing preferences and provider support.
Can Terraform manage Proxmox?
Yes, through community providers that use the Proxmox API.
Does Terraform install software?
Not really; use cloud-init or a configuration tool for that.
