PowerCLI for Guest OS Customization and In-Guest Scripting: Automating VM Configuration from the Inside

Introduction

Provisioning a VM is only the first step. Guest-level configuration like hostname setup, IP assignment, domain join, and application bootstrapping are often manual, inconsistent, and time-consuming. With PowerCLI, you can automate guest customization both during and after VM deployment.

In this article, we will explore:

  • Creating and applying customization specs
  • Modifying NIC mappings for static IPs
  • Using Invoke-VMScript to configure the OS post-deployment
  • Managing credentials and session reuse securely

My Personal Repository on GitHub

VMware Repository on GitHub


Step 1: Review or Create a Customization Spec

View existing specs:

Get-OSCustomizationSpec

Create a new one in vSphere Client or use PowerCLI:

New-OSCustomizationSpec -Name "Win2019-Auto" `
-OSType Windows `
-FullName "VMware Admin" `
-OrgName "Lab" `
-ProductKey "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" `
-AdminPassword (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force) `
-TimeZone 035 `
-ChangeSid $true

Step 2: Deploy VM with Customization Spec

New-VM -Name "SQLNode01" `
-Template "Win2019-Base" `
-Datastore "DS01" `
-VMHost "esxi01.lab.local" `
-OSCustomizationSpec "Win2019-Auto"

Step 3: Modify NIC Mapping for Static IPs

$spec = Get-OSCustomizationSpec -Name "Win2019-Auto"
Set-OSCustomizationNicMapping -OSCustomizationSpec $spec `
-Position 1 `
-IpMode UseStaticIP `
-IpAddress "192.168.10.101" `
-SubnetMask "255.255.255.0" `
-DefaultGateway "192.168.10.1"

Step 4: Use Invoke-VMScript for In-Guest Configuration

Example: Create a Directory and Registry Key on a Windows VM

$vm = Get-VM -Name "SQLNode01"
$cred = Get-Credential

Invoke-VMScript -VM $vm -ScriptText 'mkdir C:\Tools; reg add "HKLM\Software\MyCompany" /v Installed /t REG_SZ /d True /f' `
-GuestCredential $cred -ScriptType Bat

Example: Run a Bash Script on a Linux VM

$vm = Get-VM -Name "UbuntuApp01"
$cred = Get-Credential

Invoke-VMScript -VM $vm -ScriptText 'echo "export ENV=dev" >> ~/.bashrc' `
-GuestCredential $cred -ScriptType Bash

Step 5: Pass Parameters to Scripts

You can store custom values in a CSV or hashtable and loop through deployments.

$servers = Import-Csv "C:\Configs\LinuxVMs.csv"

foreach ($vmInfo in $servers) {
$vm = Get-VM -Name $vmInfo.Name
$script = "hostnamectl set-hostname $($vmInfo.Hostname)"
Invoke-VMScript -VM $vm -ScriptText $script -GuestCredential (Get-Credential) -ScriptType Bash
}

Diagram: Guest Customization Automation


Use Case: Automating SQL Server Prep on Windows

$vm = Get-VM -Name "SQL01"
$cred = Get-Credential

Invoke-VMScript -VM $vm `
-ScriptText 'Install-WindowsFeature -Name NET-Framework-45-Core' `
-GuestCredential $cred -ScriptType Powershell

You can expand this to include copying ISOs, mounting media, and unattended setup.


Security Tips

  • Always use SecureString for passwords
  • Avoid hardcoding credentials in scripts
  • Use a jump host or dedicated PowerShell session with just-in-time permissions
  • Clean up any in-guest temp files created by scripts

Troubleshooting

IssueFix
Invoke-VMScript returns blankCheck that VMware Tools is running and up-to-date
Static IP not appliedUse Set-OSCustomizationNicMapping before deployment
Script execution blockedAdjust execution policy or permissions in guest OS
Guest credentials rejectedEnsure the user has remote script permissions and is not UAC-blocked

What’s Next

In the next article, we will cover:

  • Automating VM encryption and TPM setup with PowerCLI
  • Assigning KMS policies
  • Verifying encryption status and compliance

Leave a Reply

Discover more from Digital Thought Disruption

Subscribe now to keep reading and get access to the full archive.

Continue reading