Reduce Your Virtual Machine Build Time Using Hashicorp Packer: [Part 5 - Configuration Scripts]

automation packer Jan 25, 2024
packer-part-5

Introduction:


In part 4, we created the autounattend.xml and PackerShutdown.bat files and created the source block.  

Most machine builds require additional configuration after installing the OS.  At this point, you generally wouldn't turn the server over to the application or database team without further tweaks to meet your organization's standards. 

We'll create six configuration scripts to automate these steps while building the golden image.  The goal is to have an image that can be used as a basis for 90% of the servers built.  The remaining 10% of customization can be done using tools such as Powershell's Desired State Configuration, Ansible, Chef, etc.

Let's get started.

Step 1: VMware Tools Installation


VMware Tools is a suite of utilities and drivers designed to enhance the performance and functionality of virtual machines (VMs) running on VMware virtualization platforms. These tools are specifically developed to work in the context of a virtual environment provided by VMware products like VMware ESXi, VMware Workstation, VMware Fusion, and others.

We'll install these tools while building the golden image.

  1. Create an empty file named vmware-tools.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
  2. Copy and paste the code below into the file and save it.  This script downloads the latest version of VMware Tools and installs it.

Step 2: Setup.ps1


Next, we need to create the Setup.ps1 file.  We'll use this script to set various settings on Windows.

  1. Create an empty file named setup.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory. 
  2. Copy and paste the code below into the file and save it.  

Here's what it does.

  1. Setting View Options:

    • Hidden set to 1: This command configures Windows Explorer to show hidden files, folders, and drives.
    • HideFileExt set to 0: It configures Windows Explorer to show file extensions for known file types.
    • HideDrivesWithNoMedia set to 0: Ensures that drives with no media are not hidden in Windows Explorer.
    • ShowSyncProviderNotifications set to 0: Disables sync provider notifications.
  2. Disable Hibernation:

    • HiberFileSizePercent set to 0 and HibernateEnabled set to 0: These commands disable the hibernation feature on Windows, which can free up disk space equal to your RAM size (as hibernation saves the contents of RAM to disk).
  3. Hide Edge First Run Experience:

    • Creates a new registry key for Microsoft Edge settings and sets HideFirstRunExperience to 1, which disables the first run experience (like introductory prompts) for the Edge browser.
  4. Disable Sleep and Adjust Power Settings:

    • The powercfg commands are used to change various power settings, effectively disabling sleep and monitor turn-off timings for both AC (plugged in) and DC (battery) power modes.
    • powercfg /setactive: Sets the active power profile to High Performance, which is identified by the GUID DED574B5-45A0-4F42-8737-46345C09C238.
  5. Disable Password Expiration for Administrator:

    • Set-LocalUser Administrator -PasswordNeverExpires $true: Disables password expiration for the Administrator account, ensuring that the password does not need to be changed periodically. This setting is useful for certain administrative or automated tasks, but it's generally recommended to have passwords expire for security reasons.

 Step 3: WinRMCert.ps1


Next, we need to create the WinRMCert.ps1 file.  We'll use this script to manage the self-signed certificate used by WinRM.  It will be executed on first boot when creating a virtual machine from the image.

  1. Create an empty file named WinRMCert.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
  2. Copy and paste the code below into the file and save it.

 Here's what it does.

  1. Remove Existing Self-Signed Certificate:

    • get-childitem Cert:\LocalMachine\My\ -DnsName "WinRMCertificate" | Remove-Item: This command searches for and removes a self-signed certificate with the DNS name "WinRMCertificate" from the local machine's certificate store (specifically in the Personal store, also known as 'My').
  2. Create New Self-Signed Certificate if None Exists:

    • IF (!(get-childitem Cert:\LocalMachine\My\)) { New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "WinRMCertificate"}: This command checks if there are any certificates in the 'My' store. If none are found, it creates a new self-signed certificate with the DNS name "WinRMCertificate." This step ensures that a valid certificate is always present, which is necessary for secure communications.
  3. Configure WinRM to Use the New Certificate:

    • The script then retrieves the newly created certificate and uses its thumbprint to configure WinRM. The Set-WSManInstance cmdlet updates the WinRM service configuration to use the new certificate for HTTPS communications. The -ResourceURI winrm/config/listener specifies that the configuration is for the WinRM listener and -SelectorSet @{Address="*";Transport="https"} indicates that this applies to all addresses (wildcard *) using HTTPS transport. The -ValueSet @{CertificateThumbprint=$cert.Thumbprint} part assigns the new certificate to the listener.

Step 4: install-windows-updates.ps1


We'll create a script to install and run the PSWindowsUpdate PowerShell module.  After installation, the latest updates will be applied. This will ensure the image will take considerably less time to patch once deployed as a new virtual machine.

  1. Create an empty file named install-windows-updates.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
  2. Copy and paste the code below into the file and save it.

 

Here's what it does.

  1. Setting $ProgressPreference: This line sets the progress bar preference to SilentlyContinue to avoid cluttering the output with progress bar information, which can be particularly problematic when automating tasks.

  2. Installing PSWindowsUpdate Module:

    • It uses Install-PackageProvider and Install-Module to ensure that the NuGet provider and the PSWindowsUpdate module are installed. PSWindowsUpdate is a module that allows management of Windows Update through PowerShell.
  3. Checking Module Installation:

    • It checks if the PSWindowsUpdate module is correctly installed in the Windows PowerShell Modules directory.
  4. Importing PSWindowsUpdate Module:

    • The script attempts to import the PSWindowsUpdate module. If it fails, an error is written, and the script exits.
  5. Handling Windows Update Log:

    • If there is an existing PSWindowsUpdate.log file in C:\Windows\Temp, it is removed to ensure fresh logging for this update session.
  6. Scheduling a Task for Updates:

    • The script creates a new task in the Windows Task Scheduler to run the Windows Update process. It configures the task with necessary details like description, author, settings, and actions. The task is set to run under the SYSTEM account for appropriate permissions.
  7. Executing Windows Update:

    • The scheduled task executes a command to import PSWindowsUpdate and run Get-WUInstall with the -AcceptAll and -Install flags, indicating that all updates should be automatically accepted and installed. The output is directed to PSWindowsUpdate.log.
  8. Monitoring and Outputting Update Progress:

    • The script then enters a loop where it monitors the PSWindowsUpdate.log file and outputs its contents to the console. This allows you to see the progress and results of the Windows Update process in real-time.
  9. Cleanup:

    • Once the updates are complete (determined by the task no longer running), the script cleans up by deleting the scheduled task, releasing COM objects, and closing any open file streams.

Step 5: SetupComplete.cmd


Next, we'll create the SetupComplete.cmd file.  This script is used to re-enable the WinRm, HTTP and HTTPS, firewall rules and to remove the autounattend.xml file from the virtual machine.  It's executed when the virtual machine is created from the image.  We use the file provisioner to copy it to C:\Windows\Setup\Scripts\ when building the image. 

  1. Create an empty file named SetupComplete.cmd in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
  2. Copy and paste the code below into the file and save it.

 Step 6: cleanup.ps1


Final script.  This script is used to do some cleanup of our image. 

  1. Create an empty file named cleanup.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
  2. Copy and paste the code below into the file and save it.

 Here's what it does.

  1. Clear Host:

    • Clear-Host: Clears the PowerShell console window. This is more for visual clarity and has no effect on the system or script functionality.
  2. Stopping the Windows Update Service:

    • Get-Service -Name wuauserv | Stop-Service -Force -Verbose -ErrorAction SilentlyContinue: This line stops the Windows Update service (wuauserv). The -Force flag ensures that the service stops even if there are dependent services. The -Verbose flag provides detailed information about the operation's execution, and -ErrorAction SilentlyContinue prevents the script from halting if an error occurs while stopping the service.
  3. Deleting Contents of Windows Software Distribution:

    • Get-ChildItem "C:\Windows\SoftwareDistribution\Download\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue: This line deletes the contents of the SoftwareDistribution\Download folder, where Windows stores temporary files for Windows Update. This can help resolve issues with Windows Update.
  4. Deleting Files in User's Temp Folder:

    • Get-ChildItem "C:\users\*\AppData\Local\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue: This command deletes all files and folders in the Temp folder for every user profile on the system. The Temp folder is used for storing temporary files by both the system and applications.
  5. Removing Files in Temporary Internet Files Folder:

    • Get-ChildItem "C:\users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue: This line clears out the Temporary Internet Files folder for all user profiles. These folders store cached copies of web pages and other internet content.
  6. Deleting Contents of the Windows Temp Folder:

    • Get-ChildItem "C:\Windows\Temp\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | Remove-Item -Force -Verbose -Recurse -ErrorAction SilentlyContinue: Similar to the user's Temp folder, this command clears the Windows Temp folder, which is used by the operating system and some system-level applications to store temporary files.

Conclusion:


At this point, all supporting scripts have been created.  In Part 6, we'll complete the HCL template and run "packer build."

It's a good time to review the official documentation on Packer as well. 

If you want to automate your sandbox builds using tools like packer, there's a course for that.  Check it out here.

Thanks for stopping by.