Skip to content

Build a Windows custom AMI from an ISO (Windows 11) and make it usable from spore.host tools #83

Closed

Description

@scttfrdmn

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:

  1. VM Import/Export path (most likely): build the image locally/in a VM from the ISO (e.g. Packer with the virtualbox-iso/qemu builder + an Autounattend.xml for unattended install + EC2 bootstrap), export to VMDK/OVA, upload to S3, then aws ec2 import-image → AMI. Requires the vmimport IAM 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.
  2. 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-image to an AMI, tag it for spore.host discovery.
  • Document prerequisites: vmimport role, 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 --os flag exists precisely so a custom AMI whose Platform metadata 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

Related

Activity

  1. scttfrdmn commented on Jun 10, 2026

    @scttfrdmn
    ContributorAuthor

    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 managed
    EC2 Image Builder import-disk-image workflow (Jan 2025) that does the whole
    conversion — 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-provisions
      the 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/bucket
      after build (--keep-iso opts out).
    • spawn image verify <iso> — local, no-AWS edition check (pkg/winiso): reads
      install.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 snapshots
      shared by other AMIs) + delete the Image Builder image resource (only if the AMI
      came from one). spawn ami snapshots <id> + a SNAPS column on ami list.
    • Bonus: fixed cobra double-printing errors + dumping usage on runtime failures.

    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

    • Supported: Win11 Enterprise 23H2/24H2/25H2 x64 (non-Eval). Eval/MCT/LTSC and
      consumer ISOs are rejected — spawn image verify catches this before a paid build.
    • BYOL; us-east-1 needs no NAT, other regions do.

    Remaining (separate follow-up, not blocking)

    • SSM/spored didn't register on a launched client AMI within ~12 min — a spawn
      launch-path concern on imported client images, not an import defect (the AMI
      boots fine). Worth a dedicated issue.
    • Full shared-snapshot e2e test blocked on substrate#322.

    Closing when PR #90 merges.

  2. scttfrdmn commented on Jun 10, 2026

    @scttfrdmn
    ContributorAuthor

    Follow-up filed: #95 (SSM/spored not coming online on a launched imported Windows client AMI — a launch-path concern, not an import defect).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions