# Packer Configuration to Build Windows Templates

Before moving forward if you're unfamiliar with Packer I recommend reading <https://packer.io/docs/> for the basics. Furthermore there is a ton of great articles (I added a few below) on how to use Packer to build windows templates.

### Packer Windows tutorials

{% embed url="<https://blog.ipswitch.com/create-windows-machine-builds-with-packer>" %}

{% embed url="<https://hodgkins.io/best-practices-with-packer-and-windows>" %}

### My Packer Configuration

1. I use VMWare Workstation/Fusion
2. I use Packer version 1.2.3. I have tried newer versions of Packer and unfortunately I get inconsistent results when using the windows update functionality and therefore prevents me from building the template.
3. I use <https://github.com/rgl/packer-provisioner-windows-update> to perform windows updating during the Packer build process.&#x20;
4. RTM ISO's but Trial Edition ISO's work as well.
5. Winrm for the Packer communication with the Administrator user and custom password.
6. Install latest version of VMWare tools.
7. Enable CredSSP.
8. Install PowerShell version 5.x
9. Perform sysprep and shutdown the box
10. vSphere post-processor to upload templates to vCenter.&#x20;

### More on the Administrator account requirement

I use the Administrator account simply because it's native to the OS and I want to keep my templates clean.&#x20;

### More on the CredSSP requirement.

Once you start building lab environments around Active Directory you will quickly notice that vagrant can only login with the local user which in my case is the Administrator account.  What happens when you need to perform an action as another user such as the Domain Administrator ? This is where CredSSP comes in. When trying to automate installing Exchange, RDS, etc, you can use CredSSP with winrm to authenticate to the localhost as the Domain Administrator and perform the specific domain related actions. This will be further explained with examples in the Vagrant section.

### More on the PowerShell version requirement

By installing the same version of PowerShell it is a  guarantee that all PowerShell commands will work and therefore I don't need to create specific PowerShell scripts for different versions. Furthermore, this allows me to enable security controls such as PSLogging.

{% hint style="warning" %}

### More on the sysprep requirement

Sysprep removes specific identifying elements such as the UUID from the initial template and forces the windows OS to generate a new one upon boot. This ultimately allows us to clone a Windows VM multiple times and each one will have a different UUID therefore making it unique. This is incredibly important as you build Active Directory environments because boxes with the same UUID can not join a domain.
{% endhint %}

## Getting Started

I have created a github repo with sample configurations. You will need to make adjustments to fit your environment.

## Sample Packer Configurations

### Server 2019

The below is a sample Packer configuration for Windows Server 2019 which has PSv5.x installed by default.

```
{
  "variables": {
    "iso_url": "./ISO/en_windows_server_2019_x64.iso",
    "iso_checksum_type": "md5",
    "iso_checksum": "37c51cc09182237ae2c30c9d8ce3c41e",
    "autounattend": "./answer_files/2019/Autounattend.xml",
    "sysprep": "./answer_files/2019/Autounattend_sysprep.xml",
    "template_name": "WinSrv2019x64-Template",
    "winrm_username": "{{user `winrm_username`}}",
    "winrm_password":"{{user `winrm_password`}}"
  },
  "builders": [
    {
      "type": "vmware-iso",
      "communicator": "winrm",
      "iso_url": "{{user `iso_url`}}",
      "iso_checksum_type": "{{user `iso_checksum_type`}}",
      "iso_checksum": "{{user `iso_checksum`}}",
      "headless": false,
      "boot_wait": "2m",
      "winrm_username": "Administrator",
      "winrm_password": "Administrator Password",
      "winrm_timeout": "2h",
      "shutdown_timeout": "2h",
      "shutdown_command": "a:\\sysprep.bat",
      "guest_os_type": "windows8srv-64",
      "disk_size": 61440,
      "vnc_port_min": 5900,
      "vnc_port_max": 5980,
      "version": 11,
      "floppy_files": [
        "{{user `autounattend`}}",
        "./scripts/sysprep.bat",
        "./scripts/fixnetwork.ps1",
        "./scripts/Enable-Winrm.ps1"
      ],
      "vmx_data": {
        "RemoteDisplay.vnc.enabled": "false",
        "RemoteDisplay.vnc.port": "5900",
        "memsize": "2048",
        "numvcpus": "2",
        "scsi0.virtualDev": "lsisas1068"
      }
    }
  ],
  "provisioners": [
    {
      "type": "file",
      "source": "{{user `sysprep`}}",
      "destination": "c:/Windows/Temp/Autounattend_sysprep.xml"
    },
    {
      "type": "powershell",
      "elevated_user": "Administrator",
      "elevated_password": "Administrator Password",
      "scripts": [
        "./scripts/Install-VMwareTools.ps1",
        "./scripts/Enable-CredSSP.ps1"
      ]
    },
    {
      "type": "windows-update",
      "filters": [
        "include:$true"
      ]
    },
    {
      "type": "windows-restart"
    }
  ],
  "post-processors": [
    {
      "type": "vsphere",
      "host": "vCenter Host IP of FQDN",
      "username": "User Account",
      "password": "Password",
      "cluster": "vCenter cluster where esxi box is configured",
      "datacenter": "vCenter datacenter",
      "datastore": "Storage datastore",
      "vm_folder": "VM Folder",
      "vm_name": "{{user `template_name`}}",
      "disk_mode": "thin",
      "insecure": "true",
      "vm_network": "VM Network to assign VM"
    }
  ]
}
```

### Server 2012R2

The below is a sample Packer configuration for Windows Server 2012R2 which does not have PSv5.x installed and therefore requires first installing a newer version of .NET and then installing PSv5.x.

```
{
    "variables": {
      "iso_url": "./ISO/en_windows_server_2012_r2_x64_dvd_2707946.iso",
      "iso_checksum_type": "md5",
      "iso_checksum": "0E7C09AAB20DEC3CD7EAB236DAB90E78",
      "autounattend": "./answer_files/2012_r2/Autounattend.xml",
      "sysprep": "./answer_files/2012_r2/Autounattend_sysprep.xml",
      "template_name": "WinSrv2012R2x64-Template",
      "winrm_username": "Administrator",
      "winrm_password": "Administrator Password"
    },
  "builders": [
    {
      "type": "vmware-iso",
      "communicator": "winrm",
      "iso_url": "{{user `iso_url`}}",
      "iso_checksum_type": "{{user `iso_checksum_type`}}",
      "iso_checksum": "{{user `iso_checksum`}}",
      "headless": false,
      "boot_wait": "2m",
      "winrm_username": "{{user `winrm_username`}}",
      "winrm_password": "{{user `winrm_password`}}",
      "winrm_timeout": "2h",
      "shutdown_timeout": "2h",
      "shutdown_command": "a:\\sysprep.bat",
      "guest_os_type": "windows8srv-64",
      "disk_size": 61440,
      "vnc_port_min": 5900,
      "vnc_port_max": 5980,
      "version": 11,
      "floppy_files": [
        "{{user `autounattend`}}",
        "./scripts/sysprep.bat",
        "./scripts/fixnetwork.ps1"
      ],
      "vmx_data": {
        "RemoteDisplay.vnc.enabled": "false",
        "RemoteDisplay.vnc.port": "5900",
        "memsize": "4096",
        "numvcpus": "4",
        "scsi0.virtualDev": "lsisas1068"
      }
    }
  ],
  "provisioners": [
    {
      "type": "file",
      "source": "{{user `sysprep`}}",
      "destination": "c:/Windows/Temp/Autounattend_sysprep.xml"
    },
    {
      "type": "powershell",
      "elevated_user": "{{user `winrm_username`}}",
      "elevated_password": "{{user `winrm_password`}}",
      "scripts": [
        "./scripts/Install-VMwareTools.ps1",
        "./scripts/Enable-CredSSP.ps1"
      ]
    },
    {
      "type": "windows-restart"
    },
    {
      "type": "windows-update",
      "filters": [
        "include:$true"
      ]
    },
    {
      "type": "windows-restart"
    },
    {
      "type": "powershell",
      "elevated_user": "{{user `winrm_username`}}",
      "elevated_password": "{{user `winrm_password`}}",
      "scripts": [
        "./scripts/Install-NetFramework4.7.2.ps1"
      ]
    },
    {
      "type": "windows-restart"
    },
    {
      "type": "powershell",
      "elevated_user": "{{user `winrm_username`}}",
      "elevated_password": "{{user `winrm_password`}}",
      "scripts": [
        "./scripts/Install-WMF51.ps1"
      ]
    },
    {
      "type": "windows-restart"
    },
    {
      "type": "windows-update",
      "filters": [
        "include:$true"
      ]
    }
  ],
  "post-processors": [
    {
      "type": "vsphere",
      "host": "vCenter Host IP of FQDN",
      "username": "User Account",
      "password": "Password",
      "cluster": "vCenter cluster where esxi box is configured",
      "datacenter": "vCenter datacenter",
      "datastore": "Storage datastore",
      "vm_folder": "VM Folder",
      "vm_name": "{{user `template_name`}}",
      "disk_mode": "thin",
      "insecure": "true",
      "vm_network": "VM Network to assign""
    }
  ]
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blog.lkys37en.com/infrastructure-automation/packer-configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
