The situation
You can reach the VM on port 3389 or 22, but the credentials don't work. The local admin password was never put in the vault, the person who built it has left, or the SSH private key was on a laptop that got rebuilt. You don't need to rebuild the VM. Azure can reset the credentials from outside the guest through the VMAccess extension, which the Azure VM agent runs.
This post covers:
- Checking that the VM agent is healthy (VMAccess depends on it)
- Resetting a Windows local admin password
- Resetting a Linux password or SSH key, and repairing a broken
sshd_config - Fallbacks when VMAccess can't run
If the VM isn't reachable on the network at all, this isn't your problem. Start with NSGs, routes and boot diagnostics instead.
Before you start
Permissions
You need Microsoft.Compute/virtualMachines/extensions/write on the VM. Virtual Machine Contributor has it. Reader doesn't. If you can reset the password, you effectively have local admin, so keep that role assignment tightly scoped.
Check the VM agent
VMAccess is an extension, so the VM agent has to be running and reporting Ready:
az vm get-instance-view -g rg-app -n vm-app01 \
--query "{power:instanceView.statuses[1].displayStatus, agent:instanceView.vmAgent.statuses[0].displayStatus, version:instanceView.vmAgent.vmAgentVersion}" -o table
| Agent status | What it means | Next step |
|---|---|---|
Ready | Extensions can run | Go ahead with VMAccess |
Not Ready | Agent is stopped, crashed or can't reach the platform | Fix the agent first, or use the fallbacks below |
Empty / no vmAgent | Agent not installed (common on custom images) | Use the fallbacks below |
Tip
The agent talks to the platform on
168.63.129.16. If a guest firewall or a forced-tunnel route blocks that address, the agent reports Not Ready and every extension fails, VMAccess included.
Windows: reset the local admin password
Azure CLI
az vm user update -g rg-app -n vm-win01 \
--username azureadmin \
--password '<new-strong-password>'
Behind the scenes this deploys the VMAccessAgent extension (publisher Microsoft.Compute). Here's how it handles the username you give it:
| You pass | Result |
|---|---|
| The existing local admin name | That account's password is reset |
| A different name | A new local admin account is created with that password. The existing admin isn't renamed. |
The password has to meet the Windows complexity rules. If it doesn't, the extension reports a failure and the old password stays.
Az PowerShell
$cred = Get-Credential -UserName azureadmin -Message "New local admin password"
Set-AzVMAccessExtension -ResourceGroupName rg-app -VMName vm-win01 `
-Name VMAccessAgent -Location westeurope `
-UserName $cred.UserName -Password $cred.GetNetworkCredential().Password `
-TypeHandlerVersion "2.4"
Type handler versions change over time. Run az vm extension image list --publisher Microsoft.Compute --name VMAccessAgent --location <region> -o table to see the current ones.
RDP is enabled but still refuses connections
If the password is right but RDP is broken (the service is disabled, the port has been changed, or the firewall rule has been removed), the portal option Help > Reset password > Reset configuration only restores the default Remote Desktop configuration. It's the same extension, just without credentials.
Warning
VMAccess does not support domain controllers. On a DC, local accounts don't exist in the usual sense, and the extension fails. Use Run Command with
net useror the documented AD recovery procedures instead.
Linux: reset a password or SSH key
The CLI uses the VMAccessForLinux extension (publisher Microsoft.OSTCExtensions).
Add a new SSH public key
az vm user update -g rg-app -n vm-lnx01 \
--username azureuser \
--ssh-key-value ~/.ssh/id_ed25519.pub
The key is added to that user's authorized_keys. Existing keys stay where they are, so if you're responding to a compromised key, remove the old one afterwards (see below). If the user doesn't exist, it's created and given sudo rights.
Reset a password
az vm user update -g rg-app -n vm-lnx01 \
--username azureuser \
--password '<new-strong-password>'
A new password won't help if sshd has PasswordAuthentication no, which is the default on most marketplace images built with SSH keys. In that case use a key, or connect through the Serial Console.
Repair the SSH daemon configuration
Use this when someone edited /etc/ssh/sshd_config and sshd now refuses connections or won't start:
az vm user reset-ssh -g rg-app -n vm-lnx01
This resets the SSH configuration to the defaults and restarts the daemon. Any hardening you added (custom port, AllowUsers, ciphers) is lost, so put it back from config management afterwards.
Remove a user or an old key
az vm user delete -g rg-app -n vm-lnx01 --username olduser
VMAccess can't remove a single key from authorized_keys. For that, use Run Command:
az vm run-command invoke -g rg-app -n vm-lnx01 \
--command-id RunShellScript \
--scripts "sed -i '/old-laptop-key-comment/d' /home/azureuser/.ssh/authorized_keys"
Verify and clean up
Check the extension result:
az vm extension list -g rg-app --vm-name vm-lnx01 \
--query "[].{name:name, state:provisioningState}" -o table
az vm get-instance-view -g rg-app -n vm-lnx01 \
--query "instanceView.extensions[?contains(name,'VMAccess')].statuses[0].message" -o tsv
Then:
- Sign in with the new credentials.
- Store the password or key in Key Vault, not in a ticket or a chat.
- Optionally remove the extension so stale settings don't sit on the VM:
az vm extension delete -g rg-app --vm-name vm-lnx01 -n VMAccessForLinux(on Windows,-n VMAccessAgent, or whatever name it was deployed with).
Caution
On a VM that's part of a scale set or rebuilt from an image, a reset on one instance doesn't change the model. The next reimage brings back the old credentials. Update the scale set model or the image pipeline as well.
When VMAccess fails
| Symptom | Likely cause | Fix |
|---|---|---|
Extension times out, agent Not Ready | Agent stopped or no route to 168.63.129.16 | Restart the agent through Serial Console; fix the guest firewall or UDR |
VMAccess is not supported on domain controller | The VM is a DC | Use Run Command with net user, or AD recovery |
| Password rejected | Complexity or length rules | Use a longer password with mixed character classes |
| Extension succeeds but SSH still denies | PasswordAuthentication no, wrong user, file permissions on ~/.ssh | Use a key; run az vm user reset-ssh; fix chmod 700 ~/.ssh and 600 authorized_keys |
| Every operation fails with policy errors | Azure Policy blocks the extension | Check RequestDisallowedByPolicy in the Activity Log |
Fallback 1: Run Command
Run Command also goes through the agent, but it's useful when VMAccess is blocked or can't run, for example on a DC:
az vm run-command invoke -g rg-app -n vm-win01 \
--command-id RunPowerShellScript \
--scripts "net user azureadmin '<new-strong-password>'"
Warning
The script text, including the password, is visible in the VM's extension logs and in your shell history. Rotate the password again once you're signed in.
Fallback 2: Serial Console
When the agent is dead, Serial Console gives you a text login to the guest. It needs boot diagnostics enabled and a local account with a password that works. On Linux you can boot to single-user mode from GRUB to reset root. On Windows, use SAC (cmd, then ch -si 1) if you have any working local credentials.
Fallback 3: offline repair
As a last resort, attach a copy of the OS disk to a rescue VM (az vm repair create, from the vm-repair CLI extension), fix the account or sshd_config offline, then swap the disk back. Take a snapshot first.
Prevent it next time
- Store every VM's local admin credentials in Key Vault when you build it, and rotate them on a schedule. On Windows, consider Windows LAPS.
- Prefer Microsoft Entra ID login for VMs (
AADSSHLoginForLinux/AADLoginForWindowsextensions plusaz ssh vm), so access comes from role assignments instead of shared local passwords. - Keep the VM agent in your build checklist and alert when it isn't
Ready. Every recovery path except offline repair depends on it. - Enable boot diagnostics with a managed storage account so Serial Console is available when you need it.