How to Create Windows Server 2022 Template in vSphere - using Packer

Overview

Packer uses the HashiCorp Configuration Language - HCL - designed to allow concise descriptions of the required steps to get to a build file. This page describes the features of HCL2 exhaustively

HCL Templates reference

File structure i have used:

img placeholder


Below two files are commonly used by all the templates. which will be called using packer tool

img placeholder

1. common.pkrvars.hcl
 1// Virtual Machine Settings
 2common_vm_version           = 19
 3common_tools_upgrade_policy = true
 4common_remove_cdrom         = true
 5
 6// Template and Content Library Settings
 7common_template_conversion         = false
 8common_content_library_name        = "vm_library"
 9common_content_library_ovf         = false
10common_content_library_destroy     = false
11common_content_library_skip_export = false
12
13// Removable Media Settings
14common_iso_datastore = "OS_ISO"
15
16// Boot and Provisioning Settings
17common_data_source       = "http"
18common_http_ip           = null
19common_http_port_min     = 8000
20common_http_port_max     = 8099
21common_ip_wait_timeout   = "20m"
22common_ip_settle_timeout = "5s"
23common_shutdown_timeout  = "15m"
2. vsphere.pkrvars.hcl
 1// vSphere Credentials - replace with your configuration
 2vsphere_endpoint            = "vcsa.cloudbricks.local"
 3vsphere_username            = "Administrator@vsphere.local"
 4vsphere_password            = "SuperSecretPassword"
 5vsphere_insecure_connection = false
 6
 7// vSphere Settings
 8vsphere_datacenter                     = "Lab"
 9//vsphere_cluster                      = "Cluster"
10vsphere_host                           = "esx-base.cloudbricks.local"
11vsphere_datastore                      = "SSD"
12vsphere_network                        = "cloudbricks"
13vsphere_folder                         = "Templates"
14
15vsphere_set_host_for_datastore_uploads = false

Below files are used for Windows Server template

img placeholder


1. variables.pkr.hcl

Contains all input variables to which you assign values. Any explicit values in this file will override the declared default values (these are found in the following file). The auto extension enables Packer to use this file automatically. It does not require you to reference or pass it in the command line explicitly

  1//  Defines the input variables.
  2
  3// vSphere Credentials
  4
  5variable "vsphere_endpoint" {
  6  type        = string
  7  description = "The fully qualified domain name or IP address of the vCenter Server instance."
  8}
  9
 10variable "vsphere_username" {
 11  type        = string
 12  description = "The username to login to the vCenter Server instance."
 13  sensitive   = true
 14}
 15
 16variable "vsphere_password" {
 17  type        = string
 18  description = "The password for the login to the vCenter Server instance."
 19  sensitive   = true
 20}
 21
 22variable "vsphere_insecure_connection" {
 23  type        = bool
 24  description = "Do not validate vCenter Server TLS certificate."
 25}
 26
 27// vSphere Settings
 28
 29variable "vsphere_datacenter" {
 30  type        = string
 31  description = "The name of the target vSphere datacenter."
 32  default     = ""
 33}
 34
 35variable "vsphere_cluster" {
 36  type        = string
 37  description = "The name of the target vSphere cluster."
 38  default     = ""
 39}
 40
 41variable "vsphere_host" {
 42  type        = string
 43  description = "The name of the target ESXi host."
 44  default     = ""
 45}
 46
 47variable "vsphere_datastore" {
 48  type        = string
 49  description = "The name of the target vSphere datastore."
 50}
 51
 52variable "vsphere_network" {
 53  type        = string
 54  description = "The name of the target vSphere network segment."
 55}
 56
 57variable "vsphere_folder" {
 58  type        = string
 59  description = "The name of the target vSphere folder."
 60  default     = ""
 61}
 62
 63variable "vsphere_resource_pool" {
 64  type        = string
 65  description = "The name of the target vSphere resource pool."
 66  default     = ""
 67}
 68
 69variable "vsphere_set_host_for_datastore_uploads" {
 70  type        = bool
 71  description = "Set this to true if packer should use the host for uploading files to the datastore."
 72  default     = false
 73}
 74
 75// Installer Settings
 76
 77variable "vm_inst_os_language" {
 78  type        = string
 79  description = "The installation operating system lanugage."
 80  default     = "en-US"
 81}
 82
 83variable "vm_inst_os_keyboard" {
 84  type        = string
 85  description = "The installation operating system keyboard input."
 86  default     = "en-US"
 87}
 88
 89variable "vm_inst_os_image_standard_core" {
 90  type        = string
 91  description = "The installation operating system image input for Microsoft Windows Standard Core."
 92}
 93
 94variable "vm_inst_os_image_standard_desktop" {
 95  type        = string
 96  description = "The installation operating system image input for Microsoft Windows Standard."
 97}
 98
 99variable "vm_inst_os_kms_key_standard" {
100  type        = string
101  description = "The installation operating system KMS key input for Microsoft Windows Standard edition."
102}
103
104variable "vm_inst_os_image_datacenter_core" {
105  type        = string
106  description = "The installation operating system image input for Microsoft Windows Datacenter Core."
107}
108
109variable "vm_inst_os_image_datacenter_desktop" {
110  type        = string
111  description = "The installation operating system image input for Microsoft Windows Datacenter."
112}
113
114variable "vm_inst_os_kms_key_datacenter" {
115  type        = string
116  description = "The installation operating system KMS key input for Microsoft Windows Datacenter edition."
117}
118
119// Virtual Machine Settings
120
121variable "vm_guest_os_language" {
122  type        = string
123  description = "The guest operating system lanugage."
124  default     = "en-US"
125}
126
127variable "vm_guest_os_keyboard" {
128  type        = string
129  description = "The guest operating system keyboard input."
130  default     = "en-US"
131}
132
133variable "vm_guest_os_timezone" {
134  type        = string
135  description = "The guest operating system timezone."
136  default     = "UTC"
137}
138
139variable "vm_guest_os_family" {
140  type        = string
141  description = "The guest operating system family. Used for naming and VMware Tools."
142}
143
144variable "vm_guest_os_name" {
145  type        = string
146  description = "The guest operating system name. Used for naming."
147}
148
149variable "vm_guest_os_version" {
150  type        = string
151  description = "The guest operating system version. Used for naming."
152}
153
154variable "vm_guest_os_edition_standard" {
155  type        = string
156  description = "The guest operating system edition. Used for naming."
157  default     = "standard"
158}
159
160variable "vm_guest_os_edition_datacenter" {
161  type        = string
162  description = "The guest operating system edition. Used for naming."
163  default     = "datacenter"
164}
165
166variable "vm_guest_os_experience_core" {
167  type        = string
168  description = "The guest operating system minimal experience. Used for naming."
169  default     = "core"
170}
171
172variable "vm_guest_os_experience_desktop" {
173  type        = string
174  description = "The guest operating system desktop experience. Used for naming."
175  default     = "dexp"
176}
177
178variable "vm_guest_os_type" {
179  type        = string
180  description = "The guest operating system type, also know as guestid."
181}
182
183variable "vm_firmware" {
184  type        = string
185  description = "The virtual machine firmware."
186  default     = "efi-secure"
187}
188
189variable "vm_cdrom_type" {
190  type        = string
191  description = "The virtual machine CD-ROM type."
192  default     = "sata"
193}
194
195variable "vm_cpu_count" {
196  type        = number
197  description = "The number of virtual CPUs."
198}
199
200variable "vm_cpu_cores" {
201  type        = number
202  description = "The number of virtual CPUs cores per socket."
203}
204
205variable "vm_cpu_hot_add" {
206  type        = bool
207  description = "Enable hot add CPU."
208}
209
210variable "vm_mem_size" {
211  type        = number
212  description = "The size for the virtual memory in MB."
213}
214
215variable "vm_mem_hot_add" {
216  type        = bool
217  description = "Enable hot add memory."
218}
219
220variable "vm_disk_size" {
221  type        = number
222  description = "The size for the virtual disk in MB."
223}
224
225variable "vm_disk_controller_type" {
226  type        = list(string)
227  description = "The virtual disk controller types in sequence."
228  default     = ["pvscsi"]
229}
230
231variable "vm_disk_thin_provisioned" {
232  type        = bool
233  description = "Thin provision the virtual disk."
234  default     = true
235}
236
237variable "vm_network_card" {
238  type        = string
239  description = "The virtual network card type."
240  default     = "vmxnet3"
241}
242
243variable "common_vm_version" {
244  type        = number
245  description = "The vSphere virtual hardware version."
246}
247
248variable "common_tools_upgrade_policy" {
249  type        = bool
250  description = "Upgrade VMware Tools on reboot."
251  default     = true
252}
253
254variable "common_remove_cdrom" {
255  type        = bool
256  description = "Remove the virtual CD-ROM(s)."
257  default     = true
258}
259
260// Template and Content Library Settings
261
262variable "common_template_conversion" {
263  type        = bool
264  description = "Convert the virtual machine to template. Must be 'false' for content library."
265  default     = false
266}
267
268variable "common_content_library_name" {
269  type        = string
270  description = "The name of the target vSphere content library, if used."
271  default     = null
272}
273
274variable "common_content_library_ovf" {
275  type        = bool
276  description = "Export to content library as an OVF template."
277  default     = true
278}
279
280variable "common_content_library_destroy" {
281  type        = bool
282  description = "Delete the virtual machine after exporting to the content library."
283  default     = true
284}
285
286variable "common_content_library_skip_export" {
287  type        = bool
288  description = "Skip exporting the virtual machine to the content library. Option allows for testing/debugging without saving the machine image."
289  default     = false
290}
291
292// OVF Export Settings
293
294variable "common_ovf_export_enabled" {
295  type        = bool
296  description = "Enable OVF artifact export."
297  default     = false
298}
299
300variable "common_ovf_export_overwrite" {
301  type        = bool
302  description = "Overwrite existing OVF artifact."
303  default     = true
304}
305
306// Removable Media Settings
307
308variable "common_iso_datastore" {
309  type        = string
310  description = "The name of the source vSphere datastore for the guest operating system ISO."
311}
312
313variable "iso_path" {
314  type        = string
315  description = "The path on the source vSphere datastore for the guest operating system ISO."
316}
317
318variable "iso_file" {
319  type        = string
320  description = "The file name of the guest operating system ISO."
321}
322
323// Boot Settings
324
325variable "common_data_source" {
326  type        = string
327  description = "The provisioning data source. One of `http` or `disk`."
328}
329
330variable "common_http_ip" {
331  type        = string
332  description = "Define an IP address on the host to use for the HTTP server."
333  default     = null
334}
335
336variable "common_http_port_min" {
337  type        = number
338  description = "The start of the HTTP port range."
339}
340
341variable "common_http_port_max" {
342  type        = number
343  description = "The end of the HTTP port range."
344}
345
346variable "vm_boot_order" {
347  type        = string
348  description = "The boot order for virtual machines devices."
349  default     = "disk,cdrom"
350}
351
352variable "vm_boot_wait" {
353  type        = string
354  description = "The time to wait before boot."
355}
356
357variable "vm_boot_command" {
358  type        = list(string)
359  description = "The virtual machine boot command."
360  default     = []
361}
362
363variable "vm_shutdown_command" {
364  type        = string
365  description = "Command(s) for guest operating system shutdown."
366}
367
368variable "common_ip_wait_timeout" {
369  type        = string
370  description = "Time to wait for guest operating system IP address response."
371}
372
373variable "common_ip_settle_timeout" {
374  type        = string
375  description = "Time to wait for guest operating system IP to settle down."
376  default     = "5s"
377}
378
379variable "common_shutdown_timeout" {
380  type        = string
381  description = "Time to wait for guest operating system shutdown."
382}
383
384// Communicator Settings and Credentials
385
386
387
388// Communicator Credentials
389
390variable "communicator_port" {
391  type        = string
392  description = "The port for the communicator protocol."
393}
394
395variable "communicator_timeout" {
396  type        = string
397  description = "The timeout for the communicator protocol."
398}
399
400// Provisioner Settings
401
402variable "scripts" {
403  type        = list(string)
404  description = "A list of scripts and their relative paths to transfer and run."
405  default     = []
406}
407
408variable "inline" {
409  type        = list(string)
410  description = "A list of commands to run."
411  default     = []
412}
413
414// HCP Packer Settings
415
416variable "common_hcp_packer_registry_enabled" {
417  type        = bool
418  description = "Enable the HCP Packer registry."
419  default     = false
420}
2. windows-server.pkr.hcl

This file contains the blocks as mentioned in the refernece, from declared variables, build and source blocks. Packer uses this to automate the VM template creation.

  1
  2//  BLOCK: packer
  3//  The Packer configuration.
  4
  5packer {
  6  required_version = ">= 1.9.4"
  7  required_plugins {
  8    vsphere = {
  9      source  = "github.com/hashicorp/vsphere"
 10      version = ">= 1.2.1"
 11    }
 12
 13  }
 14}
 15
 16//  BLOCK: data
 17//  Defines the data sources.
 18
 19//  BLOCK: locals
 20//  Defines the local variables.
 21
 22locals {
 23  iso_paths                  = ["[${var.common_iso_datastore}] ${var.iso_path}/${var.iso_file}",
 24  "[] /vmimages/tools-isoimages/${var.vm_guest_os_family}.iso"]
 25  vm_name                    = "WIN2022"
 26
 27}
 28
 29//  BLOCK: source
 30//  Defines the builder configuration blocks.
 31
 32
 33source "vsphere-iso" "WIN2022_Std" {
 34
 35  // vCenter Server Endpoint Settings and Credentials
 36  vcenter_server      = var.vsphere_endpoint
 37  username            = var.vsphere_username
 38  password            = var.vsphere_password
 39  insecure_connection = var.vsphere_insecure_connection
 40
 41  // vSphere Settings
 42  datacenter                     = var.vsphere_datacenter
 43  cluster                        = var.vsphere_cluster
 44  host                           = var.vsphere_host
 45  datastore                      = var.vsphere_datastore
 46  folder                         = var.vsphere_folder
 47  resource_pool                  = var.vsphere_resource_pool
 48  set_host_for_datastore_uploads = var.vsphere_set_host_for_datastore_uploads
 49
 50  // Virtual Machine Settings
 51  vm_name              = local.vm_name
 52  guest_os_type        = var.vm_guest_os_type
 53  firmware             = var.vm_firmware
 54  CPUs                 = var.vm_cpu_count
 55  cpu_cores            = var.vm_cpu_cores
 56  CPU_hot_plug         = var.vm_cpu_hot_add
 57  RAM                  = var.vm_mem_size
 58  RAM_hot_plug         = var.vm_mem_hot_add
 59  cdrom_type           = var.vm_cdrom_type
 60  disk_controller_type = var.vm_disk_controller_type
 61  storage {
 62    disk_size             = var.vm_disk_size
 63    disk_controller_index = 0
 64    disk_thin_provisioned = var.vm_disk_thin_provisioned
 65  }
 66  network_adapters {
 67    network      = var.vsphere_network
 68    network_card = var.vm_network_card
 69  }
 70  vm_version           = var.common_vm_version
 71  remove_cdrom         = var.common_remove_cdrom
 72  tools_upgrade_policy = var.common_tools_upgrade_policy
 73
 74
 75  // Removable Media Settings
 76  iso_paths = local.iso_paths
 77  cd_files = [
 78    "/opt/code/packer/windows/scripts/windows-init.ps1",
 79    "/opt/code/packer/windows/scripts/windows-prepare.ps1",
 80    "/opt/code/packer/windows/scripts/windows-vmtools.ps1",
 81
 82  ]
 83  cd_content = {
 84    "autounattend.xml" = templatefile("${abspath(path.root)}/data/autounattend.pkrtpl.hcl", {
 85      build_username       = "Administrator"
 86      build_password       = "VMware1!"
 87      vm_inst_os_language  = var.vm_inst_os_language
 88      vm_inst_os_keyboard  = var.vm_inst_os_keyboard
 89      vm_inst_os_image     = var.vm_inst_os_image_standard_desktop
 90      vm_inst_os_kms_key   = var.vm_inst_os_kms_key_standard
 91      vm_guest_os_language = var.vm_guest_os_language
 92      vm_guest_os_keyboard = var.vm_guest_os_keyboard
 93      vm_guest_os_timezone = var.vm_guest_os_timezone
 94    })
 95  }
 96
 97  // Boot and Provisioning Settings
 98  http_port_min     = var.common_http_port_min
 99  http_port_max     = var.common_http_port_max
100  boot_order        = var.vm_boot_order
101  boot_wait         = var.vm_boot_wait
102  boot_command      = var.vm_boot_command
103  ip_wait_timeout   = var.common_ip_wait_timeout
104  ip_settle_timeout = var.common_ip_settle_timeout
105  shutdown_command  = var.vm_shutdown_command
106  shutdown_timeout  = var.common_shutdown_timeout
107
108  // Communicator Settings and Credentials
109  communicator   = "winrm"
110  winrm_username = "Administrator"
111  winrm_password = "VMware1!"
112  winrm_port     = var.communicator_port
113  winrm_timeout  = var.communicator_timeout
114
115  // Template and Content Library Settings
116  convert_to_template = true
117
118}
119
120
121//  BLOCK: build
122//  Defines the builders to run, provisioners, and post-processors.
123
124build {
125  sources = [
126
127    "source.vsphere-iso.WIN2022_Std"
128
129  ]
130
131
132
133provisioner "powershell" {
134        scripts           = formatlist("${path.cwd}/windows/scripts/%s", var.scripts)
135  }
136
137}
3. windows-server.auto.pkrvars.hcl

Once a variable is declared in the configuration, we can set it as individual or using *.auto.pkrvars.hcl

Individually, with the -var foo=bar command line option.

In variable definitions files, either specified on the command line with the -var-files values.pkrvars.hcl or automatically loaded (*.auto.pkrvars.hcl).

 1
 2// Installation Operating System Metadata
 3vm_inst_os_language                 = "en-US"
 4vm_inst_os_keyboard                 = "en-GB"
 5vm_inst_os_image_standard_core      = "Windows Server 2022 SERVERSTANDARDCORE"
 6vm_inst_os_image_standard_desktop   = "Windows Server 2022 SERVERSTANDARD"
 7vm_inst_os_kms_key_standard         = "VDYBN-27WPP-V4HQT-9VMD4-VMK7H"
 8vm_inst_os_image_datacenter_core    = "Windows Server 2022 SERVERDATACENTERCORE"
 9vm_inst_os_image_datacenter_desktop = "Windows Server 2022 SERVERDATACENTER"
10vm_inst_os_kms_key_datacenter       = "WX4NM-KYWYW-QJJR4-XV3QB-6VM33"
11
12// Guest Operating System Metadata
13vm_guest_os_language           = "en-US"
14vm_guest_os_keyboard           = "en-GB"
15vm_guest_os_timezone           = "GMT Standard Time"
16vm_guest_os_family             = "windows"
17vm_guest_os_name               = "server"
18vm_guest_os_version            = "2022"
19vm_guest_os_edition_standard   = "standard"
20vm_guest_os_edition_datacenter = "datacenter"
21vm_guest_os_experience_core    = "core"
22vm_guest_os_experience_desktop = "dexp"
23
24// Virtual Machine Guest Operating System Setting
25vm_guest_os_type = "windows2019srvNext_64Guest"
26
27// Virtual Machine Hardware Settings
28vm_firmware              = "efi-secure"
29vm_cdrom_type            = "sata"
30vm_cpu_count             = 2
31vm_cpu_cores             = 1
32vm_cpu_hot_add           = false
33vm_mem_size              = 4096
34vm_mem_hot_add           = false
35vm_disk_size             = 102400
36vm_disk_controller_type  = ["pvscsi"]
37vm_disk_thin_provisioned = true
38vm_network_card          = "vmxnet3"
39
40// Removable Media Settings
41iso_path = "ISO"
42iso_file = "WIN2022_Eval.iso"
43
44// Boot Settings
45vm_boot_order       = "disk,cdrom"
46vm_boot_wait        = "2s"
47vm_boot_command     = ["<spacebar>"]
48vm_shutdown_command = "shutdown /s /t 10 /f /d p:4:1 /c \"Shutdown by Packer\""
49
50// Communicator Settings
51communicator_port    = 5985
52communicator_timeout = "12h"
53
54// Provisioner Settings
55scripts = ["/windows-prepare.ps1"]
56inline = [
57  "Get-EventLog -LogName * | ForEach { Clear-EventLog -LogName $_.Log }"
58]
4. autounattend.pkrtpl.hcl under data folder

Windows Server 2022 Autounttend.xml content

  1<?xml version="1.0" encoding="UTF-8"?>
  2<unattend xmlns="urn:schemas-microsoft-com:unattend">
  3   <settings pass="windowsPE">
  4      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
  5         <SetupUILanguage>
  6            <UILanguage>${vm_inst_os_language}</UILanguage>
  7         </SetupUILanguage>
  8         <InputLocale>${vm_inst_os_keyboard}</InputLocale>
  9         <SystemLocale>${vm_inst_os_language}</SystemLocale>
 10         <UILanguage>${vm_inst_os_language}</UILanguage>
 11         <UILanguageFallback>${vm_inst_os_language}</UILanguageFallback>
 12         <UserLocale>${vm_inst_os_language}</UserLocale>
 13      </component>
 14      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
 15         <DriverPaths>
 16            <PathAndCredentials wcm:action="add" wcm:keyValue="1">
 17               <Path>E:\Program Files\VMware\VMware Tools\Drivers\pvscsi\Win8\amd64</Path>
 18            </PathAndCredentials>
 19         </DriverPaths>
 20      </component>
 21      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
 22         <DiskConfiguration>
 23            <Disk wcm:action="add">
 24               <DiskID>0</DiskID>
 25               <WillWipeDisk>true</WillWipeDisk>
 26               <CreatePartitions>
 27                  <!-- Windows RE Tools partition -->
 28                  <CreatePartition wcm:action="add">
 29                     <Order>1</Order>
 30                     <Type>Primary</Type>
 31                     <Size>300</Size>
 32                  </CreatePartition>
 33                  <!-- System partition (ESP) -->
 34                  <CreatePartition wcm:action="add">
 35                     <Order>2</Order>
 36                     <Type>EFI</Type>
 37                     <Size>100</Size>
 38                  </CreatePartition>
 39                  <!-- Microsoft reserved partition (MSR) -->
 40                  <CreatePartition wcm:action="add">
 41                     <Order>3</Order>
 42                     <Type>MSR</Type>
 43                     <Size>128</Size>
 44                  </CreatePartition>
 45                  <!-- Windows partition -->
 46                  <CreatePartition wcm:action="add">
 47                     <Order>4</Order>
 48                     <Type>Primary</Type>
 49                     <Extend>true</Extend>
 50                  </CreatePartition>
 51               </CreatePartitions>
 52               <ModifyPartitions>
 53                  <!-- Windows RE Tools partition -->
 54                  <ModifyPartition wcm:action="add">
 55                     <Order>1</Order>
 56                     <PartitionID>1</PartitionID>
 57                     <Label>WINRE</Label>
 58                     <Format>NTFS</Format>
 59                     <TypeID>DE94BBA4-06D1-4D40-A16A-BFD50179D6AC</TypeID>
 60                  </ModifyPartition>
 61                  <!-- System partition (ESP) -->
 62                  <ModifyPartition wcm:action="add">
 63                     <Order>2</Order>
 64                     <PartitionID>2</PartitionID>
 65                     <Label>System</Label>
 66                     <Format>FAT32</Format>
 67                  </ModifyPartition>
 68                  <!-- MSR partition does not need to be modified -->
 69                  <ModifyPartition wcm:action="add">
 70                     <Order>3</Order>
 71                     <PartitionID>3</PartitionID>
 72                  </ModifyPartition>
 73                  <!-- Windows partition -->
 74                  <ModifyPartition wcm:action="add">
 75                     <Order>4</Order>
 76                     <PartitionID>4</PartitionID>
 77                     <Label>OS</Label>
 78                     <Letter>C</Letter>
 79                     <Format>NTFS</Format>
 80                  </ModifyPartition>
 81               </ModifyPartitions>
 82            </Disk>
 83         </DiskConfiguration>
 84         <ImageInstall>
 85            <OSImage>
 86               <InstallFrom>
 87                  <MetaData wcm:action="add">
 88                     <Key>/IMAGE/NAME</Key>
 89                     <Value>${vm_inst_os_image}</Value>
 90                  </MetaData>
 91               </InstallFrom>
 92               <InstallTo>
 93                  <DiskID>0</DiskID>
 94                  <PartitionID>4</PartitionID>
 95               </InstallTo>
 96            </OSImage>
 97         </ImageInstall>
 98         <UserData>
 99            <AcceptEula>true</AcceptEula>
100            <FullName>Administrator</FullName>
101            <Organization>Administrator</Organization>
102            <ProductKey>
103               <Key>${vm_inst_os_kms_key}</Key>
104               <WillShowUI>OnError</WillShowUI>
105            </ProductKey>
106         </UserData>
107         <EnableFirewall>false</EnableFirewall>
108      </component>
109   </settings>
110   <settings pass="offlineServicing">
111      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
112         <EnableLUA>false</EnableLUA>
113      </component>
114   </settings>
115   <settings pass="generalize">
116      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
117         <SkipRearm>1</SkipRearm>
118      </component>
119   </settings>
120   <settings pass="specialize">
121      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
122         <OEMInformation>
123            <HelpCustomized>false</HelpCustomized>
124         </OEMInformation>
125         <TimeZone>${vm_guest_os_timezone}</TimeZone>
126         <RegisteredOwner />
127      </component>
128      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-ServerManager-SvrMgrNc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
129         <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>
130      </component>
131      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-OutOfBoxExperience" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
132         <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>
133      </component>
134      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
135         <SkipAutoActivation>true</SkipAutoActivation>
136      </component>
137   </settings>
138   <settings pass="oobeSystem">
139      <component xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
140         <AutoLogon>
141            <Password>
142               <Value>VMware1!</Value>
143               <PlainText>true</PlainText>
144            </Password>
145            <Enabled>true</Enabled>
146            <Username>Administrator</Username>
147         </AutoLogon>
148         <OOBE>
149            <HideEULAPage>true</HideEULAPage>
150            <HideLocalAccountScreen>true</HideLocalAccountScreen>
151            <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
152            <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
153            <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
154            <NetworkLocation>Work</NetworkLocation>
155            <ProtectYourPC>2</ProtectYourPC>
156         </OOBE>
157         <UserAccounts>
158            <AdministratorPassword>
159               <Value>VMware1!</Value>
160               <PlainText>true</PlainText>
161            </AdministratorPassword>
162            <LocalAccounts>
163               <LocalAccount wcm:action="add">
164                  <Password>
165                     <Value>VMware1!</Value>
166                     <PlainText>true</PlainText>
167                  </Password>
168                  <Group>administrators</Group>
169                  <DisplayName>Administrator</DisplayName>
170                  <Name>Administrator</Name>
171                  <Description>Build Account</Description>
172               </LocalAccount>
173            </LocalAccounts>
174         </UserAccounts>
175         <FirstLogonCommands>
176            <SynchronousCommand wcm:action="add">
177               <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
178               <Description>Set Execution Policy 64-Bit</Description>
179               <Order>1</Order>
180               <RequiresUserInput>true</RequiresUserInput>
181            </SynchronousCommand>
182            <SynchronousCommand wcm:action="add">
183               <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine>
184               <Description>Set Execution Policy 32-Bit</Description>
185               <Order>2</Order>
186               <RequiresUserInput>true</RequiresUserInput>
187            </SynchronousCommand>
188            <SynchronousCommand wcm:action="add">
189               <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -File F:\windows-vmtools.ps1</CommandLine>
190               <Order>3</Order>
191               <Description>Install VMware Tools</Description>
192            </SynchronousCommand>
193            <SynchronousCommand wcm:action="add">
194               <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -File F:\windows-init.ps1</CommandLine>
195               <Order>4</Order>
196               <Description>Initial Configuration</Description>
197            </SynchronousCommand>
198         </FirstLogonCommands>
199      </component>
200   </settings>
201</unattend>

below 3 files will be mounted as F: drive in Windows Server 2022 during installtion. and the path is mentioned in autounaatend.pkrtpl.hcl file

5. windows-init.ps1 under scripts folder
 1
 2<#
 3    .DESCRIPTION
 4    Enables Windows Remote Management on Windows builds.
 5#>
 6
 7$ErrorActionPreference = 'Stop'
 8
 9# Set network connections provile to Private mode.
10Write-Output 'Setting the network connection profiles to Private...'
11$connectionProfile = Get-NetConnectionProfile
12While ($connectionProfile.Name -eq 'Identifying...') {
13    Start-Sleep -Seconds 10
14    $connectionProfile = Get-NetConnectionProfile
15}
16Set-NetConnectionProfile -Name $connectionProfile.Name -NetworkCategory Private
17
18# Set the Windows Remote Management configuration.
19Write-Output 'Setting the Windows Remote Management configuration...'
20winrm quickconfig -quiet
21winrm set winrm/config/service '@{AllowUnencrypted="true"}'
22winrm set winrm/config/service/auth '@{Basic="true"}'
23
24# Allow Windows Remote Management in the Windows Firewall.
25Write-Output 'Allowing Windows Remote Management in the Windows Firewall...'
26netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes
27netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow
28
29# Reset the autologon count.
30# Reference: https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-shell-setup-autologon-logoncount#logoncount-known-issue
31Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoLogonCount -Value 0

6. windows-prepare.ps1 under scripts folder
 1
 2<#
 3    .DESCRIPTION
 4    Prepares a Windows guest operating system.
 5#>
 6
 7$ErrorActionPreference = "Stop"
 8
 9
10
11# Set the Windows Explorer options.
12Write-Output "Setting the Windows Explorer options..."
13Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "Hidden" -Value 1 | Out-Null
14Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideFileExt" -Value 0 | Out-Null
15Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideDrivesWithNoMedia" -Value 0 | Out-Null
16Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "ShowSyncProviderNotifications" -Value 0 | Out-Null
17
18# Disable system hibernation.
19Write-Output "Disabling system hibernation..."
20Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Power\" -Name "HiberFileSizePercent" -Value 0 | Out-Null
21Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Power\" -Name "HibernateEnabled" -Value 0 | Out-Null
22
23# Disable TLS 1.0.s
24Write-Output "Disabling TLS 1.0..."
25New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols" -Name "TLS 1.0" | Out-Null
26New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0" -Name "Server" | Out-Null
27New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0" -Name "Client" | Out-Null
28New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client" -Name "Enabled" -Value 0 | Out-Null
29New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client" -Name "DisabledByDefault" -Value 1 | Out-Null
30New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -Name "Enabled" -Value 0 | Out-Null
31New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -Name "DisabledByDefault" -Value 1 | Out-Null
32
33# Disable TLS 1.1.
34Write-Output "Disabling TLS 1.1..."
35New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols" -Name "TLS 1.1" | Out-Null
36New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1" -Name "Server" | Out-Null
37New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1" -Name "Client" | Out-Null
38New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client" -Name "Enabled" -Value 0 | Out-Null
39New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client" -Name "DisabledByDefault" -Value 1 | Out-Null
40New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" -Name "Enabled" -Value 0 | Out-Null
41New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" -Name "DisabledByDefault" -Value 1 | Out-Null
42
43
44
45# Enable Remote Desktop.
46Write-Output "Enabling Remote Desktop..."
47Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value 0 | Out-Null
48Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -name "UserAuthentication" -Value 0
49Enable-NetFirewallRule -Group '@FirewallAPI.dll,-28752'
50
51
52# Disable Windows Firewall.
53Write-Output "Disabling Windows Firewall..."
54Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
7. windows-vmtools.ps1 under scripts folder
  1<#
  2    .DESCRIPTION
  3    Installs VMware Tools and runs re-attempts if the services fail on the first attempt.
  4
  5    .SYNOPSIS
  6    - Packer requires that the VMware Tools service is running.
  7    - If the "VMware Tools Service" fails to start, the script initiates a reinstallation.
  8
  9    .NOTES
 10    The below code is mostly based on the script within the following blog post by Owen Reynolds from scriptech.io.
 11    https://scriptech.io/automatically-reinstalling-vmware-tools-on-server2016-after-the-first-attempt-fails-to-install-the-vmtools-service/
 12#>
 13
 14$ErrorActionPreference = "Stop"
 15
 16# Install VMWare Tools
 17
 18Function Get-VMToolsInstalled {
 19    if (((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall") | Where-Object { $_.GetValue( "DisplayName" ) -like "*VMware Tools*" } ).Length -gt 0) {
 20        [int]$Version = "32"
 21    }
 22    if (((Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall") | Where-Object { $_.GetValue( "DisplayName" ) -like "*VMware Tools*" } ).Length -gt 0) {
 23       [int]$Version = "64"
 24    }
 25    return $Version
 26}
 27
 28# Set the current working directory to the CD-ROM that corresponds to the VMWare Tools .iso.
 29
 30Set-Location E:
 31
 32# Installation Attempt
 33
 34Write-Output "Installing VMware Tools..."
 35Start-Process "setup64.exe" -ArgumentList '/s /v "/qb REBOOT=R"' -Wait
 36
 37# Check to see if the 'VMTools' service is in a 'Running' state.
 38
 39$Running = $false
 40$iRepeat = 0
 41
 42while (-not $Running -and $iRepeat -lt 5) {
 43
 44  Start-Sleep -s 2
 45  Write-Output 'Checking VMware Tools service status...'
 46  $Service = Get-Service "VMTools" -ErrorAction SilentlyContinue
 47  $Servicestatus = $Service.Status
 48
 49  if ($ServiceStatus -ne "Running") {
 50    $iRepeat++
 51  }
 52  else {
 53    $Running = $true
 54    Write-Output "VMware Tools service is in a running state."
 55  }
 56}
 57
 58# If the service never enters the 'Running' state, reinstall VMware Tools.
 59
 60if (-not $Running) {
 61  #Uninstall VMWare Tools
 62  Write-Output "Uninstalling VMware Tools..."
 63  if (Get-VMToolsInstalled -eq "32") {
 64    $GUID = (Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.DisplayName -Like '*VMWARE Tools*' }).PSChildName
 65  }
 66  else {
 67    $GUID = (Get-ItemProperty HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.DisplayName -Like '*VMWARE Tools*' }).PSChildName
 68  }
 69
 70  # Uninstall VMware Tools based on 32-bit/64-bit install GUIDs captured via Get-VMToolsIsInstalled
 71
 72  Start-Process -FilePath msiexec.exe -ArgumentList "/X $GUID /quiet /norestart" -Wait
 73
 74  # Installation Attempt
 75
 76  Write-Output "Reintalling VMware Tools..."
 77  Start-Process "setup64.exe" -ArgumentList '/s /v "/qb REBOOT=R"' -Wait
 78
 79  # Check to see if the 'VMTools' service is in a 'Running' state.
 80
 81Write-Output "Checking VMware Tools service status..."
 82
 83$iRepeat = 0
 84while (-not $Running -and $iRepeat -lt 5) {
 85    Start-Sleep -s 2
 86    $Service = Get-Service "VMTools" -ErrorAction SilentlyContinue
 87    $ServiceStatus = $Service.Status
 88
 89    if ($ServiceStatus -ne "Running") {
 90      $iRepeat++
 91    }
 92    else {
 93      $Running = $true
 94      Write-Output "VMware Tools service is in a running state."
 95    }
 96  }
 97
 98  # If after the reinstall, the service is still not running, the installation is unsuccessful.
 99
100  if (-not $Running) {
101    Write-Error "VMware Tools installation was unsuccessful."
102    Pause
103  }
104
105}

Now that we have all the required configurations in place, will process with build.

To start the build, enter the following command from /opt/code/packer folder

1packer build -var-file=common.pkrvars.hcl -var-file=vsphere.pkrvars.hcl windows/2022

it took, approximately 12 minutes for me to complete the template creation

Watch the video on How to:


Posts in this Series