Create Azure Disk Snapshots

The azure-native:compute:Snapshot resource, part of the Pulumi Azure Native provider, defines Azure managed disk snapshots: point-in-time copies of disks or VHD blobs that can be replicated across regions and subscriptions. This guide focuses on four capabilities: VHD blob import, snapshot-to-snapshot copying, cross-region replication with bandwidth controls, and Elastic SAN integration.

Snapshots reference source data that must exist before creation: VHD blobs in Azure Storage, existing snapshots, or Elastic SAN volume snapshots. The examples are intentionally small. Combine them with your own storage accounts, encryption settings, and network policies.

Import an unmanaged VHD blob into a snapshot

Teams migrating from unmanaged disks often capture VHD blobs stored in Azure Storage as managed snapshots for backup or replication.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const snapshot = new azure_native.compute.Snapshot("snapshot", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Import,
        sourceUri: "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
    },
    location: "West US",
    resourceGroupName: "myResourceGroup",
    snapshotName: "mySnapshot1",
});
import pulumi
import pulumi_azure_native as azure_native

snapshot = azure_native.compute.Snapshot("snapshot",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.IMPORT_,
        "source_uri": "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
    },
    location="West US",
    resource_group_name="myResourceGroup",
    snapshot_name="mySnapshot1")
package main

import (
	compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption: pulumi.String(compute.DiskCreateOptionImport),
				SourceUri:    pulumi.String("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd"),
			},
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			SnapshotName:      pulumi.String("mySnapshot1"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Import,
            SourceUri = "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
        },
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        SnapshotName = "mySnapshot1",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Import")
                .sourceUri("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd")
                .build())
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .snapshotName("mySnapshot1")
            .build());

    }
}
resources:
  snapshot:
    type: azure-native:compute:Snapshot
    properties:
      creationData:
        createOption: Import
        sourceUri: https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd
      location: West US
      resourceGroupName: myResourceGroup
      snapshotName: mySnapshot1

The creationData block controls how the snapshot is created. Setting createOption to Import tells Azure to read the VHD blob from the sourceUri and convert it into a managed snapshot. When the storage account is in the same subscription, you don’t need to specify storageAccountId.

Copy a snapshot within or across subscriptions

Disaster recovery and multi-region deployments require copying snapshots to different regions or subscriptions for redundancy.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const snapshot = new azure_native.compute.Snapshot("snapshot", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.Copy,
        sourceResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
    },
    location: "West US",
    resourceGroupName: "myResourceGroup",
    snapshotName: "mySnapshot2",
});
import pulumi
import pulumi_azure_native as azure_native

snapshot = azure_native.compute.Snapshot("snapshot",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.COPY,
        "source_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
    },
    location="West US",
    resource_group_name="myResourceGroup",
    snapshot_name="mySnapshot2")
package main

import (
	compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption:     pulumi.String(compute.DiskCreateOptionCopy),
				SourceResourceId: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1"),
			},
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			SnapshotName:      pulumi.String("mySnapshot2"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.Copy,
            SourceResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
        },
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        SnapshotName = "mySnapshot2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("Copy")
                .sourceResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1")
                .build())
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .snapshotName("mySnapshot2")
            .build());

    }
}
resources:
  snapshot:
    type: azure-native:compute:Snapshot
    properties:
      creationData:
        createOption: Copy
        sourceResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1
      location: West US
      resourceGroupName: myResourceGroup
      snapshotName: mySnapshot2

Setting createOption to Copy initiates a full snapshot replication. The sourceResourceId points to the snapshot you’re copying from, which can be in the same subscription or a different one. Azure handles the data transfer and creates an independent snapshot in the target region.

Copy a snapshot with enhanced bandwidth

Large snapshots can take hours to copy across regions. Enhanced bandwidth provisioning accelerates the copy operation for time-sensitive migrations.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const snapshot = new azure_native.compute.Snapshot("snapshot", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.CopyStart,
        provisionedBandwidthCopySpeed: azure_native.compute.ProvisionedBandwidthCopyOption.Enhanced,
        sourceResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
    },
    location: "West US",
    resourceGroupName: "myResourceGroup",
    snapshotName: "mySnapshot2",
});
import pulumi
import pulumi_azure_native as azure_native

snapshot = azure_native.compute.Snapshot("snapshot",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.COPY_START,
        "provisioned_bandwidth_copy_speed": azure_native.compute.ProvisionedBandwidthCopyOption.ENHANCED,
        "source_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
    },
    location="West US",
    resource_group_name="myResourceGroup",
    snapshot_name="mySnapshot2")
package main

import (
	compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption:                  pulumi.String(compute.DiskCreateOptionCopyStart),
				ProvisionedBandwidthCopySpeed: pulumi.String(compute.ProvisionedBandwidthCopyOptionEnhanced),
				SourceResourceId:              pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1"),
			},
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			SnapshotName:      pulumi.String("mySnapshot2"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.CopyStart,
            ProvisionedBandwidthCopySpeed = AzureNative.Compute.ProvisionedBandwidthCopyOption.Enhanced,
            SourceResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1",
        },
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        SnapshotName = "mySnapshot2",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("CopyStart")
                .provisionedBandwidthCopySpeed("Enhanced")
                .sourceResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1")
                .build())
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .snapshotName("mySnapshot2")
            .build());

    }
}
resources:
  snapshot:
    type: azure-native:compute:Snapshot
    properties:
      creationData:
        createOption: CopyStart
        provisionedBandwidthCopySpeed: Enhanced
        sourceResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/snapshots/mySnapshot1
      location: West US
      resourceGroupName: myResourceGroup
      snapshotName: mySnapshot2

The CopyStart option works like Copy but allows you to specify provisionedBandwidthCopySpeed. Setting it to Enhanced allocates additional network bandwidth to speed up the transfer. This is useful for large snapshots where standard copy speeds would cause unacceptable delays.

Create a snapshot from Elastic SAN storage

Elastic SAN provides high-performance block storage for Azure workloads. Teams can capture Elastic SAN volume snapshots as managed disk snapshots for portability.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const snapshot = new azure_native.compute.Snapshot("snapshot", {
    creationData: {
        createOption: azure_native.compute.DiskCreateOption.CopyFromSanSnapshot,
        elasticSanResourceId: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
    },
    location: "West US",
    resourceGroupName: "myResourceGroup",
    snapshotName: "mySnapshot",
});
import pulumi
import pulumi_azure_native as azure_native

snapshot = azure_native.compute.Snapshot("snapshot",
    creation_data={
        "create_option": azure_native.compute.DiskCreateOption.COPY_FROM_SAN_SNAPSHOT,
        "elastic_san_resource_id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
    },
    location="West US",
    resource_group_name="myResourceGroup",
    snapshot_name="mySnapshot")
package main

import (
	compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := compute.NewSnapshot(ctx, "snapshot", &compute.SnapshotArgs{
			CreationData: &compute.CreationDataArgs{
				CreateOption:         pulumi.String(compute.DiskCreateOptionCopyFromSanSnapshot),
				ElasticSanResourceId: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot"),
			},
			Location:          pulumi.String("West US"),
			ResourceGroupName: pulumi.String("myResourceGroup"),
			SnapshotName:      pulumi.String("mySnapshot"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;

return await Deployment.RunAsync(() => 
{
    var snapshot = new AzureNative.Compute.Snapshot("snapshot", new()
    {
        CreationData = new AzureNative.Compute.Inputs.CreationDataArgs
        {
            CreateOption = AzureNative.Compute.DiskCreateOption.CopyFromSanSnapshot,
            ElasticSanResourceId = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot",
        },
        Location = "West US",
        ResourceGroupName = "myResourceGroup",
        SnapshotName = "mySnapshot",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Snapshot;
import com.pulumi.azurenative.compute.SnapshotArgs;
import com.pulumi.azurenative.compute.inputs.CreationDataArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var snapshot = new Snapshot("snapshot", SnapshotArgs.builder()
            .creationData(CreationDataArgs.builder()
                .createOption("CopyFromSanSnapshot")
                .elasticSanResourceId("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot")
                .build())
            .location("West US")
            .resourceGroupName("myResourceGroup")
            .snapshotName("mySnapshot")
            .build());

    }
}
resources:
  snapshot:
    type: azure-native:compute:Snapshot
    properties:
      creationData:
        createOption: CopyFromSanSnapshot
        elasticSanResourceId: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ElasticSan/elasticSans/myElasticSan/volumegroups/myElasticSanVolumeGroup/snapshots/myElasticSanVolumeSnapshot
      location: West US
      resourceGroupName: myResourceGroup
      snapshotName: mySnapshot

The CopyFromSanSnapshot option converts an Elastic SAN volume snapshot into a managed disk snapshot. The elasticSanResourceId points to the Elastic SAN snapshot resource. This enables you to move data from Elastic SAN into the managed disk ecosystem for broader compatibility.

Beyond these examples

These snippets focus on specific snapshot-level features: VHD blob import and snapshot-to-snapshot copying, cross-region replication with bandwidth controls, and Elastic SAN integration. They’re intentionally minimal rather than full backup solutions.

The examples reference pre-existing infrastructure such as Azure Storage accounts with VHD blobs, and source snapshots or Elastic SAN volume snapshots. They focus on configuring the snapshot rather than provisioning everything around it.

To keep things focused, common snapshot patterns are omitted, including:

  • Incremental snapshots (incremental property)
  • Encryption with customer-managed keys (encryption, encryptionSettingsCollection)
  • Network access policies and private endpoints (networkAccessPolicy, diskAccessId)
  • SKU selection for storage tier (sku property)

These omissions are intentional: the goal is to illustrate how each snapshot feature is wired, not provide drop-in backup modules. See the Snapshot resource reference for all available configuration options.

Let's create Azure Disk Snapshots

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Immutability & Constraints
What properties can't I change after creating a snapshot?
You cannot modify creationData, location, snapshotName, or extendedLocation after the snapshot is created. Plan these values carefully during initial creation.
Can I resize a snapshot after creation?
Yes, but only to increase the size. Resizes are only allowed if the disk is not attached to a running VM, and you cannot decrease disk size.
Snapshot Creation & Sources
How do I import a snapshot from an unmanaged blob?
Use createOption: Import with sourceUri pointing to the blob. If importing from a different subscription, include storageAccountId with the full resource ID of the storage account. For same-subscription imports, storageAccountId is not needed.
What's the difference between Copy and CopyStart for snapshot creation?
Use Copy to copy a snapshot within the same region or subscription. Use CopyStart to copy a snapshot across different regions or subscriptions.
How do I create a snapshot from an Elastic SAN volume snapshot?
Use createOption: CopyFromSanSnapshot with elasticSanResourceId pointing to the Elastic SAN volume snapshot resource.
Performance & Optimization
How can I speed up cross-region snapshot copies?
Set provisionedBandwidthCopySpeed to Enhanced when using createOption: CopyStart for faster copy operations across regions.
What are incremental snapshots and how do they save space?
Incremental snapshots occupy less space than full snapshots by storing only the changes since the previous snapshot. They can be diffed and share an incremental snapshot family ID.
Storage & SKU
What SKU options are available for snapshots?
You can choose Standard_LRS, Premium_LRS, or Standard_ZRS. For incremental snapshots, the default behavior is to use the same SKU as the previous snapshot.
How do I control network access to my snapshot?
Use networkAccessPolicy to control network access and publicNetworkAccess to control export policies. For private endpoints, configure diskAccessId with the ARM ID of a DiskAccess resource.

Using a different cloud?

Explore storage guides for other cloud providers: