A simple and costly mistake which can often catch Azure administrators out is the 2 states a VM can be in when powered off, it will either be in a costly Stopped state or Stopped (deallocated) state, the difference is that when a VM is shutdown using the normal operating system method it goes into a Stopped state but although shut down the resources are still allocated to it and therefore the full costs are incurred as if the VM was powered on.

This guide shows you how to initiate a shutdown and deallocate from within the guest operating system using App registration along with a service principal object.

The image below shows when the VM is shut down through the operating systems normal method which goes into a Stopped state which will incur full charges as if powered on. This can easily be deallocated by using the Stop button highlighted below but you do not want to have to login into the Azure portal every time to do this.

The following image shows when the VM is powered down correctly in a Stopped (deallocated) state with no charges as the resources have been deallocated.

Best Practice here if used within a production environment would be to use a Managed Service Identity explained in my article here as this ensures no credentials are set client side but this service principal method could be used in a development environment.

For further information on Application and service principal objects in Azure Active Directory please see https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals

Windows Instructions

Within Azure AD go to App Registration and select New Registration

Enter a logical name, skip the URI section and click Register


Once registered, select Certificates and Secrets and select New Client Secret

Add a description and select the required expiry length.

Once the client secret has been created, copy this value to notepad to be used in your VM later

On the VM itself, select Access Control and click Add

Add the App registration account created earlier with the role Virtual Machine Contributor which will give it the permission to shutdown then save the changes

With the permissions now set you can now test from your VM.

Please be aware these instructions have only been tested on Windows 2019 running PowerShell 5

Right click PowerShell and Run As Administrator on the VM, install the Azure Module's with the following command

Install-Module -Name Az -AllowClobber -Scope AllUsers

Get the credentials into a variable by running the following command, the "username" as such is the application id of the service principal, for example, 95c0e31d-1b4c-3c29-9435-dcd742c6fcac
Your password is the client secret created earlier

$pscredential = Get-Credential

Once the credentials have been written to the variable, connect to the tenant with the following command, for speed the tenant id also can also be found on the app registration page. This step will also store the service principal secret for future use.

Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant <tenant id>

Verify you have connected successfully and can see the VM(s) by running the following command

You can run the following script which will shut down and deallocate

Stop-AzVM -Name <VM name> -ResourceGroupName <RG Name> -Force

Deallocate in the Azure Portal

If the VM is already in a Stopped state, click the Stop button and after 1 minute it should be in a Stopped (Deallocated)

Auto Shutdown

Alternatively if applicable, you can set the Auto-shutdown within the VM settings as per the image below which will shut down and deallocate the VM at the specified time which is useful to set anyway just in case you accidently leave the VM running.
This method gives you a level of control but not as granular as what you can achieve using the managed identity method.