Skip to content 99% OFF 🎉 Anniversary Sale 99% OFF Shared Hosting Use Code HURRYUP Claim Offer 99% OFF Hosting
99% OFF Hosting — Code HURRYUP
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting cPanel Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Call +91 75795 45488
Login
Hosting Panel — cPanel & Billing Console Panel — VPS Management
ALL SYSTEMS OPERATIONAL
VPS

Provisioning VPS Servers with Terraform: A Beginner's Guide

Getwebup 6 min read

If you've ever spun up a VPS by clicking through a dashboard, named it something like "test-server-2," and then forgotten exactly what you configured on it six months later, Terraform solves that problem. It turns your infrastructure into a text file you can read, review, version, and re-run — so "how was this server set up?" has an actual answer.

What Terraform Actually Does

Terraform is an infrastructure-as-code (IaC) tool from HashiCorp. You describe the resources you want — a VPS instance, a firewall rule, a DNS record — in .tf files using a declarative language called HCL. Terraform compares that description to what actually exists (its "state") and figures out the exact API calls needed to close the gap. Run terraform apply again next month and it won't recreate anything that already matches your code — it only changes what drifted.

This is different from a shell script that runs commands top to bottom. Terraform is idempotent: apply the same configuration ten times and you get the same result, not ten servers.

Before You Start

  • A Terraform install (0.13+ syntax works almost everywhere; use a recent 1.x release if you can).
  • An API token from your VPS provider — most providers with an API (DigitalOcean, Hetzner, Vultr, Linode, and others) have an official or community Terraform provider on the Terraform Registry.
  • An SSH key already uploaded to your provider account, so Terraform can inject it into the new instance instead of leaving it with a random root password.
  • A place to store state that isn't your laptop — more on that below.

If your host doesn't publish a Terraform provider, you're not stuck. You can still manage the pieces that do have one — DNS records, firewalls, load balancers — with Terraform, and hand the OS-level setup to a configuration tool. We cover that combination further down.

Step 1: Install and Initialize

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
terraform -version

Create a project directory and a main.tf file inside it. Everything below lives in that one file to start — you can split it up once the project grows.

Step 2: Declare Your Provider

terraform {
  required_providers {
    example = {
      source  = "example-provider/example"
      version = "~> 2.0"
    }
  }
}

provider "example" {
  token = var.api_token
}

variable "api_token" {
  type      = string
  sensitive = true
}

Never hardcode the token into main.tf. Pass it via an environment variable (TF_VAR_api_token) or a .tfvars file that's in your .gitignore. This is the single most common way people leak API keys into a public repo — the token sits in plain text in a committed file, gets picked up by a scraper, and someone else is billing infrastructure to your account within hours.

Step 3: Define the VPS Resource

resource "example_droplet" "web" {
  name     = "prod-web-01"
  region   = "blr1"
  size     = "s-2vcpu-4gb"
  image    = "ubuntu-24-04-x64"
  ssh_keys = [var.ssh_key_id]

  tags = ["production", "web"]
}

output "web_ip" {
  value = example_droplet.web.ipv4_address
}

Swap the resource name and arguments for whatever your provider's Terraform docs specify — every provider names its fields slightly differently, but the shape is always: name it, size it, image it, hand it your SSH key.

Step 4: Plan, Then Apply

terraform init
terraform plan
terraform apply

init downloads the provider plugin. plan is the important habit to build — it shows you exactly what will be created, changed, or destroyed before anything happens. Read it every time, especially after editing an existing resource. A plan that shows "1 to destroy" on a resource you only meant to tweak is Terraform telling you that change requires recreating the box (a renamed disk size on some providers does this) — better to catch that in the plan output than after your production server vanishes.

apply asks for confirmation and then does the work. Terraform prints the new server's IP from your output block when it's done.

Step 5: Get State Off Your Laptop

Terraform tracks what it created in a terraform.tfstate file. If that file lives only on your machine and you reinstall your laptop, Terraform loses track of every resource it manages — it'll try to create everything again from scratch, or worse, believe nothing exists when it does.

For anything beyond a single-person test project, use a remote backend:

terraform {
  backend "s3" {
    bucket = "yourco-tfstate"
    key    = "vps/terraform.tfstate"
    region = "ap-south-1"
  }
}

Any S3-compatible object storage works, including buckets on most VPS providers' own storage products. Remote state also enables locking, so two people (or two CI runs) can't apply changes at the same time and corrupt the state file.

Common Errors and Fixes

ErrorCauseFix
Error acquiring the state lockA previous apply was killed mid-run and never released the lockConfirm no other process is really running, then terraform force-unlock <lock-id>
Resource already exists / 409 ConflictThe server was created outside Terraform (dashboard click) but Terraform doesn't know about itterraform import example_droplet.web <resource-id> to bring it under management
Provider produced inconsistent result after applyProvider bug, or a field changed asynchronously after creationRe-run terraform apply; if it repeats, pin an older provider version
Plan shows changes you didn't makeSomeone edited the resource by hand in the dashboard — "drift"Decide whether to terraform apply to revert it, or run terraform apply -refresh-only and update your code to match reality

Terraform + Ansible: Two Different Jobs

Terraform's job ends once the VPS exists with an IP address and SSH access. It doesn't know or care what's installed on it. That's where a configuration tool like Ansible takes over — installing packages, hardening SSH, setting up your firewall rules, deploying your app. If you haven't set that half up yet, our Ansible playbook guide picks up exactly where this one leaves off.

A common pattern: Terraform's output block writes the new server's IP straight into an Ansible inventory file, so terraform apply followed by ansible-playbook takes you from nothing to a fully configured, running server in two commands.

Best Practices That Save You Later

  • Commit your .tf files, never your state file or tfvars with secrets. Add *.tfstate* and *.tfvars to .gitignore from day one.
  • Use variables for anything that changes between environments — region, size, instance count — instead of copy-pasting a whole file for staging vs. production.
  • Run terraform plan in CI on every pull request so reviewers see the actual infrastructure diff, not just the code diff.
  • Pin provider versions (~> 2.0, not blank) so an upstream provider update doesn't silently change behavior under you.
  • Tag every resource with an owner or project name. It's the difference between knowing what a mystery server is for and having to guess before you dare delete it.

None of this replaces good judgment — Terraform will happily destroy a production database if your code says to. The plan output is your safety net; read it before you type "yes."

Frequently asked questions

Do I need Terraform if I only manage one VPS?

Not strictly, but it still pays off. Even for a single server, Terraform gives you a readable record of exactly how it was configured and a repeatable way to rebuild it if you ever need to migrate providers or recover from a lost instance.

What happens if I delete a resource from my .tf file?

On your next terraform apply, Terraform will destroy the matching real-world resource to match your code. Always run terraform plan first so you can see "to be destroyed" before it happens, not after.

Can I use Terraform if my VPS provider doesn't have an official provider on the registry?

Check the Terraform Registry for a community-maintained provider first — many popular hosts have one even without an official HashiCorp partnership. If none exists, you can still manage supporting resources like DNS or object storage with Terraform and handle the VPS itself through your provider's API or a tool like Ansible.

Where should I store my terraform.tfstate file for a small team?

Use a remote backend such as S3-compatible object storage with locking enabled, rather than keeping state on one person's laptop or committing it to git. State files often contain sensitive data in plain text, so treat access to the backend like you would a production credential.

#terraform #vps #infrastructure-as-code #devops #provisioning #iac

Keep reading

Chat with Support