Command Palette

Search for a command to run...

GitHubGitHub

Terraform Installation Guide

Install Terraform 1.16 from the official HashiCorp repositories, configure providers and backends, write your first stack and keep state safe with locking.

Terraform is HashiCorp's Infrastructure as Code (IaC) tool. You describe your infrastructure in configuration files, and Terraform plans the changes and applies them against cloud and on-prem providers.

System Requirements

  • A 64-bit operating system (Linux, macOS, FreeBSD, Windows, or a supported container)
  • Terraform runs as a single static binary — there is no runtime dependency
  • 2 GB RAM is plenty for all but the largest state files
  • Network access to releases.hashicorp.com and registry.terraform.io

Installation Instructions

Ubuntu / Debian (apt)

# Add the HashiCorp signing key
wget -O - https://apt.releases.hashicorp.com/gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
 
# Add the repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/hashicorp.list
 
# Install
sudo apt update
sudo apt install -y terraform
 
# Verify
terraform version

Verifying the Installation

# Version and platform
terraform version
 
# Enable shell completion
terraform -install-autocomplete
source ~/.bashrc
 
# Confirm the provider registry is reachable
terraform init

Your First Stack

Create main.tf in an empty directory:

terraform {
  required_version = ">= 1.16.0"
 
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}
 
provider "aws" {
  region = var.region
}
 
resource "aws_s3_bucket" "example" {
  bucket_prefix = "example-"
}
 
variable "region" {
  type    = string
  default = "eu-central-1"
}
# Download the providers and the backend configuration
terraform init
 
# See what would change — always run this first
terraform plan
 
# Apply the changes
terraform apply
 
# Inspect the state
terraform show
terraform state list

Locking Provider Versions

Commit the lock file so every machine and every CI job uses exactly the same provider builds:

# Generate the lock file for all the platforms you use
terraform providers lock -platform=linux_amd64 -platform=darwin_arm64 -platform=darwin_amd64
 
# Commit .terraform.lock.hcl to version control

State Management

State is the record of what Terraform manages. It usually belongs in a remote backend with locking enabled.

terraform {
  backend "s3" {
    bucket       = "my-terraform-state"
    key          = "prod/terraform.tfstate"
    region       = "eu-central-1"
    dynamodb_table = "terraform-locks"
    encrypt      = true
  }
}
# Switch to the remote backend
terraform init -migrate-state
 
# A stuck lock has to be released by hand — use with care
terraform force-unlock <LOCK_ID>

Testing Your Configuration

Terraform has a native test framework — no extra tooling required:

# tests/setup.tftest.hcl
variables {
  bucket_prefix = "test-"
}
 
run "validate_bucket_name" {
  command = plan
 
  assert {
    condition     = length(aws_s3_bucket.example.bucket) > 0
    error_message = "The bucket name must not be empty"
  }
}
# Run the tests
terraform test

Importing Existing Infrastructure

Terraform 1.5 and newer can generate configuration for resources you already have:

# Generate configuration for an existing resource
terraform plan -generate-config-out=generated.tf
 
# Or define the import block by hand
import {
  to = aws_s3_bucket.example
  id = "my-existing-bucket"
}
terraform plan  # shows the import
terraform apply

Upgrading

# Check for a newer version
terraform version
 
# Upgrade the binary
sudo apt update && sudo apt install --only-upgrade terraform
 
# Upgrade the providers and re-pin them
terraform init -upgrade
terraform providers lock -platform=linux_amd64
 
# Review the change before applying
terraform plan

Troubleshooting

Best Practices

  1. Always run terraform plan before apply — and review the diff, do not pipe it into apply in CI.
  2. Commit .terraform.lock.hcl so every run uses the same provider builds.
  3. Keep state remote, encrypted and versioned, and enable locking.
  4. Never commit *.tfstate or *.tfvars to Git — use a secret manager for variables.
  5. Use modules for anything you build twice, and pin module versions.
  6. Write tests with terraform test for every module.
  7. Tag every resource consistently so you can find and clean up resources later.
  8. Use import blocks to bring existing infrastructure under management instead of rebuilding it.
  9. Pin the CLI version in CI so a new release never changes your pipeline's behaviour.
  10. Use the check block for assertions on data sources and outputs.

Next Steps