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 = [""] 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", ] } }