Repository navigation
Build a Windows custom AMI from an ISO (Windows 11) and make it usable from spore.host tools #83
Copy link
Copy link
Closed
Description
Goal
A documented, repeatable process (Packer-based) to take an existing Windows ISO and produce an AMI that spore.host tools (spawn launch --ami …, --os windows) can use directly. Motivated by Windows support (#55 Phase 1 shipped) — the stock AWS Windows Server AMIs work, but we also want to bring our own client image (Windows 11) for desktop/eval workloads.
Concrete starting input
Windows 11 25H2 Enterprise Evaluation ISO already on hand:
/Volumes/External HD/26200.6584.250915-1905.25h2_ge_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso
(~7.09 GB, CLIENTENTERPRISEEVAL, x64, en-us)
The core challenge
EC2 does not boot arbitrary ISOs. Turning a Windows client ISO into an AMI requires one of:
- VM Import/Export path (most likely): build the image locally/in a VM from the ISO (e.g. Packer with the
virtualbox-iso/qemubuilder + anAutounattend.xmlfor unattended install + EC2 bootstrap), export to VMDK/OVA, upload to S3, thenaws ec2 import-image→ AMI. Requires thevmimportIAM role/service + an S3 bucket, and the guest must have the EC2 drivers + EC2Launch v2 + AWS PV/ENA/NVMe drivers + SSM agent installed or the imported instance won't boot/network/be manageable. - EC2 build-on-instance path: less applicable for a client ISO (no base client AMI), so (1) is the realistic route for Windows 11.
Note: Windows client licensing on EC2 is special — client OSes generally require Dedicated Hosts / BYOL; the Enterprise Eval edition has a time-limited license. Document the licensing/tenancy implications clearly.
Scope of this issue
- A
infra/amis/windows/(or docs/) runbook + Packer template(s) that:- take an ISO path as input, run an unattended Windows install via
Autounattend.xml, - inject the required AWS guest components (EC2Launch v2, AWS NVMe/ENA/PV drivers, SSM agent, OpenSSH), sysprep,
- export +
import-imageto an AMI, tag it for spore.host discovery.
- take an ISO path as input, run an unattended Windows install via
- Document prerequisites:
vmimportrole, S3 bucket, local hypervisor (VirtualBox/QEMU) or an EC2 metal builder, Packer plugins. - Document how to use the result:
spawn launch --ami <id> --os windows --ttl …; note the--osflag exists precisely so a custom AMI whosePlatformmetadata is unset is still treated as Windows ([exploration] Windows AMI support — what's needed for connection & monitoring? #55 Phase 1). Add the AMI to any catalog ([audit] Dead code: delete pkg/streaming (entirely unused, ~71 funcs across tcp/transport/zmq) #286-style) if applicable. - Cover Dedicated Host / BYOL requirement for Windows client and the eval-license expiry.
Acceptance
- Running the documented process against the ISO above yields an AMI that
spawn launch --ami <id> --os windows --ttl 4hboots, SSM registers, andspawn connectreaches (RDP creds + SSM, per [exploration] Windows AMI support — what's needed for connection & monitoring? #55 Phase 1).
Related
- [exploration] Windows AMI support — what's needed for connection & monitoring? #55 (Windows support;
--osflag + spawn:os tag already in place) - Support OS choice beyond AL2023 — Ubuntu 24.04 + customer AMI #54 (custom/Ubuntu AMI support — same "bring your own AMI" theme)
- Windows spored — cross-platform lifecycle agent as a Windows Service #77 (Windows spored — once it exists, bake it into the custom AMI build)
- [audit] Dead code: delete pkg/streaming (entirely unused, ~71 funcs across tcp/transport/zmq) #286 (AMI catalog), if the result should be cataloged
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
amis(windows): make qemu/macOS the active build path + machine-valida…
amis(windows): boot via cd_files answer media + UEFI-shell fallback (#83
feat(launch): --nested-virtualization flag with instance-type validat…
amis(windows): document the EC2 nested-virtualization build path (#83)
amis(windows): boot the installer headlessly via no-prompt ISO remast…
image: pivot Windows AMI build to EC2 Image Builder import-disk-image (…
image: add `spawn image verify` to pre-check a Windows ISO (#83)
image: auto-manage the ISO staging bucket (#83)
image: idempotent ISO upload + auto-delete staged ISO after build (#83)
image: async-by-default import with --wait[=min] + `image status` (#83)
image: fix SLR execution-role ARN; add `spawn ami delete` + richer im…
image: handle Ctrl-C during --wait as a clean detach (#83)
ami: smart snapshot handling on delete + snapshot visibility (#83)
ami: rename snapshots column header 'SHARED WITH' -> 'SHARED' (#83)
scttfrdmn commentedon Jun 10, 2026
Approach pivoted: EC2 Image Builder (not qemu/Packer)
This issue originally scoped a hand-rolled qemu/Packer build (unattended install
→
ec2 import-image). During implementation we found AWS shipped a managedEC2 Image Builder
import-disk-imageworkflow (Jan 2025) that does the wholeconversion — install, AWS drivers, EC2Launch v2, SSM agent, Defender, time sync,
AMI registration — so the qemu pipeline was retired in favor of it. (The qemu
detour did solve a real problem worth remembering: the Windows ISO's UEFI El
Torito boot image is the "Press any key to boot from CD" shim, unwinnable
headless; the fix was remastering to
efisys_noprompt.bin. Kept in git history +project memory in case an unsupported edition ever needs a non-Image-Builder path.)
What shipped (PR #90)
spawn image import— Windows 11 ISO → AMI via Image Builder. Self-provisionsthe IAM execution/instance roles + infrastructure configuration (no CloudFormation),
managed S3 staging bucket (
spawn-iso-import-<acct>-<region>), multipart upload,idempotent (skips re-upload by size), async-by-default with
--wait[=min](timeout/Ctrl-C → clean detach, non-zero exit), auto-tags
spawn:os=windows+spawn:source=iso-import+spawn:arch, auto-deletes the staged ISO/bucketafter build (
--keep-isoopts out).spawn image verify <iso>— local, no-AWS edition check (pkg/winiso): readsinstall.wim, lists editions + the right
--image-index, ACCEPTED/REJECTED verdict.spawn image status <arn>— poll a detached build.spawn ami delete— deregister + delete backing snapshots (retains snapshotsshared by other AMIs) + delete the Image Builder image resource (only if the AMI
came from one).
spawn ami snapshots <id>+ a SNAPS column onami list.Proven end-to-end
Real run in the dev account: Win11 Enterprise business-editions ISO (M365),
--image-index 3→ built a real AMI (Windows BYOL, UEFI, TPM 2.0), booted clean(status checks ok). Terminated + leak-checked; account left pristine.
Constraints documented
consumer ISOs are rejected —
spawn image verifycatches this before a paid build.Remaining (separate follow-up, not blocking)
launch-path concern on imported client images, not an import defect (the AMI
boots fine). Worth a dedicated issue.
Closing when PR #90 merges.
scttfrdmn commentedon Jun 10, 2026
Follow-up filed: #95 (SSM/spored not coming online on a launched imported Windows client AMI — a launch-path concern, not an import defect).
test(e2e): classify `image` command in the Tier 0 coverage gate (#83)
feat(image): spawn image import — Windows ISO→AMI via EC2 Image Build…