Edit

Share via


Create and deploy VM Application

VM Application is a resource type in Azure Compute Gallery that simplifies management, sharing, and global distribution of applications for your virtual machines. Learn more about VM Application

To create and deploy applications on Azure VM, first package and upload your application to Azure Storage Account as a storage blob. Then create Azure VM application resource and VM application version resource referencing these storage blobs. Finally, deploy the application on any VM or Virtual Machine Scale Set by passing application reference in applicationProfile.

Prerequisites

  1. Create Azure storage account and storage container. This container is used to upload your application files. It's recommended to use storage account with anonymous access disabled for added security.
  2. Create Azure Compute Gallery for storing and sharing application resources.

Package the application

Screenshot showing the folder structure recommended for uploading and creating VM Applications.

1. Package the application files

  • If your application installation requires a single file (.exe, .msi, .sh, .ps, etc.) then you can use it as is.
  • If your application installation requires multiple files (Executable file with configuration file, dependencies, manifest files, scripts, etc.), then you must archive it (using .zip, .tar, .tar.gz, etc.) into a single file.
  • For microservice application, you can package and publish each microservice as a separate Azure VM Application. This facilitates application reusability, cross-team development, and sequential installation of microservices using order property in the applicationProfile.

2. (Optional) Package the application configuration file

  • You can optionally provide the configuration file separately. This reduces the overhead of archiving and unarchiving application packages. Configuration files can also be passed during app deployment enabling customized installation per VM.

3. Create the install script

After the application and configuration blob is downloaded on the VM, Azure executes the provided install script to install the application. The install script is provided as a string and has a maximum character limit of 4,096 chars. The install commands should be written assuming the application package and the configuration file are in the current directory.

There may be few operations required to be performed in the install script

  • (Optional) Use the right command interpreter The default command interpreter used by Azure are /bin/bash on Linux OS and cmd.exe on Windows OS. It's possible to use a different interpreter like Chocolatey or PowerShell, if its installed on the machine. Call the executable and pass the commands to it. E.g., powershell.exe -command '<powershell command>'. If you're using PowerShell, you need to be using version 3.11.0 of the Az.Storage module.

  • (Optional) Rename application blob and configuration blob Azure can't retain the original file name and the file extensions. Therefore, the downloaded application file and the configuration file have a default name as "MyVMApp" and "MyVMApp-config" without a file extension. You can rename the file with the file extension using the install script or you can also pass the names in packageFileName and configFileName properties of the publishingProfile of VM Application version resource. Azure will then use these names instead of default names while downloading the files.

  • (Optional) Move application and configuration blob to appropriate ___location Azure downloads the application blob and configuration blob to following locations. The install script must move the files to appropriate locations when necessary.

    Linux: /var/lib/waagent/Microsoft.CPlat.Core.VMApplicationManagerLinux/<application name>/<application version>

    Windows: C:\Packages\Plugins\Microsoft.CPlat.Core.VMApplicationManagerWindows\1.0.16\Downloads\<application name>\<application version>

  • Unarchive application blob For archived application packages, it needs to be unarchived before installing the application. It's recommended to use .zip or .tar since most OS has built-in support for unarchiving these formats. For other formats, make sure the Guest OS provides support.

  • (Optional) Set right execution policy and permissions After unarchiving, file permissions could be reset. It's a good practice to set the right permissions before executing the files.

  • Convert the script to string The install script is passed as a string for the install property in the publishingProfile of Azure VM Application version resource.

Here are sample install scripts based on the file extension of the application blob

#!/bin/bash

# Rename blobs
mv MyVMApp app.tar
mv MyVMApp-config app-config.yaml

# Unarchive application
mkdir -p app
tar -xf app.tar -C app

# Set permissions
chmod -R +x app
chmod -R +r app

# Install the script (example: install.sh with config)
bash ./app/install.sh --config app-config.yaml

# OR Install the .deb package (example: install.deb without config)
# sudo dpkg -i ./app/install.deb

# OR Install the .rpm package (example: install.rpm without config)
# sudo rpm -ivh ./app/install.rpm

Script as string:

"#!/bin/bash\nmv MyVMApp app.tar\nmv MyVMApp-config app-config.yaml\nmkdir -p app\ntar -xf app.tar -C app\nchmod -R +x app\nchmod -R +r app\nbash ./app/install.sh --config app-config.yaml\n# sudo dpkg -i ./app/install.deb\n# sudo rpm -ivh ./app/install.rpm"

4. Create the delete script

The delete script enables you to define the delete operations for the application. The delete script is provided as a string and has a maximum character limit of 4,096 characters. Write the delete commands assuming the application package and the configuration file are in the current directory.

There may be few operations that delete script must perform.

  • Uninstall application: Properly uninstall the application from the VM. For example, execute uninstall.exe on Windows or sudo apt remove app on Linux.

  • Remove residual files: Delete residual applications files from the VM. For example, execute Remove-Item -Path "$PWD\*" -Recurse -Force -ErrorAction SilentlyContinue on Windows or sudo rm -rf ./* ./.??* on Linux.

Upload the application files to Azure storage account

1. Upload your application and configuration files to a container in an Azure storage account.

Your application can be stored in a block or page blob. If you choose to use a page blob, you need to byte align the files before you upload them. Use the following sample to byte align your file.

inputFile="<the file you want to pad>"

# Get the file size
fileSize=$(stat -c %s "$inputFile")

# Calculate the remainder when divided by 512
remainder=$((fileSize % 512))

if [ "$remainder" -ne 0 ]; then
    # Calculate how many bytes to pad
    difference=$((512 - remainder))
    
    # Create padding (empty bytes)
    dd if=/dev/zero bs=1 count=$difference >> "$inputFile"
fi

2. Generate SAS URL for the application package and the configuration file

Once the application and configuration files are uploaded to the storage account, you need to generate a SAS URL with read privilege for these blobs. These SAS URLs are then provided as reference while creating the VM Application version resource. For Storage accounts enabled for anonymous access, blob URL can also be used. However, it's recommended to use SAS URL for improved security. You can use Storage Explorer to quickly create a SAS URI if you don't already have one.


#!/bin/bash

# === CONFIGURATION ===
STORAGE_ACCOUNT="yourstorageaccount"
CONTAINER_NAME="yourcontainer"
LOCAL_FOLDER="./your-local-folder"
SAS_EXPIRY_HOURS=24

# === LOGIN (if not already logged in) ===
az login --only-show-errors

# === CREATE CONTAINER IF NOT EXISTS ===
az storage container create \
  --name $CONTAINER_NAME \
  --account-name $STORAGE_ACCOUNT \
  --auth-mode login \
  --only-show-errors

# === UPLOAD FILES ===
az storage blob upload-batch \
  --account-name $STORAGE_ACCOUNT \
  --destination $CONTAINER_NAME \
  --source $LOCAL_FOLDER \
  --auth-mode login \
  --only-show-errors

# === GENERATE SAS URLs ===
echo "Generating SAS URLs..."
FILES=$(find $LOCAL_FOLDER -type f)

for FILE in $FILES; do
  BLOB_NAME="${FILE#$LOCAL_FOLDER/}"
  EXPIRY=$(date -u -d "+$SAS_EXPIRY_HOURS hours" '+%Y-%m-%dT%H:%MZ')

  SAS_TOKEN=$(az storage blob generate-sas \
    --account-name $STORAGE_ACCOUNT \
    --container-name $CONTAINER_NAME \
    --name "$BLOB_NAME" \
    --permissions r \
    --expiry $EXPIRY \
    --auth-mode login \
    -o tsv)

  SAS_URL="https://${STORAGE_ACCOUNT}.blob.core.windows.net/${CONTAINER_NAME}/${BLOB_NAME}?${SAS_TOKEN}"
  echo "$BLOB_NAME: $SAS_URL"
done

Create the VM Application

To create the VM Application, first create the VM Application resource, which describes the application. Then create a VM Application Version resource within it, which contains the VM application payload and scripts to install, update, and delete the application. Payload is supplied using SAS URL to the blob container in Azure Storage Account.

Refer schema for VM Application and VM Application version resource to learn more about each property.

Create the VM Application definition using the 'create gallery application API'

PUT
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/galleries/{galleryName}/applications/{applicationName}?api-version=2024-03-03

{
    "___location": "West US",
    "name": "myApp",
    "properties": {
        "supportedOSType": "Windows | Linux",
        "endOfLifeDate": "2020-01-01",
	"description": "Description of the App",
	"eula": "Link to End-User License Agreement (EULA)",
	"privacyStatementUri": "Link to privacy statement for the application",
	"releaseNoteUri": "Link to release notes for the application"
    }
}

Create a VM application version using the 'create gallery application version API'.

PUT
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/galleries/{galleryName}/applications/{applicationName}/versions/{versionName}?api-version=2024-03-03

{
  "___location": "$___location",
  "properties": {
    "publishingProfile": {
      "source": {
        "mediaLink": "$mediaLink",
        "defaultConfigurationLink": "$configLink"
      },
      "manageActions": {
        "install": "echo installed",
        "remove": "echo removed",
        "update": "echo update"
      },
      "targetRegions": [
        {
          "name": "West US",
          "regionalReplicaCount": 1
        },
	{
	  "name": "East US"
	}
      ]
      "endofLifeDate": "datetime",
      "replicaCount": 1,
      "excludeFromLatest": false,
      "storageAccountType": "PremiumV2_LRS | Premium_LRS | Standard_LRS | Standard_ZRS"
      "safetyProfile": {
	"allowDeletionOfReplicatedLocations": false
      }
      "settings": {
	"scriptBehaviorAfterReboot": "None | Rerun",
	"configFileName": "$appConfigFileName",
	"packageFileName": "$appPackageFileName"
      }
   }
}

Deploy the VM Apps

One or more VM Applications can now be referenced in the applicationProfile of Azure VM or Azure VM Scale Sets. Azure then pulls the payload of the VM Application and installs it on each VM using the provided install script. The order property defines the sequential order in which the VM Applications are installed on the VM.

Refer schema of applicationProfile of the VM / Virtual Machine Scale Set to learn more about each property.

To add a VM application version to a VM, perform a PUT on the VM.

PUT
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{VMName}?api-version=2024-03-03

{
  "properties": {
    "applicationProfile": {
      "galleryApplications": [
        {
          "order": 1,
          "packageReferenceId": "/subscriptions/{subscriptionId}/resourceGroups/<resource group>/providers/Microsoft.Compute/galleries/{gallery name}/applications/{application name}/versions/{version | latest}",
          "configurationReference": "{path to configuration storage blob}",
          "treatFailureAsDeploymentFailure": false
        }
      ]
    }
  },
  "name": "{vm name}",
  "id": "/subscriptions/{subscriptionId}/resourceGroups/{resource group}/providers/Microsoft.Compute/virtualMachines/{vm name}",
  "___location": "{vm ___location}"
}

To apply the VM application to a uniform scale set:

PUT
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{VMSSName}?api-version=2024-03-03

{
  "properties": {
    "virtualMachineProfile": {
      "applicationProfile": {
        "galleryApplications": [
          {
            "order": 1,
            "packageReferenceId": "/subscriptions/{subscriptionId}/resourceGroups/<resource group>/providers/Microsoft.Compute/galleries/{gallery name}/applications/{application name}/versions/{version | latest}",
            "configurationReference": "{path to configuration storage blob}",
            "treatFailureAsDeploymentFailure": false
          }
        ]
      }
    }
  },
  "name": "{vm name}",
  "id": "/subscriptions/{subscriptionId}/resourceGroups/{resource group}/providers/Microsoft.Compute/virtualMachines/{vm name}",
  "___location": "{vm ___location}"
}

The response includes the full VM model. The following are the relevant parts.

{
  "name": "{vm name}",
  "id": "{vm id}",
  "type": "Microsoft.Compute/virtualMachines",
  "___location": "{vm ___location}",
  "properties": {
    "applicationProfile": {
      "galleryApplications": ""
    },
    "provisioningState": "Updating"
  },
  "resources": [
    {
      "name": "VMAppExtension",
      "id": "{extension id}",
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "___location": "centraluseuap",
      "properties": "@{autoUpgradeMinorVersion=True; forceUpdateTag=7c4223fc-f4ea-4179-ada8-c8a85a1399f5; provisioningState=Creating; publisher=Microsoft.CPlat.Core; type=VMApplicationManagerLinux; typeHandlerVersion=1.0; settings=}"
    }
  ]
}

Next steps

Learn more about Azure VM Applications. Learn to manage, update or delete Azure VM Applications.