Files
lite-win/README.md
jacob.b.nelson2 e4741ccc96 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>
2026-05-17 19:31:18 -05:00

5.3 KiB
Raw Permalink Blame History

lite-win

A repeatable, minimal Windows 11 Pro VM image built with Packer and QEMU/KVM. No bloatware, no Microsoft account requirement, no unnecessary services.

Designed for a resource-constrained Linux host running Fedora with QEMU/KVM.


What it does

  1. Boots the Windows 11 Pro ISO fully unattended via Autounattend.xml
  2. Partitions the disk (GPT/UEFI), installs Windows, configures WinRM
  3. Runs five PowerShell provisioner scripts over WinRM:
    • Removes ~30 built-in apps and OneDrive
    • Disables telemetry, Cortana, advertising ID, and CEIP
    • Disables resource-heavy services (SysMain, Windows Search, Xbox, etc.)
    • Applies performance tweaks (High Performance power plan, fixed page file, no animations)
    • Cleans up temp files and compacts the OS
  4. Produces a thin-provisioned, compressed QCOW2 disk image (~1215 GB)

Prerequisites

Install these on the Fedora host before building:

sudo dnf install -y qemu-kvm swtpm edk2-ovmf packer

Packer may not be in the Fedora repos depending on your version. If dnf doesn't find it, download the Linux AMD64 binary from releases.hashicorp.com/packer and place it in ~/.local/bin/.

You also need:


Quick start

# 1. Download VirtIO drivers
make virtio-iso

# 2. Create your local variable file
cp variables.pkrvars.hcl.example variables.pkrvars.hcl

Edit variables.pkrvars.hcl and set:

win_iso_path     = "/path/to/Win11_24H2_English_x64.iso"
win_iso_checksum = "sha256:<output of: sha256sum /path/to/Win11_*.iso>"
# 3. Build
make build

The finished image lands in output/windows11-lite.


Running the image

virt-install \
  --name windows11-lite \
  --memory 4096 \
  --vcpus 2 \
  --disk output/windows11-lite,format=qcow2,bus=virtio \
  --import \
  --os-variant win11 \
  --network network=default,model=virtio \
  --graphics spice,listen=none \
  --video qxl \
  --boot uefi \
  --tpm emulator,model=tpm-tis,version=2.0 \
  --noautoconsole

Then connect with virt-manager or virt-viewer windows11-lite.

virt-manager GUI

  1. File → New VM → Import existing disk image
  2. Browse to output/windows11-lite; set OS to Windows 11
  3. Set RAM and CPUs, then Customize configuration before install
  4. Set FirmwareUEFI x86_64 (not BIOS)
  5. Set disk BusVirtIO
  6. Add Hardware → TPM → Emulated, TIS, version 2.0
  7. Begin installation

All three settings — UEFI boot, VirtIO disk bus, TPM 2.0 — are required. The image was built against them; mismatching any one causes a boot failure.


Windows activation

The build uses the generic KMS client key W269N-WFGWX-YVC9B-4J6C9-T83GX to allow unattended installation. This is not an activation key. Activate Windows with your own license after the build.


Variables reference

Variable Default Description
win_iso_path Required. Absolute path to the Windows 11 ISO
win_iso_checksum Required. sha256:<hash> of the ISO
virtio_iso_path virtio-win.iso Path to VirtIO drivers ISO
vm_name windows11-lite Output image name
disk_size 51200 Virtual disk size in MB (50 GB)
memory 4096 RAM in MB during the Packer build
cpus 2 vCPUs during the Packer build
output_directory output Output directory for the QCOW2 image
winrm_password Packer1234! Build-time WinRM password — must match Autounattend.xml
ovmf_code /usr/share/edk2/ovmf/OVMF_CODE.fd UEFI firmware code (Fedora default)
ovmf_vars /usr/share/edk2/ovmf/OVMF_VARS.fd UEFI firmware vars template (Fedora default)

All variables except win_iso_path and win_iso_checksum have usable defaults.


Project structure

.
├── build.sh                       # Starts swtpm, runs packer, cleans up on exit
├── Makefile                       # Convenience targets
├── windows11.pkr.hcl              # Packer template
├── variables.pkrvars.hcl.example  # Variable template (copy → variables.pkrvars.hcl)
├── http/
│   └── Autounattend.xml           # Unattended Windows install answer file
└── scripts/
    ├── 01-debloat-apps.ps1        # Remove built-in apps and OneDrive
    ├── 02-disable-telemetry.ps1   # Disable telemetry, Cortana, CEIP
    ├── 03-disable-services.ps1    # Disable unnecessary services
    ├── 04-performance.ps1         # Power plan, page file, visual effects
    └── 05-cleanup.ps1             # DISM cleanup, temp purge, Compact OS

Make targets

Target Description
make build Build the VM image (default)
make validate Validate Packer config without building
make init Install Packer plugins
make virtio-iso Download the VirtIO drivers ISO
make clean Remove build output
make distclean Remove build output and downloaded ISOs