How to Install Terraform on Windows Server 2012 R2

Terraform is HashiCorp’s infrastructure-as-code tool that enables you to define, provision, and manage cloud and on-premises infrastructure using declarative configuration files. On Windows Server 2012 R2, Terraform runs as a standalone binary with no installation wizard or service required — you simply extract the executable and add it to the PATH. This guide walks through installing Terraform, configuring it for common use cases (Azure and VMware provisioning), writing your first Terraform configuration, and establishing a workflow for managing infrastructure state files in a team environment.

Prerequisites

  • Windows Server 2012 R2 with PowerShell 4.0
  • Administrator access to modify system PATH
  • Outbound internet access to download providers, or a Terraform provider mirror configured for air-gapped environments
  • An Azure subscription or other target cloud/virtualization platform (for applying configurations)
  • At least 2 GB of available disk space for the binary and provider caches

Step 1: Download the Terraform Binary

Terraform is distributed as a single zip file containing the binary. Download the Windows AMD64 version from HashiCorp’s release repository. Always use a specific version number in production environments rather than relying on “latest” to ensure reproducibility:

$TerraformVersion = "1.8.5"
$DownloadUrl = "https://releases.hashicorp.com/terraform/$TerraformVersion/terraform_${TerraformVersion}_windows_amd64.zip"
$OutFile = "C:Tempterraform.zip"

New-Item -ItemType Directory -Path "C:Temp" -Force
Invoke-WebRequest -Uri $DownloadUrl -OutFile $OutFile

Step 2: Extract and Install the Binary

Create a directory for Terraform and extract the binary. Using a version-specific directory makes it easy to maintain multiple versions side by side:

New-Item -ItemType Directory -Path "C:ToolsTerraform$TerraformVersion" -Force

Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($OutFile, "C:ToolsTerraform$TerraformVersion")

Verify the binary is present:

Get-Item "C:ToolsTerraform$TerraformVersionterraform.exe"

Step 3: Add Terraform to the System PATH

Add the Terraform directory to the system PATH so the binary is accessible from any terminal or script:

$TerraformPath = "C:ToolsTerraform$TerraformVersion"
$CurrentPath = [System.Environment]::GetEnvironmentVariable("Path","Machine")

if ($CurrentPath -notlike "*$TerraformPath*") {
    [System.Environment]::SetEnvironmentVariable("Path","$CurrentPath;$TerraformPath","Machine")
    Write-Host "Terraform added to system PATH"
} else {
    Write-Host "Terraform already in PATH"
}

Open a new PowerShell window and verify:

terraform version

Expected output:

Terraform v1.8.5
on windows_amd64

Step 4: Configure Terraform Plugin Cache Directory

By default, Terraform downloads providers to a .terraform directory inside each project directory. This results in duplicate downloads across projects. Configure a shared plugin cache directory to save bandwidth and disk space:

New-Item -ItemType Directory -Path "C:ToolsTerraformplugin-cache" -Force

# Create or update the Terraform CLI configuration file
$TfConfig = @"
plugin_cache_dir = "C:/Tools/Terraform/plugin-cache"
disable_checkpoint = true
"@

$TfConfigPath = "$env:APPDATAterraform.rc"
Set-Content -Path $TfConfigPath -Value $TfConfig
Write-Host "Terraform CLI config written to $TfConfigPath"

Step 5: Configure Environment for Azure Provider

For managing Azure infrastructure, configure the Azure service principal credentials as environment variables. These credentials are created in Azure Active Directory and grant Terraform permissions to create and manage resources in your subscription:

# Set per-session (for testing)
$env:ARM_CLIENT_ID     = "your-service-principal-app-id"
$env:ARM_CLIENT_SECRET = "your-service-principal-secret"
$env:ARM_TENANT_ID     = "your-azure-tenant-id"
$env:ARM_SUBSCRIPTION_ID = "your-azure-subscription-id"

# Set machine-wide for service account use
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID","your-sp-app-id","Machine")
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET","your-sp-secret","Machine")
[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID","your-tenant-id","Machine")
[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID","your-subscription-id","Machine")

Step 6: Write Your First Terraform Configuration

Create a project directory and write a configuration file to provision an Azure Resource Group and Storage Account:

New-Item -ItemType Directory -Path "C:TerraformProjectsazure-baseline" -Force
Set-Location "C:TerraformProjectsazure-baseline"

Create main.tf:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.100"
    }
  }
  required_version = ">= 1.5.0"
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "baseline" {
  name     = "rg-ws2012r2-baseline"
  location = "East US"

  tags = {
    Environment = "Production"
    ManagedBy   = "Terraform"
    Server      = "WS2012R2"
  }
}

resource "azurerm_storage_account" "tfstate" {
  name                     = "tfstateaccountuniquestr"
  resource_group_name      = azurerm_resource_group.baseline.name
  location                 = azurerm_resource_group.baseline.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  tags = azurerm_resource_group.baseline.tags
}

output "resource_group_id" {
  value = azurerm_resource_group.baseline.id
}

output "storage_account_name" {
  value = azurerm_storage_account.tfstate.name
}

Step 7: Initialize, Plan, and Apply

Initialize the working directory to download the required providers:

terraform init

Review what changes Terraform will make before applying them:

terraform plan -out=tfplan.out

Review the plan output carefully. When satisfied, apply the configuration:

terraform apply tfplan.out

To destroy the resources when they are no longer needed:

terraform destroy -auto-approve

Step 8: Configure Remote State Storage

For team environments, state files must be stored remotely so that multiple team members and CI/CD pipelines share the same state. Configure an Azure Blob Storage backend:

terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state"
    storage_account_name = "tfstateaccountuniquestr"
    container_name       = "tfstate"
    key                  = "ws2012r2-baseline.terraform.tfstate"
  }
}

Run terraform init again to migrate state to the remote backend. Terraform will prompt you to confirm the migration of any existing local state.

Step 9: Integrate Terraform with PowerShell Automation

Wrap Terraform commands in PowerShell for consistent execution in CI/CD pipelines:

function Invoke-TerraformDeploy {
    param(
        [string]$WorkingDir,
        [string]$VarFile = "terraform.tfvars",
        [switch]$AutoApprove
    )

    Push-Location $WorkingDir
    try {
        Write-Host "Initializing Terraform..."
        terraform init -input=false
        if ($LASTEXITCODE -ne 0) { throw "terraform init failed" }

        Write-Host "Planning deployment..."
        terraform plan -var-file=$VarFile -out=tfplan.out -input=false
        if ($LASTEXITCODE -ne 0) { throw "terraform plan failed" }

        if ($AutoApprove) {
            Write-Host "Applying changes..."
            terraform apply -input=false tfplan.out
            if ($LASTEXITCODE -ne 0) { throw "terraform apply failed" }
        } else {
            Write-Host "Plan complete. Review tfplan.out and run 'terraform apply tfplan.out' to proceed."
        }
    } finally {
        Pop-Location
    }
}

# Example usage:
# Invoke-TerraformDeploy -WorkingDir "C:TerraformProjectsazure-baseline" -AutoApprove

Step 10: Verify Installation and State

terraform version
terraform show
terraform state list

Summary

Terraform is now installed and operational on Windows Server 2012 R2. The installation required no agent, no service, and no special prerequisites beyond extracting the binary and setting the PATH. You have configured a shared plugin cache, set up Azure credentials via environment variables, written a Terraform configuration to manage Azure resources, initialized and applied the configuration, and configured remote state storage for team use. Terraform on WS2012 R2 provides the same full infrastructure-as-code capabilities as on any other platform, enabling you to manage Azure, VMware, and other infrastructure providers from a familiar Windows Server environment.