Reduce Your Virtual Machine Build Time Using Hashicorp Packer: [Part 5 - Configuration Scripts]
Jan 25, 2024Introduction:
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.
- Create an empty file named vmware-tools.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- 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.
- Create an empty file named setup.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- Copy and paste the code below into the file and save it.
Here's what it does.
-
Setting View Options:
Hidden
set to1
: This command configures Windows Explorer to show hidden files, folders, and drives.HideFileExt
set to0
: It configures Windows Explorer to show file extensions for known file types.HideDrivesWithNoMedia
set to0
: Ensures that drives with no media are not hidden in Windows Explorer.ShowSyncProviderNotifications
set to0
: Disables sync provider notifications.
-
Disable Hibernation:
HiberFileSizePercent
set to0
andHibernateEnabled
set to0
: 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).
-
Hide Edge First Run Experience:
- Creates a new registry key for Microsoft Edge settings and sets
HideFirstRunExperience
to1
, which disables the first run experience (like introductory prompts) for the Edge browser.
- Creates a new registry key for Microsoft Edge settings and sets
-
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 GUIDDED574B5-45A0-4F42-8737-46345C09C238
.
- The
-
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.
- Create an empty file named WinRMCert.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- Copy and paste the code below into the file and save it.
Here's what it does.
-
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').
-
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.
-
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.
- The script then retrieves the newly created certificate and uses its thumbprint to configure WinRM. The
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.
- Create an empty file named install-windows-updates.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- Copy and paste the code below into the file and save it.
Here's what it does.
-
Setting
$ProgressPreference
: This line sets the progress bar preference toSilentlyContinue
to avoid cluttering the output with progress bar information, which can be particularly problematic when automating tasks. -
Installing PSWindowsUpdate Module:
- It uses
Install-PackageProvider
andInstall-Module
to ensure that the NuGet provider and thePSWindowsUpdate
module are installed.PSWindowsUpdate
is a module that allows management of Windows Update through PowerShell.
- It uses
-
Checking Module Installation:
- It checks if the
PSWindowsUpdate
module is correctly installed in the Windows PowerShell Modules directory.
- It checks if the
-
Importing PSWindowsUpdate Module:
- The script attempts to import the
PSWindowsUpdate
module. If it fails, an error is written, and the script exits.
- The script attempts to import the
-
Handling Windows Update Log:
- If there is an existing
PSWindowsUpdate.log
file inC:\Windows\Temp
, it is removed to ensure fresh logging for this update session.
- If there is an existing
-
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.
-
Executing Windows Update:
- The scheduled task executes a command to import
PSWindowsUpdate
and runGet-WUInstall
with the-AcceptAll
and-Install
flags, indicating that all updates should be automatically accepted and installed. The output is directed toPSWindowsUpdate.log
.
- The scheduled task executes a command to import
-
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.
- The script then enters a loop where it monitors the
-
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.
- Create an empty file named SetupComplete.cmd in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- 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.
- Create an empty file named cleanup.ps1 in the C:\AutomatedSandboxFramework\Win2022\scripts directory.
- Copy and paste the code below into the file and save it.
Here's what it does.
-
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.
-
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.
-
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 theSoftwareDistribution\Download
folder, where Windows stores temporary files for Windows Update. This can help resolve issues with Windows Update.
-
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.
-
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.
-
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.