Deploy Azure Stack HCI Virtual Machines

The azure-native:azurestackhci:VirtualMachine resource, part of the Pulumi Azure Native provider, defines virtual machines on Azure Stack HCI clusters: their image source, hardware profile, networking, and security settings. This guide focuses on three capabilities: gallery and marketplace image deployment, existing disk attachment, and security profile configuration.

Azure Stack HCI VMs depend on custom locations (Azure Arc extended locations), image or disk resources, storage containers, and network interfaces. The examples are intentionally small. Combine them with your own Azure Stack HCI infrastructure and networking.

Most deployments start with a pre-configured gallery image and enable TPM and Secure Boot for compliance.

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

const virtualMachine = new azure_native.azurestackhci.VirtualMachine("virtualMachine", {
    extendedLocation: {
        name: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        type: azure_native.azurestackhci.ExtendedLocationTypes.CustomLocation,
    },
    hardwareProfile: {
        vmSize: azure_native.azurestackhci.VmSizeEnum.Default,
    },
    location: "West US2",
    networkProfile: {
        networkInterfaces: [{
            id: "test-nic",
        }],
    },
    osProfile: {
        adminPassword: "password",
        adminUsername: "localadmin",
        computerName: "luamaster",
    },
    resourceGroupName: "test-rg",
    securityProfile: {
        enableTPM: true,
        uefiSettings: {
            secureBootEnabled: true,
        },
    },
    storageProfile: {
        imageReference: {
            id: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image",
        },
        vmConfigStoragePathId: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtualMachineName: "test-vm",
});
import pulumi
import pulumi_azure_native as azure_native

virtual_machine = azure_native.azurestackhci.VirtualMachine("virtualMachine",
    extended_location={
        "name": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        "type": azure_native.azurestackhci.ExtendedLocationTypes.CUSTOM_LOCATION,
    },
    hardware_profile={
        "vm_size": azure_native.azurestackhci.VmSizeEnum.DEFAULT,
    },
    location="West US2",
    network_profile={
        "network_interfaces": [{
            "id": "test-nic",
        }],
    },
    os_profile={
        "admin_password": "password",
        "admin_username": "localadmin",
        "computer_name": "luamaster",
    },
    resource_group_name="test-rg",
    security_profile={
        "enable_tpm": True,
        "uefi_settings": {
            "secure_boot_enabled": True,
        },
    },
    storage_profile={
        "image_reference": {
            "id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image",
        },
        "vm_config_storage_path_id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtual_machine_name="test-vm")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := azurestackhci.NewVirtualMachine(ctx, "virtualMachine", &azurestackhci.VirtualMachineArgs{
			ExtendedLocation: &azurestackhci.ExtendedLocationArgs{
				Name: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location"),
				Type: pulumi.String(azurestackhci.ExtendedLocationTypesCustomLocation),
			},
			HardwareProfile: &azurestackhci.VirtualMachinePropertiesHardwareProfileArgs{
				VmSize: pulumi.String(azurestackhci.VmSizeEnumDefault),
			},
			Location: pulumi.String("West US2"),
			NetworkProfile: &azurestackhci.VirtualMachinePropertiesNetworkProfileArgs{
				NetworkInterfaces: azurestackhci.VirtualMachinePropertiesNetworkInterfacesArray{
					&azurestackhci.VirtualMachinePropertiesNetworkInterfacesArgs{
						Id: pulumi.String("test-nic"),
					},
				},
			},
			OsProfile: &azurestackhci.VirtualMachinePropertiesOsProfileArgs{
				AdminPassword: pulumi.String("password"),
				AdminUsername: pulumi.String("localadmin"),
				ComputerName:  pulumi.String("luamaster"),
			},
			ResourceGroupName: pulumi.String("test-rg"),
			SecurityProfile: &azurestackhci.VirtualMachinePropertiesSecurityProfileArgs{
				EnableTPM: pulumi.Bool(true),
				UefiSettings: &azurestackhci.VirtualMachinePropertiesUefiSettingsArgs{
					SecureBootEnabled: pulumi.Bool(true),
				},
			},
			StorageProfile: &azurestackhci.VirtualMachinePropertiesStorageProfileArgs{
				ImageReference: &azurestackhci.VirtualMachinePropertiesImageReferenceArgs{
					Id: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image"),
				},
				VmConfigStoragePathId: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container"),
			},
			VirtualMachineName: pulumi.String("test-vm"),
		})
		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 virtualMachine = new AzureNative.AzureStackHCI.VirtualMachine("virtualMachine", new()
    {
        ExtendedLocation = new AzureNative.AzureStackHCI.Inputs.ExtendedLocationArgs
        {
            Name = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
            Type = AzureNative.AzureStackHCI.ExtendedLocationTypes.CustomLocation,
        },
        HardwareProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesHardwareProfileArgs
        {
            VmSize = AzureNative.AzureStackHCI.VmSizeEnum.Default,
        },
        Location = "West US2",
        NetworkProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkProfileArgs
        {
            NetworkInterfaces = new[]
            {
                new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkInterfacesArgs
                {
                    Id = "test-nic",
                },
            },
        },
        OsProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesOsProfileArgs
        {
            AdminPassword = "password",
            AdminUsername = "localadmin",
            ComputerName = "luamaster",
        },
        ResourceGroupName = "test-rg",
        SecurityProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesSecurityProfileArgs
        {
            EnableTPM = true,
            UefiSettings = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesUefiSettingsArgs
            {
                SecureBootEnabled = true,
            },
        },
        StorageProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesStorageProfileArgs
        {
            ImageReference = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesImageReferenceArgs
            {
                Id = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image",
            },
            VmConfigStoragePathId = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
        },
        VirtualMachineName = "test-vm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.azurestackhci.VirtualMachine;
import com.pulumi.azurenative.azurestackhci.VirtualMachineArgs;
import com.pulumi.azurenative.azurestackhci.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesHardwareProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesNetworkProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesOsProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesSecurityProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesUefiSettingsArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesStorageProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesImageReferenceArgs;
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 virtualMachine = new VirtualMachine("virtualMachine", VirtualMachineArgs.builder()
            .extendedLocation(ExtendedLocationArgs.builder()
                .name("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location")
                .type("CustomLocation")
                .build())
            .hardwareProfile(VirtualMachinePropertiesHardwareProfileArgs.builder()
                .vmSize("Default")
                .build())
            .location("West US2")
            .networkProfile(VirtualMachinePropertiesNetworkProfileArgs.builder()
                .networkInterfaces(VirtualMachinePropertiesNetworkInterfacesArgs.builder()
                    .id("test-nic")
                    .build())
                .build())
            .osProfile(VirtualMachinePropertiesOsProfileArgs.builder()
                .adminPassword("password")
                .adminUsername("localadmin")
                .computerName("luamaster")
                .build())
            .resourceGroupName("test-rg")
            .securityProfile(VirtualMachinePropertiesSecurityProfileArgs.builder()
                .enableTPM(true)
                .uefiSettings(VirtualMachinePropertiesUefiSettingsArgs.builder()
                    .secureBootEnabled(true)
                    .build())
                .build())
            .storageProfile(VirtualMachinePropertiesStorageProfileArgs.builder()
                .imageReference(VirtualMachinePropertiesImageReferenceArgs.builder()
                    .id("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image")
                    .build())
                .vmConfigStoragePathId("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container")
                .build())
            .virtualMachineName("test-vm")
            .build());

    }
}
resources:
  virtualMachine:
    type: azure-native:azurestackhci:VirtualMachine
    properties:
      extendedLocation:
        name: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location
        type: CustomLocation
      hardwareProfile:
        vmSize: Default
      location: West US2
      networkProfile:
        networkInterfaces:
          - id: test-nic
      osProfile:
        adminPassword: password
        adminUsername: localadmin
        computerName: luamaster
      resourceGroupName: test-rg
      securityProfile:
        enableTPM: true
        uefiSettings:
          secureBootEnabled: true
      storageProfile:
        imageReference:
          id: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/galleryImages/test-gallery-image
        vmConfigStoragePathId: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container
      virtualMachineName: test-vm

The extendedLocation property places the VM on a specific Azure Stack HCI cluster via a custom location. The storageProfile.imageReference points to a gallery image, while vmConfigStoragePathId specifies where VM configuration files are stored. The securityProfile enables TPM (enableTPM) and Secure Boot (uefiSettings.secureBootEnabled), which are required for many compliance frameworks. The osProfile sets initial credentials, and networkProfile attaches the VM to a pre-existing network interface.

Deploy from Azure Marketplace images

Azure Stack HCI supports marketplace gallery images for standardized OS deployments without maintaining custom images.

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

const virtualMachine = new azure_native.azurestackhci.VirtualMachine("virtualMachine", {
    extendedLocation: {
        name: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        type: azure_native.azurestackhci.ExtendedLocationTypes.CustomLocation,
    },
    hardwareProfile: {
        vmSize: azure_native.azurestackhci.VmSizeEnum.Default,
    },
    location: "West US2",
    networkProfile: {
        networkInterfaces: [{
            id: "test-nic",
        }],
    },
    osProfile: {
        adminPassword: "password",
        adminUsername: "localadmin",
        computerName: "luamaster",
    },
    resourceGroupName: "test-rg",
    securityProfile: {
        enableTPM: true,
        uefiSettings: {
            secureBootEnabled: true,
        },
    },
    storageProfile: {
        imageReference: {
            id: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image",
        },
        vmConfigStoragePathId: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtualMachineName: "test-vm",
});
import pulumi
import pulumi_azure_native as azure_native

virtual_machine = azure_native.azurestackhci.VirtualMachine("virtualMachine",
    extended_location={
        "name": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        "type": azure_native.azurestackhci.ExtendedLocationTypes.CUSTOM_LOCATION,
    },
    hardware_profile={
        "vm_size": azure_native.azurestackhci.VmSizeEnum.DEFAULT,
    },
    location="West US2",
    network_profile={
        "network_interfaces": [{
            "id": "test-nic",
        }],
    },
    os_profile={
        "admin_password": "password",
        "admin_username": "localadmin",
        "computer_name": "luamaster",
    },
    resource_group_name="test-rg",
    security_profile={
        "enable_tpm": True,
        "uefi_settings": {
            "secure_boot_enabled": True,
        },
    },
    storage_profile={
        "image_reference": {
            "id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image",
        },
        "vm_config_storage_path_id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtual_machine_name="test-vm")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := azurestackhci.NewVirtualMachine(ctx, "virtualMachine", &azurestackhci.VirtualMachineArgs{
			ExtendedLocation: &azurestackhci.ExtendedLocationArgs{
				Name: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location"),
				Type: pulumi.String(azurestackhci.ExtendedLocationTypesCustomLocation),
			},
			HardwareProfile: &azurestackhci.VirtualMachinePropertiesHardwareProfileArgs{
				VmSize: pulumi.String(azurestackhci.VmSizeEnumDefault),
			},
			Location: pulumi.String("West US2"),
			NetworkProfile: &azurestackhci.VirtualMachinePropertiesNetworkProfileArgs{
				NetworkInterfaces: azurestackhci.VirtualMachinePropertiesNetworkInterfacesArray{
					&azurestackhci.VirtualMachinePropertiesNetworkInterfacesArgs{
						Id: pulumi.String("test-nic"),
					},
				},
			},
			OsProfile: &azurestackhci.VirtualMachinePropertiesOsProfileArgs{
				AdminPassword: pulumi.String("password"),
				AdminUsername: pulumi.String("localadmin"),
				ComputerName:  pulumi.String("luamaster"),
			},
			ResourceGroupName: pulumi.String("test-rg"),
			SecurityProfile: &azurestackhci.VirtualMachinePropertiesSecurityProfileArgs{
				EnableTPM: pulumi.Bool(true),
				UefiSettings: &azurestackhci.VirtualMachinePropertiesUefiSettingsArgs{
					SecureBootEnabled: pulumi.Bool(true),
				},
			},
			StorageProfile: &azurestackhci.VirtualMachinePropertiesStorageProfileArgs{
				ImageReference: &azurestackhci.VirtualMachinePropertiesImageReferenceArgs{
					Id: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image"),
				},
				VmConfigStoragePathId: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container"),
			},
			VirtualMachineName: pulumi.String("test-vm"),
		})
		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 virtualMachine = new AzureNative.AzureStackHCI.VirtualMachine("virtualMachine", new()
    {
        ExtendedLocation = new AzureNative.AzureStackHCI.Inputs.ExtendedLocationArgs
        {
            Name = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
            Type = AzureNative.AzureStackHCI.ExtendedLocationTypes.CustomLocation,
        },
        HardwareProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesHardwareProfileArgs
        {
            VmSize = AzureNative.AzureStackHCI.VmSizeEnum.Default,
        },
        Location = "West US2",
        NetworkProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkProfileArgs
        {
            NetworkInterfaces = new[]
            {
                new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkInterfacesArgs
                {
                    Id = "test-nic",
                },
            },
        },
        OsProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesOsProfileArgs
        {
            AdminPassword = "password",
            AdminUsername = "localadmin",
            ComputerName = "luamaster",
        },
        ResourceGroupName = "test-rg",
        SecurityProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesSecurityProfileArgs
        {
            EnableTPM = true,
            UefiSettings = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesUefiSettingsArgs
            {
                SecureBootEnabled = true,
            },
        },
        StorageProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesStorageProfileArgs
        {
            ImageReference = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesImageReferenceArgs
            {
                Id = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image",
            },
            VmConfigStoragePathId = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
        },
        VirtualMachineName = "test-vm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.azurestackhci.VirtualMachine;
import com.pulumi.azurenative.azurestackhci.VirtualMachineArgs;
import com.pulumi.azurenative.azurestackhci.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesHardwareProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesNetworkProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesOsProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesSecurityProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesUefiSettingsArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesStorageProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesImageReferenceArgs;
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 virtualMachine = new VirtualMachine("virtualMachine", VirtualMachineArgs.builder()
            .extendedLocation(ExtendedLocationArgs.builder()
                .name("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location")
                .type("CustomLocation")
                .build())
            .hardwareProfile(VirtualMachinePropertiesHardwareProfileArgs.builder()
                .vmSize("Default")
                .build())
            .location("West US2")
            .networkProfile(VirtualMachinePropertiesNetworkProfileArgs.builder()
                .networkInterfaces(VirtualMachinePropertiesNetworkInterfacesArgs.builder()
                    .id("test-nic")
                    .build())
                .build())
            .osProfile(VirtualMachinePropertiesOsProfileArgs.builder()
                .adminPassword("password")
                .adminUsername("localadmin")
                .computerName("luamaster")
                .build())
            .resourceGroupName("test-rg")
            .securityProfile(VirtualMachinePropertiesSecurityProfileArgs.builder()
                .enableTPM(true)
                .uefiSettings(VirtualMachinePropertiesUefiSettingsArgs.builder()
                    .secureBootEnabled(true)
                    .build())
                .build())
            .storageProfile(VirtualMachinePropertiesStorageProfileArgs.builder()
                .imageReference(VirtualMachinePropertiesImageReferenceArgs.builder()
                    .id("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image")
                    .build())
                .vmConfigStoragePathId("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container")
                .build())
            .virtualMachineName("test-vm")
            .build());

    }
}
resources:
  virtualMachine:
    type: azure-native:azurestackhci:VirtualMachine
    properties:
      extendedLocation:
        name: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location
        type: CustomLocation
      hardwareProfile:
        vmSize: Default
      location: West US2
      networkProfile:
        networkInterfaces:
          - id: test-nic
      osProfile:
        adminPassword: password
        adminUsername: localadmin
        computerName: luamaster
      resourceGroupName: test-rg
      securityProfile:
        enableTPM: true
        uefiSettings:
          secureBootEnabled: true
      storageProfile:
        imageReference:
          id: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/marketplaceGalleryImages/test-marketplace-gallery-image
        vmConfigStoragePathId: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container
      virtualMachineName: test-vm

The imageReference.id now points to a marketplaceGalleryImages resource instead of a custom gallery image. This allows you to deploy from Azure’s curated catalog. All other configuration (security, networking, storage) remains identical to gallery image deployment.

Attach an existing OS disk

When migrating VMs or using custom disk configurations, you can attach a pre-configured virtual hard disk.

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

const virtualMachine = new azure_native.azurestackhci.VirtualMachine("virtualMachine", {
    extendedLocation: {
        name: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        type: azure_native.azurestackhci.ExtendedLocationTypes.CustomLocation,
    },
    hardwareProfile: {
        vmSize: azure_native.azurestackhci.VmSizeEnum.Default,
    },
    location: "West US2",
    networkProfile: {
        networkInterfaces: [{
            id: "test-nic",
        }],
    },
    resourceGroupName: "test-rg",
    securityProfile: {
        enableTPM: true,
        uefiSettings: {
            secureBootEnabled: true,
        },
    },
    storageProfile: {
        osDisk: {
            id: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd",
        },
        vmConfigStoragePathId: "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtualMachineName: "test-vm",
});
import pulumi
import pulumi_azure_native as azure_native

virtual_machine = azure_native.azurestackhci.VirtualMachine("virtualMachine",
    extended_location={
        "name": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
        "type": azure_native.azurestackhci.ExtendedLocationTypes.CUSTOM_LOCATION,
    },
    hardware_profile={
        "vm_size": azure_native.azurestackhci.VmSizeEnum.DEFAULT,
    },
    location="West US2",
    network_profile={
        "network_interfaces": [{
            "id": "test-nic",
        }],
    },
    resource_group_name="test-rg",
    security_profile={
        "enable_tpm": True,
        "uefi_settings": {
            "secure_boot_enabled": True,
        },
    },
    storage_profile={
        "os_disk": {
            "id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd",
        },
        "vm_config_storage_path_id": "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
    },
    virtual_machine_name="test-vm")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := azurestackhci.NewVirtualMachine(ctx, "virtualMachine", &azurestackhci.VirtualMachineArgs{
			ExtendedLocation: &azurestackhci.ExtendedLocationArgs{
				Name: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location"),
				Type: pulumi.String(azurestackhci.ExtendedLocationTypesCustomLocation),
			},
			HardwareProfile: &azurestackhci.VirtualMachinePropertiesHardwareProfileArgs{
				VmSize: pulumi.String(azurestackhci.VmSizeEnumDefault),
			},
			Location: pulumi.String("West US2"),
			NetworkProfile: &azurestackhci.VirtualMachinePropertiesNetworkProfileArgs{
				NetworkInterfaces: azurestackhci.VirtualMachinePropertiesNetworkInterfacesArray{
					&azurestackhci.VirtualMachinePropertiesNetworkInterfacesArgs{
						Id: pulumi.String("test-nic"),
					},
				},
			},
			ResourceGroupName: pulumi.String("test-rg"),
			SecurityProfile: &azurestackhci.VirtualMachinePropertiesSecurityProfileArgs{
				EnableTPM: pulumi.Bool(true),
				UefiSettings: &azurestackhci.VirtualMachinePropertiesUefiSettingsArgs{
					SecureBootEnabled: pulumi.Bool(true),
				},
			},
			StorageProfile: &azurestackhci.VirtualMachinePropertiesStorageProfileArgs{
				OsDisk: &azurestackhci.VirtualMachinePropertiesOsDiskArgs{
					Id: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd"),
				},
				VmConfigStoragePathId: pulumi.String("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container"),
			},
			VirtualMachineName: pulumi.String("test-vm"),
		})
		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 virtualMachine = new AzureNative.AzureStackHCI.VirtualMachine("virtualMachine", new()
    {
        ExtendedLocation = new AzureNative.AzureStackHCI.Inputs.ExtendedLocationArgs
        {
            Name = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location",
            Type = AzureNative.AzureStackHCI.ExtendedLocationTypes.CustomLocation,
        },
        HardwareProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesHardwareProfileArgs
        {
            VmSize = AzureNative.AzureStackHCI.VmSizeEnum.Default,
        },
        Location = "West US2",
        NetworkProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkProfileArgs
        {
            NetworkInterfaces = new[]
            {
                new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesNetworkInterfacesArgs
                {
                    Id = "test-nic",
                },
            },
        },
        ResourceGroupName = "test-rg",
        SecurityProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesSecurityProfileArgs
        {
            EnableTPM = true,
            UefiSettings = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesUefiSettingsArgs
            {
                SecureBootEnabled = true,
            },
        },
        StorageProfile = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesStorageProfileArgs
        {
            OsDisk = new AzureNative.AzureStackHCI.Inputs.VirtualMachinePropertiesOsDiskArgs
            {
                Id = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd",
            },
            VmConfigStoragePathId = "/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container",
        },
        VirtualMachineName = "test-vm",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.azurestackhci.VirtualMachine;
import com.pulumi.azurenative.azurestackhci.VirtualMachineArgs;
import com.pulumi.azurenative.azurestackhci.inputs.ExtendedLocationArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesHardwareProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesNetworkProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesSecurityProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesUefiSettingsArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesStorageProfileArgs;
import com.pulumi.azurenative.azurestackhci.inputs.VirtualMachinePropertiesOsDiskArgs;
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 virtualMachine = new VirtualMachine("virtualMachine", VirtualMachineArgs.builder()
            .extendedLocation(ExtendedLocationArgs.builder()
                .name("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location")
                .type("CustomLocation")
                .build())
            .hardwareProfile(VirtualMachinePropertiesHardwareProfileArgs.builder()
                .vmSize("Default")
                .build())
            .location("West US2")
            .networkProfile(VirtualMachinePropertiesNetworkProfileArgs.builder()
                .networkInterfaces(VirtualMachinePropertiesNetworkInterfacesArgs.builder()
                    .id("test-nic")
                    .build())
                .build())
            .resourceGroupName("test-rg")
            .securityProfile(VirtualMachinePropertiesSecurityProfileArgs.builder()
                .enableTPM(true)
                .uefiSettings(VirtualMachinePropertiesUefiSettingsArgs.builder()
                    .secureBootEnabled(true)
                    .build())
                .build())
            .storageProfile(VirtualMachinePropertiesStorageProfileArgs.builder()
                .osDisk(VirtualMachinePropertiesOsDiskArgs.builder()
                    .id("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd")
                    .build())
                .vmConfigStoragePathId("/subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container")
                .build())
            .virtualMachineName("test-vm")
            .build());

    }
}
resources:
  virtualMachine:
    type: azure-native:azurestackhci:VirtualMachine
    properties:
      extendedLocation:
        name: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.ExtendedLocation/customLocations/dogfood-location
        type: CustomLocation
      hardwareProfile:
        vmSize: Default
      location: West US2
      networkProfile:
        networkInterfaces:
          - id: test-nic
      resourceGroupName: test-rg
      securityProfile:
        enableTPM: true
        uefiSettings:
          secureBootEnabled: true
      storageProfile:
        osDisk:
          id: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/virtualHardDisks/test-vhd
        vmConfigStoragePathId: /subscriptions/a95612cb-f1fa-4daa-a4fd-272844fa512c/resourceGroups/dogfoodarc/providers/Microsoft.AzureStackHCI/storageContainers/test-container
      virtualMachineName: test-vm

The storageProfile.osDisk property references an existing virtual hard disk instead of an image. This approach skips image provisioning and boots directly from the specified disk. Note that osProfile is omitted because the disk already contains OS configuration and credentials.

Beyond these examples

These snippets focus on specific VM-level features: image-based and disk-based provisioning, security configuration, and custom and marketplace image sources. They’re intentionally minimal rather than full VM deployments.

The examples reference pre-existing infrastructure such as custom locations (Azure Arc extended locations), gallery images, marketplace images, or virtual hard disks, storage containers for VM configuration files, and network interfaces. They focus on configuring the VM rather than provisioning the surrounding Azure Stack HCI infrastructure.

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

  • Guest agent configuration (guestAgentProfile)
  • Managed identity assignment (identity)
  • Data disk attachment beyond OS disk
  • VM sizing and hardware customization (processors, memory)

These omissions are intentional: the goal is to illustrate how each VM feature is wired, not provide drop-in infrastructure modules. See the Azure Stack HCI VirtualMachine resource reference for all available configuration options.

Let's deploy Azure Stack HCI Virtual Machines

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Deployment & Location
What's required to deploy a VM on Azure Stack HCI?
You must specify extendedLocation with type CustomLocation pointing to your Azure Stack HCI custom location resource.
What image sources can I use for my VM?

You have three options:

  1. Gallery images - Use imageReference.id pointing to Microsoft.AzureStackHCI/galleryImages
  2. Marketplace images - Use imageReference.id pointing to Microsoft.AzureStackHCI/marketplaceGalleryImages
  3. Existing OS disk - Use osDisk.id pointing to Microsoft.AzureStackHCI/virtualHardDisks
Storage Configuration
What's the difference between imageReference and osDisk in storageProfile?
Use imageReference to deploy from a gallery or marketplace image. Use osDisk to attach an existing virtual hard disk. These are mutually exclusive options.
What's vmConfigStoragePathId used for?
vmConfigStoragePathId specifies the storage container path for VM configuration files. It’s required in storageProfile and points to a Microsoft.AzureStackHCI/storageContainers resource.
Security Configuration
How do I enable secure boot and TPM for my VM?
Configure securityProfile with enableTPM: true and uefiSettings.secureBootEnabled: true.
Resource Lifecycle
What properties can't I change after creating the VM?
The following properties are immutable and require resource recreation to change: location, resourceGroupName, and virtualMachineName.
What VM sizes are available?
The examples show vmSize set to Default. Refer to your Azure Stack HCI cluster’s available VM sizes for other options.
Networking & OS Configuration
How do I configure network interfaces for my VM?
Specify networkProfile.networkInterfaces with an array of network interface IDs. Each interface requires an id property.
What OS configuration can I set during deployment?
Use osProfile to configure adminUsername, adminPassword, and computerName for the VM’s operating system.

Using a different cloud?

Explore compute guides for other cloud providers: