home / skills / hashicorp / agent-skills / windows-builder

windows-builder skill

/packer/builders/skills/windows-builder

This skill guides building Windows images with Packer using WinRM and PowerShell to streamline AMIs, Azure images, and VMware templates.

npx playbooks add skill hashicorp/agent-skills --skill windows-builder

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.5 KB
---
name: windows-builder
description: Build Windows images with Packer using WinRM communicator and PowerShell provisioners. Use when creating Windows AMIs, Azure images, or VMware templates.
---

# Windows Builder

Platform-agnostic patterns for building Windows images with Packer.

**Reference:** [Windows Builders](https://developer.hashicorp.com/packer/guides/windows)

> **Note:** Windows builds incur significant costs and time. Expect 45-120 minutes per build due to Windows Updates. Failed builds may leave resources running - always verify cleanup.

## WinRM Communicator Setup

Windows requires WinRM for Packer communication.

### AWS Example

```hcl
source "amazon-ebs" "windows" {
  region        = "us-west-2"
  instance_type = "t3.medium"

  source_ami_filter {
    filters = {
      name = "Windows_Server-2022-English-Full-Base-*"
    }
    most_recent = true
    owners      = ["amazon"]
  }

  ami_name = "windows-server-2022-${local.timestamp}"

  communicator   = "winrm"
  winrm_username = "Administrator"
  winrm_use_ssl  = true
  winrm_insecure = true
  winrm_timeout  = "15m"

  user_data_file = "scripts/setup-winrm.ps1"
}
```

### WinRM Setup Script (scripts/setup-winrm.ps1)

```powershell
<powershell>
# Configure WinRM
winrm quickconfig -q
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'

# Configure firewall
netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow
netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow

# Restart WinRM
net stop winrm
net start winrm
</powershell>
```

### Azure Example

```hcl
source "azure-arm" "windows" {
  client_id       = var.client_id
  client_secret   = var.client_secret
  subscription_id = var.subscription_id
  tenant_id       = var.tenant_id

  managed_image_resource_group_name = "images-rg"
  managed_image_name                = "windows-${local.timestamp}"

  os_type         = "Windows"
  image_publisher = "MicrosoftWindowsServer"
  image_offer     = "WindowsServer"
  image_sku       = "2022-datacenter-g2"

  location = "East US"
  vm_size  = "Standard_D2s_v3"

  # Azure auto-configures WinRM
  communicator   = "winrm"
  winrm_use_ssl  = true
  winrm_insecure = true
  winrm_timeout  = "15m"
  winrm_username = "packer"
}
```

## PowerShell Provisioners

### Install Software

```hcl
build {
  sources = ["source.amazon-ebs.windows"]

  # Install Chocolatey
  provisioner "powershell" {
    inline = [
      "Set-ExecutionPolicy Bypass -Scope Process -Force",
      "iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"
    ]
  }

  # Install applications
  provisioner "powershell" {
    inline = [
      "choco install -y googlechrome",
      "choco install -y 7zip",
    ]
  }

  # Install IIS
  provisioner "powershell" {
    inline = [
      "Install-WindowsFeature -Name Web-Server -IncludeManagementTools"
    ]
  }
}
```

### Windows Updates

```hcl
provisioner "powershell" {
  inline = [
    "Install-PackageProvider -Name NuGet -Force",
    "Install-Module -Name PSWindowsUpdate -Force",
    "Import-Module PSWindowsUpdate",
    "Get-WindowsUpdate -Install -AcceptAll -AutoReboot",
  ]
  timeout = "2h"
}

# Wait for reboots
provisioner "windows-restart" {
  restart_timeout = "30m"
}
```

## Cleanup

```hcl
provisioner "powershell" {
  inline = [
    "# Clear temp files",
    "Remove-Item -Path 'C:\\Windows\\Temp\\*' -Recurse -Force -ErrorAction SilentlyContinue",
    "# Clear Windows Update cache",
    "Stop-Service -Name wuauserv -Force",
    "Remove-Item -Path 'C:\\Windows\\SoftwareDistribution\\*' -Recurse -Force -ErrorAction SilentlyContinue",
    "Start-Service -Name wuauserv",
  ]
}
```

## Common Issues

**WinRM Timeout**
- Increase `winrm_timeout` to 15m or more
- Verify security group allows ports 5985/5986
- Check user data script completed successfully

**PowerShell Execution Policy**
```hcl
provisioner "powershell" {
  inline = [
    "Set-ExecutionPolicy Bypass -Scope Process -Force",
    "# Your commands here",
  ]
}
```

**Long Build Times**
- Windows Updates can take 1-2 hours
- Use pre-patched base images when available
- Set provisioner `timeout = "2h"`

## References

- [Packer Windows Builders](https://developer.hashicorp.com/packer/guides/windows)
- [WinRM Communicator](https://developer.hashicorp.com/packer/docs/communicators/winrm)
- [PowerShell Provisioner](https://developer.hashicorp.com/packer/docs/provisioners/powershell)

Overview

This skill builds Windows images with Packer using the WinRM communicator and PowerShell provisioners. It provides patterns and examples for AWS, Azure, and generic platforms, including WinRM setup, software installation, Windows Update handling, reboots, and cleanup. Use it to produce AMIs, Azure managed images, or VMware templates with repeatable, automated provisioning.

How this skill works

The skill configures Packer sources to use the WinRM communicator and supplies user-data or provisioning scripts to enable and harden WinRM on the VM. It runs PowerShell provisioners to install Chocolatey, packages, Windows features, and PSWindowsUpdate for patching. Reboots are coordinated with windows-restart and long timeouts to accommodate Windows Update and installer durations.

When to use it

  • Creating Windows AMIs for AWS or Azure managed images
  • Building VMware or other hypervisor templates with automated provisioning
  • Automating software installation and Windows feature configuration in an image
  • When images require full Windows Update runs and reboots before capture
  • Environments that need repeatable, versioned Windows base images

Best practices

  • Enable and test WinRM early via a user-data script and open ports 5985/5986 in security groups or NSGs
  • Use winrm_use_ssl and winrm_insecure when using self-signed certs; increase winrm_timeout to at least 15m
  • Install Chocolatey to manage application installs consistently across builds
  • Run PSWindowsUpdate with long timeouts and include windows-restart to handle reboots reliably
  • Clean temp files and Windows Update caches before image capture to reduce image size and state

Example use cases

  • AWS: amazon-ebs source with WinRM user_data to enable remote provisioning and build an AMI
  • Azure: azure-arm source building a managed image with preinstalled enterprise apps and patches
  • CI pipeline: automated image builds that install monitoring agents, IIS, and baseline tools via Chocolatey
  • VMware template: create a standard VM template with updates and cleanup for vSphere deployments
  • Patch baseline creation: run PSWindowsUpdate, reboot, then capture a patched image for distribution

FAQ

Why do Windows builds take so long?

Windows Update and cumulative installers can run for 45–120 minutes. Allow long provisioner timeouts and consider pre-patched base images to shorten builds.

What causes WinRM timeouts and failures?

Common causes are closed ports (5985/5986), incomplete user-data WinRM setup, or short winrm_timeout. Verify network rules, user-data execution, and increase winrm_timeout to 15m or more.