Initial commit: Packer + QEMU/KVM Windows 11 minimal VM

Fully unattended Windows 11 Pro build using Autounattend.xml, swtpm
for TPM 2.0 emulation, and VirtIO drivers. Five PowerShell provisioners
strip bloatware, telemetry, unused services, and apply performance tuning
for a resource-constrained host. Output is a compressed QCOW2 image.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-17 19:31:18 -05:00
commit e4741ccc96
12 changed files with 980 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
#Requires -RunAsAdministrator
$apps = @(
# Microsoft bloat
"Microsoft.3DBuilder",
"Microsoft.BingFinance",
"Microsoft.BingNews",
"Microsoft.BingSearch",
"Microsoft.BingSports",
"Microsoft.BingTranslator",
"Microsoft.BingWeather",
"Microsoft.GetHelp",
"Microsoft.Getstarted",
"Microsoft.GamingApp",
"Microsoft.Microsoft3DViewer",
"Microsoft.MicrosoftOfficeHub",
"Microsoft.MicrosoftSolitaireCollection",
"Microsoft.MicrosoftStickyNotes",
"Microsoft.MixedReality.Portal",
"Microsoft.Office.OneNote",
"Microsoft.People",
"Microsoft.PowerAutomateDesktop",
"Microsoft.Print3D",
"Microsoft.SkypeApp",
"Microsoft.Todos",
"Microsoft.WindowsAlarms",
"Microsoft.WindowsCamera",
"Microsoft.windowscommunicationsapps", # Mail + Calendar
"Microsoft.WindowsFeedbackHub",
"Microsoft.WindowsMaps",
"Microsoft.WindowsPhone",
"Microsoft.WindowsSoundRecorder",
"Microsoft.Whiteboard",
"Microsoft.Windows.DevHome",
# Xbox ecosystem
"Microsoft.Xbox.TCUI",
"Microsoft.XboxApp",
"Microsoft.XboxGameOverlay",
"Microsoft.XboxGamingOverlay",
"Microsoft.XboxIdentityProvider",
"Microsoft.XboxSpeechToTextOverlay",
# Media / entertainment
"Microsoft.ZuneMusic",
"Microsoft.ZuneVideo",
"Clipchamp.Clipchamp",
# Teams personal and Cortana
"MicrosoftTeams",
"Microsoft.549981C3F5F10",
# Phone Link
"Microsoft.YourPhone"
)
foreach ($app in $apps) {
Get-AppxPackage -Name $app -AllUsers -ErrorAction SilentlyContinue |
Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue |
Where-Object { $_.PackageName -like "*$app*" } |
Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
}
# Uninstall OneDrive
Stop-Process -Name OneDrive -Force -ErrorAction SilentlyContinue
$uninstaller = if (Test-Path "$env:SYSTEMROOT\SysWOW64\OneDriveSetup.exe") {
"$env:SYSTEMROOT\SysWOW64\OneDriveSetup.exe"
} else {
"$env:SYSTEMROOT\System32\OneDriveSetup.exe"
}
if (Test-Path $uninstaller) {
Start-Process $uninstaller -ArgumentList "/uninstall" -Wait -ErrorAction SilentlyContinue
}
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\OneDrive" /v DisableFileSyncNGSC /t REG_DWORD /d 1 /f | Out-Null

View File

@@ -0,0 +1,63 @@
#Requires -RunAsAdministrator
# Telemetry level — policy key can enforce 0 (Security) even on Home/Pro
$telemetryPaths = @(
"HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection"
)
foreach ($p in $telemetryPaths) {
New-Item -Path $p -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path $p -Name AllowTelemetry -Value 0 -Type DWord -Force
Set-ItemProperty -Path $p -Name MaxTelemetryAllowed -Value 0 -Type DWord -Force
}
# Advertising ID
New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo" -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo" -Name DisabledByGroupPolicy -Value 1 -Type DWord -Force
# Windows Error Reporting
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Error Reporting" /v Disabled /t REG_DWORD /d 1 /f | Out-Null
# Customer Experience Improvement Program
reg add "HKLM\SOFTWARE\Policies\Microsoft\SQMClient\Windows" /v CEIPEnable /t REG_DWORD /d 0 /f | Out-Null
# Feedback notifications
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\DataCollection" /v DoNotShowFeedbackNotifications /t REG_DWORD /d 1 /f | Out-Null
# Cortana and web search
$searchPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search"
New-Item -Path $searchPath -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path $searchPath -Name AllowCortana -Value 0 -Type DWord -Force
Set-ItemProperty -Path $searchPath -Name DisableWebSearch -Value 1 -Type DWord -Force
Set-ItemProperty -Path $searchPath -Name ConnectedSearchUseWeb -Value 0 -Type DWord -Force
Set-ItemProperty -Path $searchPath -Name AllowSearchToUseLocation -Value 0 -Type DWord -Force
# Activity History / Timeline
$systemPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System"
New-Item -Path $systemPath -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path $systemPath -Name EnableActivityFeed -Value 0 -Type DWord -Force
Set-ItemProperty -Path $systemPath -Name PublishUserActivities -Value 0 -Type DWord -Force
Set-ItemProperty -Path $systemPath -Name UploadUserActivities -Value 0 -Type DWord -Force
# Disable DiagTrack (telemetry) service
Stop-Service DiagTrack -Force -ErrorAction SilentlyContinue
Set-Service DiagTrack -StartupType Disabled -ErrorAction SilentlyContinue
# Disable telemetry-related scheduled tasks
$tasks = @(
@{Path="\Microsoft\Windows\Application Experience"; Name="Microsoft Compatibility Appraiser"},
@{Path="\Microsoft\Windows\Application Experience"; Name="ProgramDataUpdater"},
@{Path="\Microsoft\Windows\Application Experience"; Name="StartupAppTask"},
@{Path="\Microsoft\Windows\Autochk"; Name="Proxy"},
@{Path="\Microsoft\Windows\Customer Experience Improvement Program"; Name="Consolidator"},
@{Path="\Microsoft\Windows\Customer Experience Improvement Program"; Name="UsbCeip"},
@{Path="\Microsoft\Windows\DiskDiagnostic"; Name="Microsoft-Windows-DiskDiagnosticDataCollector"},
@{Path="\Microsoft\Windows\Feedback\Siuf"; Name="DmClient"},
@{Path="\Microsoft\Windows\Feedback\Siuf"; Name="DmClientOnScenarioDownload"},
@{Path="\Microsoft\Windows\Maps"; Name="MapsToastTask"},
@{Path="\Microsoft\Windows\Maps"; Name="MapsUpdateTask"},
@{Path="\Microsoft\Windows\Windows Error Reporting"; Name="QueueReporting"}
)
foreach ($t in $tasks) {
Disable-ScheduledTask -TaskPath $t.Path -TaskName $t.Name -ErrorAction SilentlyContinue | Out-Null
}

View File

@@ -0,0 +1,32 @@
#Requires -RunAsAdministrator
# Services that consume resources without adding value in a minimal VM
$disable = @{
"DiagTrack" = "Connected User Experiences and Telemetry"
"dmwappushservice" = "WAP Push Message Routing"
"SysMain" = "Superfetch — causes high I/O in VMs"
"WSearch" = "Windows Search indexer — CPU/disk heavy"
"MapsBroker" = "Downloaded Maps Manager"
"lfsvc" = "Geolocation Service"
"XblAuthManager" = "Xbox Live Auth Manager"
"XblGameSave" = "Xbox Live Game Save"
"XboxGipSvc" = "Xbox Accessory Management"
"XboxNetApiSvc" = "Xbox Live Networking"
"RetailDemo" = "Retail Demo"
"Fax" = "Fax"
"WbioSrvc" = "Windows Biometric (no fingerprint reader in VM)"
"WMPNetworkSvc" = "Windows Media Player Network Sharing"
"icssvc" = "Mobile Hotspot"
"SharedAccess" = "Internet Connection Sharing"
"wisvc" = "Windows Insider Service"
"PcaSvc" = "Program Compatibility Assistant"
"wercplsupport" = "Problem Reports control panel support"
}
foreach ($name in $disable.Keys) {
$svc = Get-Service -Name $name -ErrorAction SilentlyContinue
if ($svc) {
Stop-Service -Name $name -Force -ErrorAction SilentlyContinue
Set-Service -Name $name -StartupType Disabled -ErrorAction SilentlyContinue
}
}

View File

@@ -0,0 +1,43 @@
#Requires -RunAsAdministrator
# ── Power plan: High Performance ────────────────────────────────────────────
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
# ── Hibernate: off (saves ~RAM-size on disk) ─────────────────────────────────
powercfg /hibernate off
# ── System Restore: off (saves disk and shadow-copy overhead) ────────────────
Disable-ComputerRestore -Drive "C:\" -ErrorAction SilentlyContinue
vssadmin delete shadows /for=C: /all /quiet 2>$null
# ── Visual effects: best performance ─────────────────────────────────────────
$ve = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects"
New-Item -Path $ve -Force -ErrorAction SilentlyContinue | Out-Null
Set-ItemProperty -Path $ve -Name VisualFXSetting -Value 2 -Type DWord
$desktop = "HKCU:\Control Panel\Desktop"
Set-ItemProperty -Path $desktop -Name DragFullWindows -Value "0"
Set-ItemProperty -Path $desktop -Name MenuShowDelay -Value "0"
$adv = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Set-ItemProperty -Path $adv -Name TaskbarAnimations -Value 0 -Type DWord
Set-ItemProperty -Path $adv -Name DisallowShaking -Value 1 -Type DWord
# ── Page file: fixed size to avoid resize churn ──────────────────────────────
$cs = Get-WmiObject Win32_ComputerSystem -EnableAllPrivileges
$cs.AutomaticManagedPagefile = $false
$cs.Put() | Out-Null
$pf = Get-WmiObject -Query "Select * From Win32_PageFileSetting Where Name='C:\\pagefile.sys'"
if ($pf) {
$pf.InitialSize = 2048
$pf.MaximumSize = 4096
$pf.Put() | Out-Null
}
# ── NTFS: skip Last Access Time updates ──────────────────────────────────────
fsutil behavior set disablelastaccess 1 | Out-Null
# ── Processor scheduling: favor background services (better for VM workloads) ─
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\PriorityControl" `
-Name Win32PrioritySeparation -Value 24 -Type DWord

31
scripts/05-cleanup.ps1 Normal file
View File

@@ -0,0 +1,31 @@
#Requires -RunAsAdministrator
# Windows Update cache
Stop-Service wuauserv -Force -ErrorAction SilentlyContinue
Remove-Item "C:\Windows\SoftwareDistribution\Download\*" -Recurse -Force -ErrorAction SilentlyContinue
Start-Service wuauserv -ErrorAction SilentlyContinue
# Temp folders
Remove-Item "$env:TEMP\*" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\Windows\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue
# Windows Error Reporting archives
Remove-Item "C:\ProgramData\Microsoft\Windows\WER\*" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item "C:\Windows\Minidump\*" -Force -ErrorAction SilentlyContinue
Remove-Item "C:\Windows\MEMORY.DMP" -Force -ErrorAction SilentlyContinue
# Prefetch (small, but consistent)
Remove-Item "C:\Windows\Prefetch\*" -Force -ErrorAction SilentlyContinue
# Event logs
Get-EventLog -LogName * -ErrorAction SilentlyContinue | ForEach-Object {
Clear-EventLog -LogName $_.Log -ErrorAction SilentlyContinue
}
# DISM: remove superseded Windows component store entries
DISM /Online /Cleanup-Image /StartComponentCleanup /ResetBase
# Compact OS: reduces on-disk footprint using XPRESS4K compression
Compact.exe /CompactOS:Always
Write-Output "Cleanup complete."