Create custom Windows Server images Stay organized with collections Save and categorize content based on your preferences.
You can create customized Windows Server images from existing Compute EngineWindows Server images. Use these custom images to create instances with bootdisks that are the same as your existing instances.
These custom images are useful for saving the operating system configuration ofyour existing instances and reusing the same configuration to create otherinstances.
The following tasks are not covered in this section:
- Create a VM from a public image or a custom image; instead seeCreating a new Windows instance.
- Schedule a backup of your persistent disks; instead seepersistent disk snapshots.
- Import Windows Server or SQL Server systems; instead use theVM migration service.
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.
Go
To use the Go samples on this page in a local development environment, install and initialize the gcloud CLI, and then set up Application Default Credentials with your user credentials.
Install the Google Cloud CLI.
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.If you're using a local shell, then create local authentication credentials for your user account:
gcloudauthapplication-defaultlogin
You don't need to do this if you're using Cloud Shell.
If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.
For more information, see Set up authentication for a local development environment.
Java
To use the Java samples on this page in a local development environment, install and initialize the gcloud CLI, and then set up Application Default Credentials with your user credentials.
Install the Google Cloud CLI.
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.If you're using a local shell, then create local authentication credentials for your user account:
gcloudauthapplication-defaultlogin
You don't need to do this if you're using Cloud Shell.
If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.
For more information, see Set up authentication for a local development environment.
Node.js
To use the Node.js samples on this page in a local development environment, install and initialize the gcloud CLI, and then set up Application Default Credentials with your user credentials.
Install the Google Cloud CLI.
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.If you're using a local shell, then create local authentication credentials for your user account:
gcloudauthapplication-defaultlogin
You don't need to do this if you're using Cloud Shell.
If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.
For more information, see Set up authentication for a local development environment.
Python
To use the Python samples on this page in a local development environment, install and initialize the gcloud CLI, and then set up Application Default Credentials with your user credentials.
Install the Google Cloud CLI.
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.If you're using a local shell, then create local authentication credentials for your user account:
gcloudauthapplication-defaultlogin
You don't need to do this if you're using Cloud Shell.
If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.
For more information, see Set up authentication for a local development environment.
REST
To use the REST API samples on this page in a local development environment, you use the credentials you provide to the gcloud CLI.
Install the Google Cloud CLI.
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.For more information, seeAuthenticate for using REST in the Google Cloud authentication documentation.
Prepare to create a Windows Server image
Before you create the image, runGCESysprep on the instance to prepare it forthe image creation process.
GCESysprep prepares an instance for becoming a Compute Engine image bycompleting the following steps:
- Disables the
GCEStartupscheduled task. - Deletes all files from temp folder location.
- Clears all Windows event logs.
- Runs sysprep.exe /generalize /oobe /quit /unattend
- Configures
instance_setup.ps1to run on the first boot of the VM instance. - Deletes the RDP Certificate.
- Removes the stored list of persistent disks.
- Enables RDP and WinRM firewall rules.
- Disables the Google OS Config service.
- Shuts down the instance.
GCESysprep operations are logged to the Windows event log and serial port 1.Sysprep writes to multiplelog files.
GCESysprep as any enabled accounts and credentialswill be present in the new image.How to create a Compute Engine image usingGCESysprep:
Run
GCESysprepwith administrative rights.GCESysprep
Specify an image location
When creating a custom image, you can specify the image'sCloud Storage location, excludingdual-region locations. By specifying the image storage location, youcan meet your regulatory and compliance requirements for data locality as wellas your high availability needs by ensuring redundancy across regions.
The storage location feature is optional. If you don't select a location,Compute Engine will store your image in the multi-region closest to theimage source. You can create custom images from source disks, images, snapshots,or images stored in Cloud Storage. You can use these images to createnew VM instances.
All of your existing images prior to this feature launch remain where they are.The only change is that you can view the image location of all your images.If you have an existing image you want to move, you must recreate it in theselected location.
Create a Windows image
You can create disk images from the following sources:
- A persistent disk, even while that disk is attached to an instance
- A snapshot of a persistent disk
- Another image in your project
- An image that is shared from another project
Animported imagestored in Cloud Storage
Console
- In the Google Cloud console, go to theCreate a new image page.
- Specify the imageName.
- Choose aSource disk with a Windows operating system from which youwant to create an image.
- Specify theLocation to store the image. Choose an imagelocation from theBased on source disk location (default)drop-down menu. For example, specify
usto store the image in theusmulti-region, orus-central1to store it in theus-central1region.If you don't make a selection, Compute Engine will store theimage in the multi-region closest to your image's source location. - Specify the properties for your image. For example, you canspecify an image family name for your image to organize this image aspart of animage family.
- ClickCreate.
gcloud
Use thegcloud compute withimages create, and providethe source persistent disk from which you want to create an image.Optionally, include the--force flag to create the image even if it isattached to a running instance.
gcloud compute images create example-image --source-diskDISK_NAME \ --source-disk-zoneZONE \ --storage-locationLOCATION \ [--force]Replace the following:
DISK_NAME: the name of the source disk to create the image from.ZONE: the zone of the disk.LOCATION: an optional flag that lets you designate theregion or multi-region where your image is going to be stored.For example, specifyusto store the image in theusmulti-region, orus-central1to store it in theus-central1region.If you don't make a selection, Compute Engine stores theimage in the multi-region closest to your image's source location.--force: an optional flag that creates the image even if the disk isattached to a running instance. This option mightcompromise the integrity of your image. Stop the instance before youcreate the image if possible.
When you run this command,gcloud compute creates a new image based onthe persistent disk you provided and adds it to your collection. You canconfirm that your image was successfully created by running:
gcloud compute images listGo
Before trying this sample, follow theGo setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineGo API reference documentation.
To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.
import("context""fmt""io""strings"compute"cloud.google.com/go/compute/apiv1"computepb"cloud.google.com/go/compute/apiv1/computepb""google.golang.org/protobuf/proto")// createWindowsOSImage creates a new Windows image from the specified source disk.funccreateWindowsOSImage(wio.Writer,projectID,zone,sourceDiskName,imageName,storageLocationstring,forceCreatebool,)error{// projectID := "your_project_id"// zone := "europe-central2-b"// sourceDiskName := "your_source_disk_name"// imageName := "your_image_name"// storageLocation := "eu"// forceCreate := falsectx:=context.Background()instancesClient,err:=compute.NewInstancesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewInstancesRESTClient: %w",err)}deferinstancesClient.Close()imagesClient,err:=compute.NewImagesRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewImagesRESTClient: %w",err)}deferimagesClient.Close()disksClient,err:=compute.NewDisksRESTClient(ctx)iferr!=nil{returnfmt.Errorf("NewDisksRESTClient: %w",err)}deferdisksClient.Close()// Getting instances where source disk is attacheddiskRequest:=&computepb.GetDiskRequest{Project:projectID,Zone:zone,Disk:sourceDiskName,}sourceDisk,err:=disksClient.Get(ctx,diskRequest)iferr!=nil{returnfmt.Errorf("unable to get disk: %w",err)}// Сhecking whether the instances is stoppedfor_,fullInstanceName:=rangesourceDisk.GetUsers(){parsedName:=strings.Split(fullInstanceName,"/")l:=len(parsedName)ifl <5{returnfmt.Errorf("API returned instance name with unexpected format",)}instanceReq:=&computepb.GetInstanceRequest{Project:parsedName[l-5],Zone:parsedName[l-3],Instance:parsedName[l-1],}instance,err:=instancesClient.Get(ctx,instanceReq)iferr!=nil{returnfmt.Errorf("unable to get instance: %w",err)}ifinstance.GetStatus()!="TERMINATED" &&instance.GetStatus()!="STOPPED"{if!forceCreate{returnfmt.Errorf("instance %s should be stopped. "+"Please stop the instance using "+"GCESysprep command or set forceCreate parameter to true "+"(not recommended). More information here: "+"https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api",parsedName[l-1],)}}}ifforceCreate{fmt.Fprintf(w,"Warning: ForceCreate option compromise the integrity of your image. "+"Stop the instance before you create the image if possible.",)}req:=&computepb.InsertImageRequest{Project:projectID,ForceCreate:&forceCreate,ImageResource:&computepb.Image{Name:proto.String(imageName),SourceDisk:proto.String(fmt.Sprintf("zones/%s/disks/%s",zone,sourceDiskName)),StorageLocations:[]string{storageLocation},},}op,err:=imagesClient.Insert(ctx,req)iferr!=nil{returnfmt.Errorf("unable to create image: %w",err)}iferr=op.Wait(ctx);err!=nil{returnfmt.Errorf("unable to wait for the operation: %w",err)}fmt.Fprintf(w,"Image created\n")returnnil}Java
Before trying this sample, follow theJava setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineJava API reference documentation.
To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.
importcom.google.cloud.compute.v1.Disk;importcom.google.cloud.compute.v1.DisksClient;importcom.google.cloud.compute.v1.Image;importcom.google.cloud.compute.v1.ImagesClient;importcom.google.cloud.compute.v1.InsertImageRequest;importcom.google.cloud.compute.v1.Instance;importcom.google.cloud.compute.v1.InstancesClient;importcom.google.cloud.compute.v1.Operation;importjava.io.IOException;importjava.util.Arrays;importjava.util.HashMap;importjava.util.Map;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;importjava.util.concurrent.TimeoutException;publicclassCreateImage{publicstaticvoidmain(String[]args)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// TODO(developer): Replace these variables before running the sample.// Project ID or project number of the Cloud project you use.Stringproject="your-project-id";// Zone of the disk you copy from.Stringzone="europe-central2-b";// Name of the source disk you copy from.StringsourceDiskName="source-disk-name";// Name of the image you want to create.StringimageName="your-image-name";// Storage location for the image. If the value is undefined,// function will store the image in the multi-region closest to your image's source location.StringstorageLocation="eu";// Create the image even if the source disk is attached to a running instance.booleanforceCreate=false;createImage(project,zone,sourceDiskName,imageName,storageLocation,forceCreate);}// Creates a new disk image from the specified source disk.publicstaticvoidcreateImage(Stringproject,Stringzone,StringsourceDiskName,StringimageName,StringstorageLocation,booleanforceCreate)throwsIOException,ExecutionException,InterruptedException,TimeoutException{// Initialize client that will be used to send requests. This client only needs to be created// once, and can be reused for multiple requests. After completing all of your requests, call// the `client.close()` method on the client to safely// clean up any remaining background resources.try(ImagesClientimagesClient=ImagesClient.create();InstancesClientinstancesClient=InstancesClient.create();DisksClientdisksClient=DisksClient.create()){Diskdisk=disksClient.get(project,zone,sourceDiskName);// Getting instances where source disk is attached.for(StringfullInstanceName:disk.getUsersList()){Map<String,String>instanceInfo=parseInstanceName(fullInstanceName);Instanceinstance=instancesClient.get(instanceInfo.get("instanceProjectId"),instanceInfo.get("instanceZone"),instanceInfo.get("instanceName"));// Сheck whether the instances are stopped.if(!Arrays.asList("TERMINATED","STOPPED").contains(instance.getStatus()) &&!forceCreate){thrownewIllegalStateException(String.format("Instance %s should be stopped. For Windows instances please stop the instance "+"using GCESysprep command. For Linux instances just shut it down normally."+" You can suppress this error and create an image of the disk by setting "+"'forceCreate' parameter to true (not recommended). "+"More information here: "+"* https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api"+"* https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image",instanceInfo.get("instanceName")));}}if(forceCreate){System.out.println("Warning: forceCreate option compromise the integrity of your image. "+"Stop the instance before you create the image if possible.");}// Create Image.IImageimage=IImagenewBuilder().setName(imageName).setSourceDisk(String.format("/zones/%s/disks/%s",zone,sourceDiskName)).addStorageLocations(storageLocation.isEmpty()?"":storageLocation).build();IInsertImageRequestinsertImageRequest=IInsertImageRequestnewBuilder().setProject(project).ssetForceCreateforceCreate).setImageResource(image).build();OOperationresponse=imagesClient.insertAsync(insertImageRequest).get(5,TimeUnit.MINUTES);if(rresponse.hasError(){System.out.println("Image creation failed ! ! "+response);return;}System.out.println("Image created.");}}publicstaticMap<String,String>parseInstanceName(Stringname){String[]parsedName=name.split("/");intsplitLength=parsedName.length;if(splitLength <5){thrownewIllegalArgumentException("Provide correct instance name in the following format: "+"https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME");}returnnewHashMap<>(){{put("instanceName",parsedName[splitLength-1]);put("instanceZone",parsedName[splitLength-3]);put("instanceProjectId",parsedName[splitLength-5]);}};}}Node.js
Node.js
Before trying this sample, follow theNode.js setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EngineNode.js API reference documentation.
To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.
/** * TODO(developer): Uncomment and replace these variables before running the sample. */// const projectId = 'YOUR_PROJECT_ID';// const zone = 'europe-central2-b';// const sourceDiskName = 'YOUR_SOURCE_DISK_NAME';// const imageName = 'YOUR_IMAGE_NAME';// const storageLocation = 'eu';// const forceCreate = false;constcompute=require('@google-cloud/compute');functionparseInstanceName(name){constparsedName=name.split('/');constl=parsedName.length;if(parsedName.legth <5){thrownewError('Provide correct instance name in the following format: https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME');}return[parsedName[l-1],parsedName[l-3],parsedName[l-5]];}asyncfunctioncreateWindowsOSImage(){constimagesClient=newcompute.ImagesClient();constinstancesClient=newcompute.InstancesClient();constdisksClient=newcompute.DisksClient();// Getting instances where source disk is attachedconst[sourceDisk]=awaitdisksClient.get({project:projectId,zone,disk:sourceDiskName,});// Сhecking whether the instances is stoppedfor(constfullInstanceNameofsourceDisk.users){const[instanceName,instanceZone,instanceProjectId]=parseInstanceName(fullInstanceName);const[instance]=awaitinstancesClient.get({project:instanceProjectId,zone:instanceZone,instance:instanceName,});if(!['TERMINATED','STOPPED'].includes(instance.status)&&!forceCreate){thrownewError(`Instance${instanceName} should be stopped. Please stop the instance using GCESysprep command or set forceCreate parameter to true (not recommended). More information here: https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api.`);}}if(forceCreate){console.warn('Warning: forceCreate option compromise the integrity of your image. Stop the instance before you create the image if possible.');}const[response]=awaitimagesClient.insert({project:projectId,forceCreate,imageResource:{name:imageName,sourceDisk:`/zones/${zone}/disks/${sourceDiskName}`,storageLocations:storageLocation?[storageLocation]:[],},});letoperation=response.latestResponse;constoperationsClient=newccompute.GlobalOperationsClient);// Wait for the create operation to complete.while(operation.status!=='DONE'){[operation]=awaitoperationsClient.wait({operation:operation.name,project:projectId,});}console.log('Image created.');}createWindowsOSImage();Python
Python
Before trying this sample, follow thePython setup instructions in theCompute Engine quickstart using client libraries. For more information, see theCompute EnginePython API reference documentation.
To authenticate to Compute Engine, set up Application Default Credentials. For more information, seeSet up authentication for a local development environment.
from__future__importannotationsimportsysfromtypingimportAnyimportwarningsfromgoogle.api_core.extended_operationimportExtendedOperationfromgoogle.cloudimportcompute_v1defwait_for_extended_operation(operation:ExtendedOperation,verbose_name:str="operation",timeout:int=300)->Any:""" Waits for the extended (long-running) operation to complete. If the operation is successful, it will return its result. If the operation ends with an error, an exception will be raised. If there were any warnings during the execution of the operation they will be printed to sys.stderr. Args: operation: a long-running operation you want to wait on. verbose_name: (optional) a more verbose name of the operation, used only during error and warning reporting. timeout: how long (in seconds) to wait for operation to finish. If None, wait indefinitely. Returns: Whatever the operation.result() returns. Raises: This method will raise the exception received from `operation.exception()` or RuntimeError if there is no exception set, but there is an `error_code` set for the `operation`. In case of an operation taking longer than `timeout` seconds to complete, a `concurrent.futures.TimeoutError` will be raised. """result=operation.result(timeout=timeout)ifoperation.error_code:print(f"Error during{verbose_name}: [Code:{operation.error_code}]:{operation.error_message}",file=sys.stderr,flush=True,)print(f"Operation ID:{operation.name}",file=sys.stderr,flush=True)raiseoperation.exception()orRuntimeError(operation.error_message)ifoperation.warnings:print(f"Warnings during{verbose_name}:\n",file=sys.stderr,flush=True)forwarninginoperation.warnings:print(f" -{warning.code}:{warning.message}",file=sys.stderr,flush=True)returnresultSTOPPED_MACHINE_STATUS=(compute_v1.Instance.Status.TERMINATED.name,compute_v1.Instance.Status.STOPPED.name,)defcreate_image_from_disk(project_id:str,zone:str,source_disk_name:str,image_name:str,storage_location:str|None=None,force_create:bool=False,)->compute_v1.Image:""" Creates a new disk image. Args: project_id: project ID or project number of the Cloud project you use. zone: zone of the disk you copy from. source_disk_name: name of the source disk you copy from. image_name: name of the image you want to create. storage_location: storage location for the image. If the value is undefined, function will store the image in the multi-region closest to your image's source location. force_create: create the image even if the source disk is attached to a running instance. Returns: An Image object. """image_client=compute_v1.ImagesClient()disk_client=compute_v1.DisksClient()instance_client=compute_v1.InstancesClient()# Get source diskdisk=disk_client.get(project=project_id,zone=zone,disk=source_disk_name)fordisk_userindisk.users:instance_name=disk_user.split("/")[-1]instance=instance_client.get(project=project_id,zone=zone,instance=instance_name)ifinstance.statusinSTOPPED_MACHINE_STATUS:continueifnotforce_create:raiseRuntimeError(f"Instance{disk_user} should be stopped. For Windows instances please "f"stop the instance using `GCESysprep` command. For Linux instances just "f"shut it down normally. You can supress this error and create an image of"f"the disk by setting `force_create` parameter to true (not recommended).\n"f"More information here:\n"f" * https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api\n"f" * https://cloud.google.com/compute/docs/images/create-delete-deprecate-private-images#prepare_instance_for_image")else:warnings.warn(f"Warning: The `force_create` option may compromise the integrity of your image. "f"Stop the{disk_user} instance before you create the image if possible.")# Create imageimage=compute_v1.Image()image.source_disk=disk.self_linkimage.name=image_nameifstorage_location:image.storage_locations=[storage_location]operation=image_client.insert(project=project_id,image_resource=image)wait_for_extended_operation(operation,"image creation from disk")returnimage_client.get(project=project_id,image=image_name)REST
Make aPOST request to theimages().insertmethod, with asourceDisk URL in the request body.
POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/images?FORCE_OPTION{ "name": "IMAGE_NAME", "sourceDisk": "zones/ZONE/disks/DISK_NAME", "storageLocations": "LOCATION",}Replace the following:
PROJECT_ID: the project ID for this request.FORCE_OPTION: an optional flag to create the image even if the sourcedisk is attached to a running instance. SpecifyforceCreate=trueat the end of your POST line to set this option. This option mightcompromise the integrity of your image. Stop the instance before youcreate the image if possible.IMAGE_NAME: the name to give this image.ZONE: the zone of the source disk to create an image from.DISK_NAME: the name of the source disk.LOCATION: an optional parameter that lets you selectthe multi-region or a region storage location of your image.For example, specifyusto store the image in theusmulti-region, orus-central1to store it in theus-central1region.If you don't make a selection, Compute Engine stores theimage in the multi-region closest to your image's source location.
For more information about adding images, see theimages reference.
Update Windows agents and scripts
Compute Engine occasionally releases new Windows images with thelatest agents and scripts. These items assist Windows instances with startupand shutdown processes, account management, and address management.
Since Windows image versionv20160112, the Windows agent updates itself withupstream releases. You can disable these agent updates by setting thedisable-agent-updates instance metadata key totrue. If you have instancesthat are based on older image releases, you canmanually update the Windows agent of those instances.
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.