Create custom Windows BYOL images Stay organized with collections Save and categorize content based on your preferences.
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
.msuformat) to apply to the image.
Before you begin
- If you haven't already, set upauthentication. Authentication verifies your identity for access to Google Cloud services and APIs. To run code or samples from a local development environment, you can authenticate to Compute Engine by selecting one of the following options:
Select the tab for how you plan to use the samples on this page:
Console
When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.
gcloud
Install the Google Cloud CLI. After installation,initialize the Google Cloud CLI by running the following command:
gcloudinit
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
Note: If you installed the gcloud CLI previously, make sure you have the latest version by runninggcloud components update.- Set a default region and zone.
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:
- Creating a new disk.
- Extracting the Windows image (
install.wimfrom the installation media) to the disk. - Adding necessary drivers, configuring Windows Setup so that it runs unattended, and making the disk bootable.
- Booting from the new disk to run Windows Setup.
- Installing additional software including the Guest OS agent.
- 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:
- 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.createpermission.Learn how to grant roles. - 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.createpermission.Learn how to grant roles.
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
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.
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
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.
default.The next steps differ depending on whether you use Windows or Linux on your local computer:
Windows
- On your local computer, open a Windows PowerShell window.
Initialize a variable:
$PROJECT_ID = "
PROJECT_ID"where
PROJECT_IDis the project ID of theGoogle Cloud project that you created in the previous section.Initialize another variable so that it contains the project number of the project:
$PROJECT_NUMBER = gcloud projects describe $PROJECT_ID --format=value`(projectNumber`)
Linux
- On your local computer, open a terminal window.
Initialize a variable:
PROJECT_ID=
PROJECT_IDwhere
PROJECT_IDis the project ID of theGoogle Cloud project that you created in the previous section.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.
On your local computer, download required installation packages:
Create a new Cloud Storage bucket to store the installation files:
gcloud storage buckets create gs://$PROJECT_ID-media --project=$PROJECT_ID
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
Upload the PowerShell installation package:
gcloud storage cp
POWERSHELL_PACKAGEgs://$PROJECT_ID-media/PowerShell.msiwhere
POWERSHELL_PACKAGEis the path to the PowerShellinstallation package.Upload the .NET Framework installation package:
gcloud storage cp
DOTNET_PACKAGEgs://$PROJECT_ID-media/dotnet-sdk.exewhere
DOTNET_PACKAGEis the path to the NET Frameworkinstallation package.Upload the gcloud CLI installation package:
gcloud storage cp
CLOUDSDK_PACKAGEgs://$PROJECT_ID-media/GoogleCloudSDKInstaller.exewhere
CLOUDSDK_PACKAGEis the path to the gcloud CLIinstallation package.Upload the ISO file containing your Windows installation media:
gcloud storage cp
ISOgs://$PROJECT_ID-media/where
ISOis the name of the ISO file.Optionally, upload additional update packages:
gcloud storage cp
UPDATE_DIR/*.msu gs://$PROJECT_ID-media/updates/where
UPDATE_DIRis 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.
On your local computer, clone the Git repository containing the
daisyworkflowsfor building Windows images:git clone https://github.com/GoogleCloudPlatform/compute-image-tools.git
Switch to
windowsdirectory:cd compute-image-tools/daisy_workflows/image_build/windows/
In the
windowsdirectory, you find a selection of files with the suffix.wf.json. These files contain Daisy workflow definitions for commonly usedWindows versions:Windows version Workflow file Windows Server Core 2022 (64-bit) windows-server-2022-dc-core-uefi-byol.wf.jsonWindows Server 2019 (64-bit) windows-server-2019-dc-uefi-byol.wf.jsonWindows Server Core 2019 (64-bit) windows-server-2019-dc-core-uefi-byol.wf.jsonWindows Server 2016 (64-bit) windows-server-2016-dc-uefi-byol.wf.jsonWindows Server Core 2016 (64-bit) windows-server-2016-dc-core-uefi-byol.wf.jsonWindows 11 21H2 (64-bit) windows-11-21h2-ent-x64-uefi.wf.jsonWindows 11 22H2 (64-bit) windows-11-22h2-ent-x64-uefi.wf.jsonWindows 11 23H2 (64-bit) windows-11-23h2-ent-x64-uefi.wf.jsonWindows 10 21H2 (64-bit) windows-10-21h2-ent-x64-uefi.wf.jsonWindows 10 22H2 (64-bit) windows-10-22h2-ent-x64-uefi.wf.jsonOpen 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-NullReplace
ISOwith the local path to the ISO image.In the
windowsdirectory, create a new file namedcloudbuild.yamland 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-WORKFLOWReplace:
ISO: name of the ISO file on Cloud Storage.WORKFLOW: name of the workflow file that correspondsto the Windows version that you're using.
Varssection of the workflow file.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.
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
- Find out moreabout the daisy tool.
- Learn more aboutdaisy workflows for building images.
- Learn how tobring existing licenses to Compute Engine.
- Read aboutbest practices for working with image families.
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.