Create custom Windows BYOL images

Windows

To create a Windows VM on Google Cloud, you must use a VM image that has Windowsor Windows Server preinstalled. Google Cloud providespublic imagesfor commonly used versions of Windows Server, but these images are only suitable foron-demand licensing.To bring your own Windows license (BYOL), you must eitherimport an existing image, or you must build a custom image.

This guide describes how you can create a custom image by using the same toolsand processes that Google Cloud uses to create the public images.

To complete this guide, you need:

  • An ISO file containing the Windows or Windows Server installation media.
  • Optionally, one or more Windows update packages (in.msu format) to apply to the image.
Note: To test the image building process, you can use theWindows Server Evaluation media.

Before you begin

Understand the build process

To install Windows from scratch, a common approach is to boot a computer froma DVD or ISO file that contains the Windows installation files. Unlike some on-premiseshypervisors, Compute Engine does not let you boot from an ISO file.

To install Windows from scratch, you must therefore follow a different approachthat entails the following steps:

  1. Creating a new disk.
  2. Extracting the Windows image (install.wim from the installation media) to the disk.
  3. Adding necessary drivers, configuring Windows Setup so that it runs unattended, and making the disk bootable.
  4. Booting from the new disk to run Windows Setup.
  5. Installing additional software including the Guest OS agent.
  6. Creating an image from the disk.

Instead of performing these steps manually, this guide describes how you can useCloud Build, thedaisytool, and the reference workflows which areavailable on GitHubto automate the process.

daisy is anopen source command-line toolthat lets you execute workflows. Workflows are authored as JSON files and containa sequence of steps. Each such step describes a Compute Engine operation – forexample, creating a disk, or shutting down a VM instance. Daisy workflows aretherefore suitable to automate the steps required to build a Windows image from scratch.

The daisy workflows for building custom Windows images create two temporary VM instances.The first VM instance (prefixedbootstrap) performs the necessary steps to createa bootable disk. The second VM instance (prefixedinstall) runs Windows Setupand performs all the remaining steps.

Prepare the project for building images

To prevent the daisy tool from interfering with your existing VM instances orinfrastructure, create a dedicated project for building images:

    Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.

    In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.create permission.Learn how to grant roles.
    Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.

    Go to project selector

    Verify that billing is enabled for your Google Cloud project.

    Enable the Compute Engine API, Cloud Build API, and Cloud Storage API APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    Enable the APIs

    In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.create permission.Learn how to grant roles.
    Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.

    Go to project selector

    Verify that billing is enabled for your Google Cloud project.

    Enable the Compute Engine API, Cloud Build API, and Cloud Storage API APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    Enable the APIs

Note: The build process assumes that your project contains adefault network. If you'vedisabled the creation of default networksin your organization, you must manually create an auto-mode VPC network nameddefault.

The next steps differ depending on whether you use Windows or Linux on your local computer:

Windows

  1. On your local computer, open a Windows PowerShell window.
  2. Initialize a variable:

    $PROJECT_ID = "PROJECT_ID"

    wherePROJECT_ID is the project ID of theGoogle Cloud project that you created in the previous section.

  3. Initialize another variable so that it contains the project number of the project:

    $PROJECT_NUMBER = gcloud projects describe $PROJECT_ID --format=value`(projectNumber`)

Linux

  1. On your local computer, open a terminal window.
  2. Initialize a variable:

    PROJECT_ID=PROJECT_ID

    wherePROJECT_ID is the project ID of theGoogle Cloud project that you created in the previous section.

  3. Initialize another variable so that it contains the project number of the project:

    PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format=value\(projectNumber\)`

Upload installation files

You now collect all the installation files required for the custom image and uploadthem to a Cloud Storage bucket. By storing the files in a Cloud Storage bucket,you ensure that the files are accessible bydaisy and by the temporary VM instancesthatdaisy uses to build the image.

  1. On your local computer, download required installation packages:

  2. Create a new Cloud Storage bucket to store the installation files:

    gcloud storage buckets create gs://$PROJECT_ID-media --project=$PROJECT_ID
  3. Grant theStorage Object Viewerrole to Cloud Build so that it can read the installation files:

    gcloud storage buckets add-iam-policy-binding gs://$PROJECT_ID-media --member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com --role=roles/storage.objectViewer
  4. Upload the PowerShell installation package:

    gcloud storage cpPOWERSHELL_PACKAGE gs://$PROJECT_ID-media/PowerShell.msi

    wherePOWERSHELL_PACKAGE is the path to the PowerShellinstallation package.

  5. Upload the .NET Framework installation package:

    gcloud storage cpDOTNET_PACKAGE gs://$PROJECT_ID-media/dotnet-sdk.exe

    whereDOTNET_PACKAGE is the path to the NET Frameworkinstallation package.

  6. Upload the gcloud CLI installation package:

    gcloud storage cpCLOUDSDK_PACKAGE gs://$PROJECT_ID-media/GoogleCloudSDKInstaller.exe

    whereCLOUDSDK_PACKAGE is the path to the gcloud CLIinstallation package.

  7. Upload the ISO file containing your Windows installation media:

    gcloud storage cpISO gs://$PROJECT_ID-media/

    whereISO is the name of the ISO file.

  8. Optionally, upload additional update packages:

    gcloud storage cpUPDATE_DIR/*.msu gs://$PROJECT_ID-media/updates/

    whereUPDATE_DIR is the directory containing the update packages.

You are now ready to build the custom image.

Build the image

Executing thedaisy workflow to build a custom image takes up to four hours.Instead of runningdaisy locally, you now create a Cloud Build configurationso that you can let Cloud Build execute the workflow in the background.

  1. On your local computer, clone the Git repository containing thedaisy workflowsfor building Windows images:

    git clone https://github.com/GoogleCloudPlatform/compute-image-tools.git
  2. Switch towindows directory:

    cd compute-image-tools/daisy_workflows/image_build/windows/
  3. In thewindows directory, you find a selection of files with the suffix.wf.json. These files contain Daisy workflow definitions for commonly usedWindows versions:

    Windows versionWorkflow file
    Windows Server Core 2022 (64-bit)windows-server-2022-dc-core-uefi-byol.wf.json
    Windows Server 2019 (64-bit)windows-server-2019-dc-uefi-byol.wf.json
    Windows Server Core 2019 (64-bit)windows-server-2019-dc-core-uefi-byol.wf.json
    Windows Server 2016 (64-bit)windows-server-2016-dc-uefi-byol.wf.json
    Windows Server Core 2016 (64-bit)windows-server-2016-dc-core-uefi-byol.wf.json
    Windows 11 21H2 (64-bit)windows-11-21h2-ent-x64-uefi.wf.json
    Windows 11 22H2 (64-bit)windows-11-22h2-ent-x64-uefi.wf.json
    Windows 11 23H2 (64-bit)windows-11-23h2-ent-x64-uefi.wf.json
    Windows 10 21H2 (64-bit)windows-10-21h2-ent-x64-uefi.wf.json
    Windows 10 22H2 (64-bit)windows-10-22h2-ent-x64-uefi.wf.json

    Open the workflow file that most closely matches the Windows version thatyou want to install. If necessary, change the Windows edition (edition) andlicense key (product_key) settings in the workflow files so that they matchyour installation media.

    If you are unsure about the correct edition name, open an elevated PowerShellprompt and run the following commands to list all editions supported by yourinstallation media:

    $IsoFile = "ISO"$Mount = Mount-DiskImage -ImagePath (Resolve-Path $IsoFile)$DriveLetter = ($Mount | Get-Volume).DriveLetterGet-WindowsImage -ImagePath "$($DriveLetter):\sources\install.wim" | select ImageNameDismount-DiskImage -InputObject $Mount | Out-Null

    ReplaceISO with the local path to the ISO image.

  4. In thewindows directory, create a new file namedcloudbuild.yaml and pastethe following code:

    timeout: 14400s  # 4 hour timeout for entire buildsteps:- name: 'gcr.io/compute-image-tools/daisy'  timeout: 14400s  # 4 hour timeout for build step  waitFor: ['-']  args:    - -project=$PROJECT_ID    - -zone=us-central1-a    - -var:updates=gs://$PROJECT_ID-media/updates/    - -var:pwsh=gs://$PROJECT_ID-media/PowerShell.msi    - -var:dotnet48=gs://$PROJECT_ID-media/dotnet-sdk.exe    - -var:cloudsdk=gs://$PROJECT_ID-media/GoogleCloudSDKInstaller.exe    - -var:media=gs://$PROJECT_ID-media/ISO    -WORKFLOW

    Replace:

    • ISO: name of the ISO file on Cloud Storage.
    • WORKFLOW: name of the workflow file that correspondsto the Windows version that you're using.
    Note: Some workflows support additional, optional parameters to customize thebuild process. You can find the complete list of parameters in theVarssection of the workflow file.
  5. Submit the build to Cloud Build:

    gcloud builds submit --project $PROJECT_ID --async

    The build takes around up to four hours to complete. You can track the status of thebuild in the Google Cloud console underCloud Build > History.

    Cloud Build History

Use the custom image

After the build has completed, you can find the custom BYOL image in theGoogle Cloud console underCompute Engine > Images.

To help differentiate between multiple versions of the same image, the buildprocess embeds a timestamp into the image name, for examplewindows-server-2019-dc-v1613488342.In addition, the process associates the image with a customimage family,for examplewindows-server-2019.

To create a VM instance that uses the custom BYOL image, you mustprovision the VM instance on a sole-tenant node.

Note: The image build process does not configure a KMS server. If you're using avolume licensed copy of Windows Server, you mustconfigure a KMS server before you can activate Windows Server.

Troubleshooting

If you suspect that the build process failed or is not progressing, use thefollowing approaches to diagnose the situation:

  • Verify that you've uploaded the right installation packages and ISO file.
  • Verify that you selected a workflow that matches the Windows version of the ISO file.
  • Review thebuild log in Cloud Buildand check whether there are any error messages.
  • If the build seems stuck, review theserial port outputof the VM instance created by the build and check for error messages.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.