Share via


Common questions about VM in Microsoft Marketplace

These frequently asked questions (FAQ) cover common issues you might encounter when creating a virtual machine (VM) offer in Microsoft Marketplace.

Why does my VM show "Provisioning failed" in the Azure portal even though it's running normally?

This occurs when your Linux VM image lacks a provisioning agent or the agent is misconfigured. Azure relies on these agents to report successful deployment status.

The most common cause is missing or failed provisioning agents:

  • cloud-init (recommended for Linux VMs)
  • AzureInit (supported alternative)
  • WALA (Azure Linux Agent) (least recommended)

To resolve this issue:

  1. Install cloud-init in your VM image. See Overview of cloud-init support for Linux VMs in Azure.
  2. Ensure the agent can communicate with Azure services during boot.
  3. Test or preview your image thoroughly before publishing. See How do I test a hidden preview image? for the preview process.

You can publish images without provisioning agents for specialized scenarios, but this may require additional configuration. For details, see Create Linux images without a provisioning agent.

How do I configure a virtual private network (VPN) to work with my VMs?

What are Microsoft support policies for running Microsoft server software on Azure-based VMs?

In a VM, how do I manage the custom script extension in the startup task?

For details on using the Custom Script Extension using the Azure PowerShell module, Azure Resource Manager templates, and troubleshooting steps on Windows systems, see Custom Script Extension for Windows.

Are 32-bit applications or services supported in Microsoft Marketplace?

No. The supported operating systems and standard services for Azure VMs are all 64-bit. Though most 64-bit operating systems support 32-bit versions of applications for backward compatibility, using 32-bit applications as part of your VM solution is unsupported and highly discouraged. Recreate your application as a 64-bit project.

For more information, see these articles:

Error: VHD is already registered with image repository as the resource

Every time I try to create an image from my VHDs, I get the error "VHD is already registered with image repository as the resource" in Azure PowerShell. I didn't create any image before nor did I find any image with this name in Azure. How do I resolve this issue?

This issue usually appears if you created a VM from a VHD that has a lock on it. Confirm that there's no VM allocated from this VHD and then retry the operation. If this issue continues, open a support ticket. See Support for Partner Center.

How do I create a VM from a generalized VHD?

Prepare an Azure Resource Manager template

This section describes how to create and deploy a user-provided virtual machine (VM) image using managed disks from a generalized VHD stored in Azure Storage.

  1. Sign in to the Azure portal.

  2. Upload your generalized operating system VHD and any data disk VHDs to an Azure Storage account. The template will create a managed image from the VHD URL during deployment.

  3. On the home page, select Create a resource. Search for "template deployment" and select Create.

  4. Choose Build your own template in the editor.

    Shows the selection of a template

Note

This template deploys a Gen 1 VM using managed disks. For Gen 2 VM deployment, see the Gen 2 template further below.

  1. Paste the following JSON template into the editor and select Save.

     {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
              "dnsNameForPublicIP": {
                  "type": "String"
              },
              "adminUserName": {
                  "defaultValue": "isv",
                  "type": "String"
              },
              "adminPassword": {
                  "type": "SecureString"
              },
              "osType": {
                  "defaultValue": "windows",
                  "allowedValues": [
                      "windows",
                      "linux"
                  ],
                  "type": "String"
              },
              "location": {
                  "defaultValue": "[resourceGroup().location]",
                  "type": "String"
              },
              "vmSize": {
                  "defaultValue": "Standard_D2s_v3",
                  "type": "String"
              },
              "publicIPAddressName": {
                  "type": "String"
              },
              "vmName": {
                  "type": "String"
              },
              "virtualNetworkName": {
                  "type": "String"
              },
              "nicName": {
                  "type": "String"
              },
              "vhdUrl": {
                  "type": "String",
                  "metadata": {
                      "description": "URL of the generalized VHD in a storage account"
                  }
              }
          },
          "variables": {
              "addressPrefix": "10.0.0.0/16",
              "subnet1Name": "Subnet-1",
              "subnet1Prefix": "10.0.0.0/24",
              "publicIPAddressType": "Static",
              "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
              "subnet1Ref": "[concat(variables('vnetID'),'/subnets/',variables('subnet1Name'))]",
              "imageName": "[concat(parameters('vmName'),'-image')]",
              "osDiskName": "[concat(parameters('vmName'),'-osDisk')]"
          },
          "resources": [
              {
                  "type": "Microsoft.Compute/images",
                  "apiVersion": "2024-03-01",
                  "name": "[variables('imageName')]",
                  "location": "[parameters('location')]",
                  "properties": {
                      "storageProfile": {
                          "osDisk": {
                              "osType": "[parameters('osType')]",
                              "blobUri": "[parameters('vhdUrl')]",
                              "storageAccountType": "Standard_LRS"
                          }
                      },
                      "hyperVGeneration": "V1"
                  }
              },
              {
                  "type": "Microsoft.Network/publicIPAddresses",
                  "apiVersion": "2024-03-01",
                  "name": "[parameters('publicIPAddressName')]",
                  "location": "[parameters('location')]",
                  "sku": {
                      "name": "Standard"
                  },
                  "properties": {
                      "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
                      "dnsSettings": {
                          "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
                      }
                  }
              },
              {
                  "type": "Microsoft.Network/virtualNetworks",
                  "apiVersion": "2024-03-01",
                  "name": "[parameters('virtualNetworkName')]",
                  "location": "[parameters('location')]",
                  "properties": {
                      "addressSpace": {
                          "addressPrefixes": [
                              "[variables('addressPrefix')]"
                          ]
                      },
                      "subnets": [
                          {
                              "name": "[variables('subnet1Name')]",
                              "properties": {
                                  "addressPrefix": "[variables('subnet1Prefix')]"
                              }
                          }
                      ]
                  }
              },
              {
                  "type": "Microsoft.Network/networkInterfaces",
                  "apiVersion": "2024-03-01",
                  "name": "[parameters('nicName')]",
                  "location": "[parameters('location')]",
                  "dependsOn": [
                      "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]",
                      "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
                  ],
                  "properties": {
                      "ipConfigurations": [
                          {
                              "name": "ipconfig1",
                              "properties": {
                                  "privateIPAllocationMethod": "Dynamic",
                                  "publicIPAddress": {
                                      "id": "[resourceId('Microsoft.Network/publicIPAddresses',parameters('publicIPAddressName'))]"
                                  },
                                  "subnet": {
                                      "id": "[variables('subnet1Ref')]"
                                  }
                              }
                          }
                      ]
                  }
              },
              {
                  "type": "Microsoft.Compute/virtualMachines",
                  "apiVersion": "2024-03-01",
                  "name": "[parameters('vmName')]",
                  "location": "[parameters('location')]",
                  "dependsOn": [
                      "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicName'))]",
                      "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
                  ],
                  "properties": {
                      "hardwareProfile": {
                          "vmSize": "[parameters('vmSize')]"
                      },
                      "osProfile": {
                          "computerName": "[parameters('vmName')]",
                          "adminUsername": "[parameters('adminUserName')]",
                          "adminPassword": "[parameters('adminPassword')]"
                      },
                      "storageProfile": {
                          "imageReference": {
                              "id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
                          },
                          "osDisk": {
                              "name": "[variables('osDiskName')]",
                              "createOption": "FromImage",
                              "managedDisk": {
                                  "storageAccountType": "Standard_LRS"
                              }
                          }
                      },
                      "networkProfile": {
                          "networkInterfaces": [
                              {
                                  "id": "[resourceId('Microsoft.Network/networkInterfaces',parameters('nicName'))]"
                              }
                          ]
                      }
                  }
              }
          ]
      }
    
  2. Provide the parameter values for the displayed Custom deployment property pages.

    Parameter Description
    dnsNameForPublicIP DNS name for the public IP; must be lowercase.
    adminUserName Username of the administrator account.
    adminPassword Administrator password.
    osType OS type: windows or linux.
    location Azure region of the resource group. Defaults to the resource group location.
    vmSize Size of the virtual machine instance (for example, Standard_D2s_v3).
    publicIPAddressName Name of the public IP address.
    vmName Name of the virtual machine.
    virtualNetworkName Name of the virtual network.
    nicName Name of the network interface card for the virtual network.
    vhdUrl URL of the generalized VHD in a storage account.
  3. After you supply these values, select Purchase.

    Azure begins the deployment. It creates a managed image from your VHD, then deploys a new VM with managed disks. You can track the progress in the Azure portal by selecting Virtual Machines on the left side of the portal. When the VM is created, the status changes from Starting to Running.

    For generation 2 VM deployment, use this template:

    {
         "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
         "contentVersion": "1.0.0.0",
         "parameters": {
             "dnsNameForPublicIP": {
                 "type": "String"
             },
             "adminUserName": {
                 "defaultValue": "isv",
                 "type": "String"
             },
             "adminPassword": {
                 "type": "SecureString"
             },
             "osType": {
                 "defaultValue": "windows",
                 "allowedValues": [
                     "windows",
                     "linux"
                 ],
                 "type": "String"
             },
             "location": {
                 "defaultValue": "[resourceGroup().location]",
                 "type": "String"
             },
             "vmSize": {
                 "defaultValue": "Standard_D2s_v3",
                 "type": "String"
             },
             "publicIPAddressName": {
                 "type": "String"
             },
             "vmName": {
                 "type": "String"
             },
             "virtualNetworkName": {
                 "type": "String"
             },
             "nicName": {
                 "type": "String"
             },
             "vhdUrl": {
                 "type": "String",
                 "metadata": {
                     "description": "URL of the generalized VHD in a storage account"
                 }
             }
         },
         "variables": {
             "addressPrefix": "10.0.0.0/16",
             "subnet1Name": "Subnet-1",
             "subnet1Prefix": "10.0.0.0/24",
             "publicIPAddressType": "Static",
             "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
             "subnet1Ref": "[concat(variables('vnetID'),'/subnets/',variables('subnet1Name'))]",
             "imageName": "[concat(parameters('vmName'),'-image')]",
             "osDiskName": "[concat(parameters('vmName'),'-osDisk')]"
         },
         "resources": [
             {
                 "type": "Microsoft.Compute/images",
                 "apiVersion": "2024-03-01",
                 "name": "[variables('imageName')]",
                 "location": "[parameters('location')]",
                 "properties": {
                     "storageProfile": {
                         "osDisk": {
                             "osType": "[parameters('osType')]",
                             "blobUri": "[parameters('vhdUrl')]",
                             "storageAccountType": "Standard_LRS"
                         }
                     },
                     "hyperVGeneration": "V2"
                 }
             },
             {
                 "type": "Microsoft.Network/publicIPAddresses",
                 "apiVersion": "2024-03-01",
                 "name": "[parameters('publicIPAddressName')]",
                 "location": "[parameters('location')]",
                 "sku": {
                     "name": "Standard"
                 },
                 "properties": {
                     "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
                     "dnsSettings": {
                         "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
                     }
                 }
             },
             {
                 "type": "Microsoft.Network/virtualNetworks",
                 "apiVersion": "2024-03-01",
                 "name": "[parameters('virtualNetworkName')]",
                 "location": "[parameters('location')]",
                 "properties": {
                     "addressSpace": {
                         "addressPrefixes": [
                             "[variables('addressPrefix')]"
                         ]
                     },
                     "subnets": [
                         {
                             "name": "[variables('subnet1Name')]",
                             "properties": {
                                 "addressPrefix": "[variables('subnet1Prefix')]"
                             }
                         }
                     ]
                 }
             },
             {
                 "type": "Microsoft.Network/networkInterfaces",
                 "apiVersion": "2024-03-01",
                 "name": "[parameters('nicName')]",
                 "location": "[parameters('location')]",
                 "dependsOn": [
                     "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddressName'))]",
                     "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
                 ],
                 "properties": {
                     "ipConfigurations": [
                         {
                             "name": "ipconfig1",
                             "properties": {
                                 "privateIPAllocationMethod": "Dynamic",
                                 "publicIPAddress": {
                                     "id": "[resourceId('Microsoft.Network/publicIPAddresses',parameters('publicIPAddressName'))]"
                                 },
                                 "subnet": {
                                     "id": "[variables('subnet1Ref')]"
                                 }
                             }
                         }
                     ]
                 }
             },
             {
                 "type": "Microsoft.Compute/virtualMachines",
                 "apiVersion": "2024-03-01",
                 "name": "[parameters('vmName')]",
                 "location": "[parameters('location')]",
                 "dependsOn": [
                     "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicName'))]",
                     "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
                 ],
                 "properties": {
                     "hardwareProfile": {
                         "vmSize": "[parameters('vmSize')]"
                     },
                     "osProfile": {
                         "computerName": "[parameters('vmName')]",
                         "adminUsername": "[parameters('adminUserName')]",
                         "adminPassword": "[parameters('adminPassword')]"
                     },
                     "storageProfile": {
                         "imageReference": {
                             "id": "[resourceId('Microsoft.Compute/images', variables('imageName'))]"
                         },
                         "osDisk": {
                             "name": "[variables('osDiskName')]",
                             "createOption": "FromImage",
                             "managedDisk": {
                                 "storageAccountType": "Standard_LRS"
                             }
                         }
                     },
                     "networkProfile": {
                         "networkInterfaces": [
                             {
                                 "id": "[resourceId('Microsoft.Network/networkInterfaces',parameters('nicName'))]"
                             }
                         ]
                     }
                 }
             }
         ]
     }
    

Deploy an Azure VM using PowerShell

Copy and edit the following script to provide values for the variables, then execute it to create an Azure VM resource from your existing generalized VHD.

# Set your variables
$rgName = "<your-resource-group>"
$storageaccount = "<your-storage-account>"
$vhdUrl = "https://<your-storage-account>.blob.core.windows.net/vhds/<your-vhd-file>.vhd"
$vmName = "<your-vm-name>"
$location = "<azure-region>"
$vmSize = "Standard_A2"
$subId = "<your-subscription-id>"

# Deploy VM from existing generalized VHD using ARM template
New-AzResourceGroupDeployment `
  -Name "deploy-$vmName" `
  -ResourceGroupName $rgName `
  -TemplateFile "VHDtoImage.json" `
  -userStorageAccountName $storageaccount `
  -dnsNameForPublicIP $vmName `
  -subscriptionId $subId `
  -location $location `
  -vmName $vmName `
  -vhdUrl $vhdUrl `
  -vmSize $vmSize `
  -publicIPAddressName "myPublicIP1" `
  -virtualNetworkName "myVNET1" `
  -nicName "myNIC1" `
  -adminUserName "isv" `
  -adminPassword (Read-Host -AsSecureString "Enter admin password")

How do I test a hidden preview image?

Use the following steps to test a preview image that is hidden from the marketplace.

First, ensure that the subscription used to test the preview image has been added to the preview audience for the offer within Partner Center. If not, the subscription ID needs to be added to the preview audience and the offer needs to be published again for the update to take effect. For instructions, see Add a preview audience for a virtual machine offer or refer to Updating the preview audience later in this article.

  1. In Azure portal, select Virtual Machines.

  2. Select + Create and + Virtual machine from the drop-down menu to open the Create a virtual machine screen.

  3. Complete the fields according to the appropriate configuration needed for deploying and testing the preview image. Fill out all applicable tabs until you reach the Review + Create tab.

    Important

    It doesn't matter what image is selected here as this will be changed later to the image that you're looking to test. However, you must ensure that the image is either a 1st party or 3rd party image depending on whether you're testing an image within a CoreVM or VM offer. In other words, for CoreVM offers, select a 1st party image and for VM offers, select a 3rd party image. This is important as it will affect properties generated within the ARM template that you'll later use.

  4. On the Review + Create tab, select Download a template for automation. Don't select Create.

  5. You're redirected to the ARM template within the Azure portal. Select Download.

  6. Navigate to your downloads through File Explorer to find the downloaded .zip file. Save the file locally on your computer and extract all files within the folder. There should be two files available: a parameters file and a template file.

  7. Open both files in a code editor such as Visual Studio Code.

  8. In the template file, edit the imageReference with your publisherID, offerID, skuID, and image version. Be sure to append -preview to the offerID. By specifying the image version, you can test a lower version image. Otherwise, you can specify latest to test the latest image version in the plan. For instructions on where to find this information, see Image Reference details.

  9. Further down in the template file, update the plan section with your plan name, publisherID, and product information. Name is the same as the skuID used in step 8. Product is the same as the offerID used in step 8 (with -preview appended). Select Save.

    Important

    This step is only applicable to VM offer types (Plans under this offer have the plan information included), NOT for CoreVM offers.

  10. In the parameters file, remove the adminPassword parameter. When you downloaded the template, it set this parameter as null. However, the password is a secure string so you can proceed with the same password that you set within Azure portal. Select Save.

  11. Sign in to the Azure portal and open Cloud Shell from the top navigation bar. Choose Bash when prompted.

  12. In Cloud Shell, select Upload/Download files and upload your template file and parameter file. You must upload each file one at a time. After uploading, confirm the files exist by running:

    ls
    
  13. Verify that your parameter file follows the ARM parameter schema. The correct format is:

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "virtualMachineName": {
          "value": "myVmName"
        }
      }
    }
    

    Note

    Every parameter must exist in the template file. Extra or unused parameters cause validation to fail.

  14. (Recommended) Validate the deployment before creating resources:

    az deployment group validate \
      --resource-group <Name of RG> \
      --template-file template.json \
      --parameters @parameter.json
    
  15. (Optional) Preview what Azure will create or modify using what-if:

    az deployment group what-if \
      --resource-group <Name of RG> \
      --template-file template.json \
      --parameters @parameter.json
    
  16. Deploy the template using one of the following commands:

    Azure CLI (Bash):

    az deployment group create \
      --resource-group <Name of RG> \
      --template-file template.json \
      --parameters @parameter.json
    

    PowerShell:

    New-AzResourceGroupDeployment -ResourceGroupName <Name of RG> -TemplateFile template.json -TemplateParameterFile parameter.json
    

    Important

    PS/CLI deployment using VM creation commands directly will not work. This will return a NotFound error for -preview images. You must use ARM template deployment as shown above.

  17. After deployment, check the deployment status:

    az deployment group list \
      --resource-group <Name of RG> \
      -o table
    

    To view details for a specific deployment:

    az deployment group show \
      --resource-group <Name of RG> \
      --name <deployment-name>
    
  18. Verify which resources were created:

    az deployment operation group list \
      --resource-group <Name of RG> \
      --name <deployment-name> \
      -o table
    

The hidden image should now be deployed within the specified resource group and is ready for testing and validation.

Common deployment errors

  • "Parameters were supplied but don't correspond to the template" — Remove unused parameters from the parameter file, or add the missing parameter definition to the template file.
  • "Unable to parse parameter: @parameter.json" — Ensure the file is uploaded and correctly named, follows the ARM parameter schema, and that you're running the command from the correct directory.

Updating the preview audience

The preview audience can be updated by performing the following steps:

  1. Sign in to Partner Center.
  2. On the Commercial Marketplace Overview page, search and select your VM offer.
  3. Navigate to the Preview audience page, where you see the list of subscription IDs that can test and validate the offer when it is in preview. Ensure that the subscription being used to test the preview image has been added to the preview audience.
  4. If the subscription ID isn't found within the Preview audience, add it. Then, save your changes and republish the offer. The offer must be republished in order for the changes to take effect.

Image Reference details

How to find your Publisher ID:

Go to Account Settings within Partner Center. Within Legal Info, under the Developer tab, you find the details of your account including the Publisher ID.

How to find your Offer ID:

Within the offer in Partner Center, you can find the offer ID in the left navigation panel. Be sure to append -preview to the Offer ID within the ARM template.

How to find the SKU ID:

Within the plan overview, each Plan ID is found under the respective plan name. The Plan ID is the same as the SKU ID.

How to find the image version:

The image version is denoted as the disk version within the technical configuration page of Partner Center. Navigate to the image you're looking to test in preview and find the respective disk version.

Publishing VM images to Microsoft Marketplace from your Azure Compute Gallery requires you to set permissions so that Partner Center can acquire the images hosted within your gallery. This is a two-step process:

Step 1: Register the resource provider

Register the Microsoft.PartnerCenterIngestion resource provider in the subscription that contains your Compute Gallery. This provisions the required service principals in your tenant.

PowerShell:

Connect-AzAccount
Set-AzContext -Subscription <SubscriptionId>
Register-AzResourceProvider -ProviderNamespace Microsoft.PartnerCenterIngestion
Get-AzResourceProvider -ProviderNamespace Microsoft.PartnerCenterIngestion

Azure CLI:

az login
az account set --subscription <subscriptionId>
az provider register --namespace Microsoft.PartnerCenterIngestion
az provider show --namespace Microsoft.PartnerCenterIngestion

Step 2: Assign the Compute Gallery Image Reader role

Grant the role to both Microsoft Partner Center Resource Provider and Compute Image Registry service principals, scoped to your gallery:

PowerShell:

$galleryId = (Get-AzGallery -ResourceGroupName <resource-group> -GalleryName <gallery-name>).Id
$sp1 = (Get-AzADServicePrincipal -SearchString "Microsoft Partner Center Resource Provider").Id
$sp2 = (Get-AzADServicePrincipal -SearchString "Compute Image Registry").Id
New-AzRoleAssignment -ObjectId $sp1 -RoleDefinitionId cf7c76d2-98a3-4358-a134-615aa78bf44d -Scope $galleryId
New-AzRoleAssignment -ObjectId $sp2 -RoleDefinitionId cf7c76d2-98a3-4358-a134-615aa78bf44d -Scope $galleryId

You can also grant access through the Azure portal by navigating to your Compute Gallery > Access control (IAM) > Add role assignment and assigning the Compute Gallery Image Reader role to both service principals.

Tip

Use a dedicated Compute Gallery for publishing to Partner Center and only grant permissions to that gallery, not at the subscription level.

For full details, see Create a virtual machine using your own image.

What are common SAS URI errors when publishing a VM image?

The following table shows common shared access signature (SAS) URI errors and suggested fixes:

Issue Failure Message Fix
"?" not found in SAS URI Must be a valid Azure shared access signature URI. Ensure the SAS URI includes the "?" character between the endpoint URL and the connection string.
"st" parameter not in SAS URI Specified SAS URL can't be reached. Update the SAS URI with a proper Start Date ("st") value.
"se" parameter not in SAS URI The end date parameter (se) is required. Update the SAS URI with a proper End Date ("se") value.
"sp=r" not in SAS URI Missing Permissions (sp) must include 'read' (r). Update the SAS URI with permissions set as Read ("sp=r").
Authorization error Failure: Copying Images. Not able to download blob due to authorization error. Review and correct the SAS URI format. Regenerate if necessary.
"st" and "se" don't have full date-time format The start time parameter (st) isn't a valid date string. Start Date and End Date parameters must use full date-time format (YYYY-MM-DDT00:00:00Z). Shortened values are invalid.

Tip

Before submitting a SAS URI, verify that it includes your VHD filename (ending in .vhd), that sp=r appears in the URI, and that you can test-download the blob by pasting the URI in a browser.

For more details, see Get a SAS URI for your VM image.

How do I generalize a VM image before publishing?

All images in Microsoft Marketplace must be reusable in a generic fashion. The operating system VHD must be generalized, which removes all instance-specific identifiers and software drivers from the VM.

For Windows:

Generalize using the sysprep tool.

Warning

After you run sysprep, turn the VM off until it's deployed because updates might run automatically. This shutdown avoids subsequent updates from making instance-specific changes to the OS or installed services. For more information, see Generalize a Windows VM.

For Linux:

  1. Connect to your Linux VM using an SSH client.
  2. Run: sudo waagent –deprovision+user and type Y to confirm.
  3. Exit the SSH client.
  4. If Microsoft Defender for Endpoint (MDE) is installed, uninstall it:
    • RHEL, CentOS, Oracle: sudo yum remove mdatp
    • SLES: sudo zypper remove mdatp
    • Ubuntu, Debian: sudo apt-get purge mdatp
    • Mariner: sudo dnf remove mdatp
  5. In the Azure portal, stop and deallocate the VM.

Important

If Microsoft Defender for Cloud is enabled on the subscription where you create the VM, and you don't remove MDE, any VM created from this image will auto-enroll in the Defender for Endpoint portal, even if deployed in a different tenant.

For full details, see Create a VM image using an approved base.

How do I deprecate a VM image, plan, or offer?

Deprecation is the removal of a VM offer (or part of it) from Microsoft Marketplace so it's no longer available for new deployments. The deprecation feature replaces the previous stop sell feature and complies with the Azure 90-day wind down period.

You can deprecate at three levels:

  • Image version — Removes an individual VM image version
  • Plan — Removes a plan and all images within it
  • Offer — Removes the entire VM offer, including all plans and images

Key things to know:

  • Existing deployments are not affected by deprecation.
  • Existing virtual machine scale set deployments can't be scaled out after deprecation.
  • Customers with active deployments are notified before the deprecation date.
  • When deprecating an offer, it immediately becomes unsearchable in Marketplace.
  • Deprecation can be reversed by restoring the deprecated item.

Tip

Before deprecating, review the Usage dashboard to understand current usage. For high-usage offers, consider hiding the plan first to minimize discoverability.

For step-by-step instructions, see Deprecate or restore a virtual machine offer.

How do I remove Microsoft Defender for Endpoint (MDE) from my image before publishing?

If MDE is installed on a VM image and not removed before publishing, any VM created from the image will auto-enroll in the Defender for Endpoint portal — even when deployed to a different tenant without Microsoft Defender for Cloud enabled.

To remove MDE, run the appropriate uninstall command for your OS before generalizing the image:

OS Command
RHEL, CentOS, Oracle sudo yum remove mdatp
SLES and variants sudo zypper remove mdatp
Ubuntu, Debian sudo apt-get purge mdatp
Mariner sudo dnf remove mdatp

For Windows, uninstall Microsoft Defender for Endpoint through Settings > Apps or by disabling Microsoft Defender for Cloud on the subscription before creating the VM image.

For more details, see Create a VM image using an approved base.

What is the difference between Generation 1, Generation 2, and ARM64 image types?

When creating a VM plan, you choose an image type that defines the virtual hardware generation:

  • x64 Gen 1 — Uses BIOS-based boot. Supports most existing VM sizes.
  • x64 Gen 2 — Uses UEFI-based boot. Supports larger memory sizes, Intel SGX, and is required for Trusted Launch and Confidential VM security types.
  • ARM64 Gen 2 — For ARM-based processors. Used for workloads optimized for ARM architecture.

You can add multiple image types to a single plan. However, once a generation is published, it requires at least one image version to remain available. To remove an entire generation, you must deprecate the plan.

For more details on the differences, see Support for generation 2 VMs on Azure and Technical configuration for a VM plan.

What is the difference between preview audience, private audience, and hidden plans?

These three concepts control visibility and access at different stages:

Concept When it applies Who can access Identified by
Preview audience Before the offer is published live Only subscribers in the preview list Azure subscription IDs
Private audience After the offer is live Only subscribers/tenants in the private list Subscription IDs and/or tenant IDs
Hidden plan After the offer is live Anyone with the direct link or ARM template Not searchable in Marketplace but deployable

Key differences:

  • A preview audience can access all plans (including private ones) for validation before publishing.
  • A private audience is plan-specific and restricts who can purchase or deploy after the offer is live.
  • A hidden plan isn't searchable in Marketplace but any user can deploy it via direct link, CLI, or ARM template.

For more details, see Add a preview audience and Plan pricing and availability.

How do I configure security types (Trusted Launch or Confidential VMs) for my plan?

Security types are available for plans that support x64 Gen 2 image types. You can configure the following:

  • Standard — No additional security features.
  • Trusted Launch — Provides secure boot and vTPM to protect against boot-level attacks. See Trusted launch.
  • Trusted Launch and Confidential — Adds hardware-based memory encryption on top of Trusted Launch. See Confidential VMs.

Important

After publishing, the security type can only be upgraded to a higher option (for example, from Trusted Launch to Trusted Launch and Confidential). It can never be downgraded.

Configure security types on the Technical configuration page of your plan in Partner Center. For more details, see Technical configuration for a VM plan.

What VM technical properties should I configure before publishing?

On the Technical configuration page in Partner Center, you can flag which technical properties your VM image supports. Setting these correctly is important for both certification and customer experience.

Available properties include:

  • Supports backup — The VM image supports Azure Backup.
  • Supports accelerated networking — The VM uses single root I/O virtualization (SR-IOV) for high-performance networking.
  • Supports cloud-init configuration — The VM supports cloud-init for Linux provisioning.
  • Supports extensions — The VM supports Azure VM extensions.
  • Is a network virtual appliance — The VM acts as a network appliance (firewall, WAN optimizer, etc.).
  • Remote desktop or SSH disabled — The VM doesn't allow RDP/SSH connections.
  • Requires custom ARM template for deployment — The VM requires a custom ARM template (for example, when multiple NICs or extra subnets are needed).
  • Supports NVMe — The VM supports NVMe disk controllers.
  • Supports hibernation — The VM supports hibernate/resume.

Tip

If your image requires a custom ARM template for deployment, make sure to enable that property. Otherwise, the certification team may fail your image for provisioning issues during standard deployment testing.

For more details, see Technical configuration for a VM plan.

Can I reuse technical configuration across plans?

Yes. When creating a new plan, you can choose to reuse images from another plan. This is useful when you want to offer the same VM image under different pricing models (for example, BYOL and pay-as-you-go).

To reuse configuration, select Yes, I want to reuse images from another plan on the Technical configuration page when creating the plan. Then select the source plan from the dropdown.

Important

Once you detach a plan from its reused configuration, the action is irreversible — you can't re-attach it to reuse the same configuration.

For more details, see Technical configuration for a VM plan.