Files
lite-win/windows11.pkr.hcl
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

140 lines
3.4 KiB
HCL

packer {
required_plugins {
qemu = {
version = ">= 1.1.0"
source = "github.com/hashicorp/qemu"
}
}
}
variable "win_iso_path" {
type = string
description = "Absolute path to Windows 11 Pro ISO"
}
variable "win_iso_checksum" {
type = string
description = "SHA-256 checksum prefixed with 'sha256:'"
}
variable "virtio_iso_path" {
type = string
default = "virtio-win.iso"
description = "Path to VirtIO drivers ISO (downloaded by 'make virtio-iso')"
}
variable "swtpm_sock" {
type = string
description = "Unix socket path for swtpm TPM emulator (managed by build.sh)"
}
variable "vm_name" {
type = string
default = "windows11-lite"
}
variable "disk_size" {
type = number
default = 51200
description = "Virtual disk size in MB (default 50 GB)"
}
variable "memory" {
type = number
default = 4096
description = "RAM in MB allocated during build"
}
variable "cpus" {
type = number
default = 2
}
variable "output_directory" {
type = string
default = "output"
}
variable "winrm_password" {
type = string
default = "Packer1234!"
sensitive = true
description = "WinRM password used during build; must match Autounattend.xml"
}
variable "ovmf_code" {
type = string
default = "/usr/share/edk2/ovmf/OVMF_CODE.fd"
}
variable "ovmf_vars" {
type = string
default = "/usr/share/edk2/ovmf/OVMF_VARS.fd"
}
source "qemu" "windows11" {
vm_name = var.vm_name
iso_url = "file://${var.win_iso_path}"
iso_checksum = var.win_iso_checksum
output_directory = var.output_directory
disk_size = var.disk_size
memory = var.memory
cpus = var.cpus
machine_type = "q35"
efi_firmware_code = var.ovmf_code
efi_firmware_vars = var.ovmf_vars
# VirtIO for minimal overhead; network also VirtIO
disk_interface = "virtio-scsi"
net_device = "virtio-net"
disk_cache = "unsafe"
disk_compression = true # deflate QCOW2 at build time; ~20-30% smaller image
qemuargs = [
# Software TPM 2.0 via swtpm
["-chardev", "socket,id=chrtpm,path=${var.swtpm_sock}"],
["-tpmdev", "emulator,id=tpm0,chardev=chrtpm"],
["-device", "tpm-tis,tpmdev=tpm0"],
# VirtIO drivers ISO (drive letter assigned dynamically; Autounattend searches D-G)
["-drive", "file=${var.virtio_iso_path},media=cdrom,readonly=on,if=ide"],
# Absolute-position mouse so installer clicks land correctly without X11
["-device", "usb-tablet"],
]
# Autounattend.xml served on a small virtual CD; Windows Setup finds it automatically
cd_files = ["./http/Autounattend.xml"]
cd_label = "AUTOUNATTEND"
communicator = "winrm"
winrm_username = "Administrator"
winrm_password = var.winrm_password
winrm_timeout = "3h"
winrm_insecure = true
winrm_use_ssl = false
headless = true
boot_wait = "5s"
boot_command = ["<spacebar>"]
shutdown_command = "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\""
shutdown_timeout = "15m"
}
build {
name = "windows11-lite"
sources = ["source.qemu.windows11"]
provisioner "powershell" {
elevated_user = "Administrator"
elevated_password = var.winrm_password
scripts = [
"./scripts/01-debloat-apps.ps1",
"./scripts/02-disable-telemetry.ps1",
"./scripts/03-disable-services.ps1",
"./scripts/04-performance.ps1",
"./scripts/05-cleanup.ps1",
]
}
}