{"id":29675817,"url":"https://github.com/oxidecomputer/windows-image-builder","last_synced_at":"2025-07-22T23:38:50.115Z","repository":{"id":222353332,"uuid":"553515088","full_name":"oxidecomputer/windows-image-builder","owner":"oxidecomputer","description":"Scripts and tooling to build Windows images suitable to use on an Oxide rack.","archived":false,"fork":false,"pushed_at":"2025-05-27T20:46:22.000Z","size":138,"stargazers_count":4,"open_issues_count":8,"forks_count":2,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-05-27T21:40:32.424Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxidecomputer.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-10-18T10:33:50.000Z","updated_at":"2025-05-27T20:46:27.000Z","dependencies_parsed_at":"2024-02-13T19:28:35.510Z","dependency_job_id":"5957e9df-7c8c-402d-9dd5-876423a9dedf","html_url":"https://github.com/oxidecomputer/windows-image-builder","commit_stats":null,"previous_names":["oxidecomputer/windows-image-builder"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/oxidecomputer/windows-image-builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fwindows-image-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fwindows-image-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fwindows-image-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fwindows-image-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxidecomputer","download_url":"https://codeload.github.com/oxidecomputer/windows-image-builder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidecomputer%2Fwindows-image-builder/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266591233,"owners_count":23953082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-22T23:38:49.099Z","updated_at":"2025-07-22T23:38:50.043Z","avatar_url":"https://github.com/oxidecomputer.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":":showtitle:\n:toc: left\n:toclevels: 2\n:icons: font\nifdef::env-github[]\n:tip-caption: :bulb:\n:note-caption: :information_source:\n:important-caption: :heavy_exclamation_mark:\n:caution-caption: :fire:\n:warning-caption: :warning:\nendif::[]\n\n= Windows Image Builder\n\nimage:https://img.shields.io/badge/platform-linux-green.svg[Linux]\nimage:https://img.shields.io/badge/status-active-blue.svg[Status]\n\nThis repository provides tooling and automation for building customized Windows Server disk images on modern Linux hosts, designed for upload and use with the Oxide platform.\n\nThis project has been designed to handle both Illumos and Linux as build platforms, however this README is focused on the Linux build process. The illumos build process is documented in a separate README.\n\nThe imgbuild.sh script is the main entry point for building Windows images on Linux. It orchestrates the entire process, from validating inputs to creating the final image.\n\ntoc::[]\n\n== Requirements\n\nTo build images successfully on Linux, the following prerequisites must be met:\n\n- **Operating System:** Ubuntu 20.04+ or related distributions (others may work but are not tested).\n- **Nested Virtualization:** Required. Your system must support `vmx` (Intel) or `svm` (AMD). On cloud VMs (e.g. AWS/GCP), this usually requires special instance types that expose nested virtualization.\n- **Privileges:** Depending on how your system is configured, scripts may require `sudo` access to create VMs and configure bridges. The script tries to check for this and will prompt if needed.\n- **Tools:** See `install_prerequisites.sh` to install:\n  - `qemu-kvm`, `virt-install`, `libvirt-daemon`, `libguestfs-tools`, `genisoimage`, `virtio-win`, etc.\n- **Internet Access:** Required to download updates and dependencies during install.\n\n== Quickstart\n\n=== 1. Install Dependencies\n\nRun:\n\n```bash\n./install_prerequisites.sh\n```\n\n=== 2. Configure Build Environment\n\nCreate and edit the environment file - these variables must be set in your `imgbuild.env` file before running the builder. Each controls a key part of the image creation process. A sample file is provided for reference and can be copied to start:\n\n```bash\ncp imgbuild.env.sample imgbuild.env\n```\n\n[cols=\"1,3\"]\n|===\n| Variable | Description\n\n| `WORK_DIR`\n| Path to a scratch workspace directory used for temporary files, log output, and intermediate image artifacts.\n\n| `OUTPUT_IMAGE`\n| Full path to the resulting raw disk image (`.img` or `.raw`) that will be produced by the build.\n\n| `WINDOWS_ISO`\n| Path to the Windows Server installation ISO (2019 or 2022 recommended).\n\n| `VIRTIO_ISO`\n| Path to the VirtIO driver ISO, used to inject storage and network drivers during Windows setup.\n\n| `UNATTEND_DIR`\n| Directory containing your `Autounattend.xml` file, which automates the Windows installation process.\n\n| `OVMF_PATH`\n| Path to the OVMF firmware file (e.g. `OVMF_CODE.fd`), used for UEFI boot with `qemu`. Common location: `/var/lib/libvirt/images/OVMF_CODE.fd`.\n\n|===\n\nNOTE: All paths must be absolute. Relative paths may not resolve correctly within virtualized builds.\n\n=== 3. Build the Image\n\n```bash\n./imgbuild.sh\n```\n\nThis drives the full flow using modular scripts in `imgbuild.d/`.\n\n== Submodule Breakdown\n\nEach stage in the `imgbuild.d/` directory is responsible for a key phase of the build:\n\n[cols=\"1,3\"]\n|===\n| Script | Description\n\n| `run-all`\n| Virtual module that runs all of the submodules in order.\n| `check_system.sh`\n| Verifies all required tools are present and working (`qemu`, `genisoimage`, `libguestfs`).\n\n| `validate_inputs.sh`\n| Ensures `imgbuild.env` is loaded, validates ISO paths, product keys, and environment assumptions.\n\n| `build_app.sh`\n| Compiles the Rust-based `wimsy` CLI tool, which assists with image metadata and preparation.\n\n| `build_image.sh`\n| The main action:\n  - Spins up a temporary VM using `virt-install`.\n  - Mounts the VirtIO ISO and the Windows ISO.\n  - Injects the provided `Autounattend.xml`.\n  - Waits for installation to complete.\n  - Converts and shrinks the resulting disk image.\n|===\n\nTo run a specific phase individually:\n\n```bash\n./imgbuild.d/build_image.sh phase\n```\n\n(Ensure your environment is sourced beforehand.)\n\n== Output Format\n\nThis process produces a `.raw` file in **raw disk image format**.\n\nIMPORTANT: The **Oxide rack only accepts raw disk images** for upload. Other formats like VMDK or QCOW2 will not work.\n\nYour output will be something like:\n\n```bash\noutput/windows-2022.raw\n```\n\nIMPORTANT: This image will be fairly large, roughly 13-15GB for most basic installations.\n\n== Download Links\n\n=== Official Windows ISOs\n\n- https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2022\n- https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2019\n\nUse the **ISO for installation and evaluation**; this is what we use for testing. Licensing is the responsibility of the user.\n\n=== VirtIO Driver ISO\n\n- https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md\n\nEnsure this is accessible at the path defined in your `.env` file.\n\n== Unattended Windows Installation\n\nTo fully automate Windows installation, this project uses Microsoft's Autounattend.xml system.\n\nExample configuration lives in:\n\n```bash\nunattend/Autounattend.xml\n```\n\nTo customize:\n\n- Set timezone, locale, keyboard, disk layout.\n- Add user credentials.\n- Configure product key injection.\n\nResources for learning and modifying:\n\n- Microsoft Docs: https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/\n- Answer file generator: https://www.windowsafg.com\n\n\n== Additional Image Customization Options\n\nThe wimsy tool runs an unattended Windows Setup session using the files found in the directory specified by the `--unattend-dir` argument. These files can be modified directly, or you can pass flags to alter behavior dynamically\n\n`--unattend-image-index`: Overrides the ImageIndex in the Autounattend.xml. This allows you to choose a specific Windows edition (e.g., Standard vs. Datacenter, with or without Desktop Experience).\n\n`--windows-version`: Rewrites driver paths in Autounattend.xml to match a specific Windows version, ensuring the correct VirtIO drivers are used.\n\n`--vga-console`: (Linux only) Starts QEMU with VGA output so you can watch or interact with the Windows installation via console.\n\nWARNING: You need to have a DISPLAY configured to use the VGA console option. This will silently fail if you set it and do not have a DISPLAY.\n\nNOTE: If you are using the `ingbuild.sh` script you will need to adjust the `build-image.sh` module. This module is responsible for calling wimsy and passing the correct arguments.\n\n== Default Image Configuration\n\nThe images created by wimsy and this build system are fully generalized:\nhttps://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/sysprep--generalize--a-windows-installation?view=windows-11[What is Generalization?]\n\nThey can be reused across multiple VMs. The default image includes:\n\nDrivers:\n\n- virtio-net for networking support\n- virtio-block for disk support\n\nUser Accounts:\n\n- The default Administrator account is disabled.\n- A local user named oxide is created and added to the Administrators group.\n- SSH keys from Oxide instance metadata are injected into oxide's authorized_keys.\n- No password is set by default. You can assign one later using:\n\n```cmd\nnet user oxide *\n```\n\nRemote Access:\n\n- EMS (Emergency Management Services) is enabled on COM1. Accessible via the Oxide console (Web or CLI).\n- OpenSSH is installed via PowerShell (Add-WindowsCapability) or from GitHub if needed.\n- RDP is enabled and firewall rules are pre-configured to allow port 3389.\n\nNOTE: Instance-level firewall rules must also allow access to port 3389 for RDP to function externally.\n\nIn-Guest Agents: Installs an Oxide-compatible fork of https://cloudbase-init.readthedocs.io/en/latest/[Cloudbase-Init]:\n\n- Metadata is read from the NoCloud config drive.\n- Hostname is set automatically to match the Oxide instance name.\n- SSH key injection is configured for the oxide user.\n- The system drive is auto-expanded to match the VM disk size at boot.\n\n== Finding the Correct Windows Image Index\n\nEach Windows ISO may contain multiple editions (e.g., Standard, Datacenter, Core). You must set the correct image index in Autounattend.xml.\n\nTo inspect available indexes:\n\n```bash\n# On a Debian/Ubuntu-based host\nsudo apt-get install wimtools p7zip-full\n7z e '-ir!install.wim' /path/to/windows.iso\nwiminfo install.wim\n```\n\nUse the /IMAGE/INDEX that corresponds to your desired edition.\n\n== Uploading to Oxide\n\nOnce the .raw file is generated, it can be uploaded to your Oxide silo as a custom image.\n\n=== Upload via CLI\n\n```bash\noxide disk import \\\n--project yourproject \\\n--path yourimage.raw \\\n--disk disk-name \\\n--disk-block-size 512 \\\n--description \"Windows on Oxide\" \\\n--snapshot win-2022 \\\n--image win-2022 \\\n--image-description \"Windows with Oxide\"\n--image-os windows --image-version 2022\n```\n\nCLI docs: https://oxide.computer/docs/cli/oxide_disk_import\n\n=== Upload via Web UI\n\n1. Visit your Oxide console.\n2. Navigate to the \"Images\" section.\n3. Click \"Import Disk\".\n4. Provide a name, description, os type, and version. Then add your .raw file and import the image.\n5. Now you can deploy an instance using this image.\n\nMore information: https://oxide.computer/docs/ui/image-import\n\n== illumos Support\n\nWhile this project has pivoted toward a Linux-first experience, full support for illumos-based systems continues.\n\nIf you're using an illumos host (such as SmartOS or OmniOS), please refer to the dedicated documentation:\n\n→ link:README.illumos.md[README.illumos.md – Illumos Instructions]\n\n== Roadmap\n\n- Integration with Oxide CLI for direct uploads\n- Add support for Windows 2016\n- Support for external app layer injection (e.g., Chocolatey or WinRM)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fwindows-image-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxidecomputer%2Fwindows-image-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidecomputer%2Fwindows-image-builder/lists"}