Useful CLI Commands to script Start and Stop of a Virtual Machine in Microsoft Azure

I am using my virtual machine in Azure to do development tasks. That means, as long as I am not doing any development, I do not need the virtual machine. Accordingly, I deallocate the VM when I’m done, and start it again when there are new development tasks to be completed.

Note: This post is part of a series of postings describing several aspects I found noticeable or good to know when I recently created a virtual machine in Microsoft Azure. “Notes and Observations when setting up a Virtual Machine in Microsoft Azure” gives an overview of all parts of the series.

Starting the Virtual Machine

For security reasons, I have restricted the RDP access via the firewall settings of the VM’s network security group to only grant RDP access to my IP address. When working from home, I do get a new IP address every day. That means I also have to update the firewall settings every day I want to access the VM.

And finally, I have not set a permanent IP address for the VM. So every time it is booted, it has a new IP address, and I need to know it.

Overall, there are four things I need to do when starting the VM:

  • Start the Virtual Machine
  • Get my IP address
  • Update the firewall settings to grant RDP access to my IP address of the day
  • Get the IP address of the VM once it is started

As I do not like to do these things manually day by day, I’ve created a small PowerShell script I called StartVM.ps1. The script is using the Azure Command-Line Interface (CLI).

Write-Host 'Starting VM'
az vm start --name <VM-name> --resource-group <source group name>

Write-Host 'VM started, getting client IP address'
$response = Invoke-RestMethod https://<API address to retrieve my IP>

Write-Host 'Updating nsg rule'
az network nsg rule update --nsg-name <nsg name> -g <resource group name> -n <rule name> --source-address-prefixes $response.clientIP --access Allow

Write-Host 'getting public IP'
az vm show -d -g <resource group name>-n <VM name> --query publicIps -o tsv

There is a very simple JSON query expression in the last statement: --query publicIps. In case more complex queries are required to extract specific data from JSON output, the JMESPath Tutorial is very helpful to understand the query syntax. The reason why JMESPath is used is that the Azure CLI commands always return data in JSON format.

az vm list-ip-addresses -n <VM-name> -g <resource group name> -o table

would lead to almost the same result here (print the IP address to the screen), but does not give me the chance to add a link to JMESPath to this post 😉

The usage of $response.clientIP when updating the network security rule is specific to the API I am using to retrieve my external IP address. Depending on the API you are using this needs to be changed. In case you do have a permanent IP address, this step can be omitted.

Stopping the Virtual Machine

To reduce the overall cost of my virtual machine, I manually stop it when I know I do not need it any more. As Chris Pietschmann’s points out in his blog post “Deallocate VM to save Money“, it is not sufficient to stop a virtual machine. It has to be deallocated.

I do also disable RDP access when deallocating the VM. Here is my PowerShell script StopVM.ps1:

Write-Host 'Stopping VM'
az vm deallocate --name <VM name> --resource-group <resource group name>

Write-Host 'Disabling rdp access'
az network nsg rule update --nsg-name <nsg name> -g <resource group name> -n <rule name> --access Deny


Of course, I also have an auto-shutdown implemented for my virtual machine, in case I forget to run my script when I leave for the day. When creating a new VM via the portal, the auto-shutdown settings can be found at the “Management” tab.

Set Auto-shutdown when creating a VM

In case it was missed to configure auto-shutdown on creation, it can be set afterwards. Via the portal, open the VM and go to “Operations / Auto-shutdown”:

Configure VM Auto-shutdown


Notes and Observations when setting up a Virtual Machine in Microsoft Azure
Azure Command-Line Interface (CLI) Documentation
JMESPath Tutorial
Chris Pietschmann’s blog post “Deallocate VM to save Money