You deployed the Azure Migrate appliance, pointed it at vCenter, and waited for the inventory to fill in. Twenty minutes later the project still says 0 servers discovered, or it shows the VMs but every one is flagged “Credentials not provided”, or the count is right but software inventory and dependency mapping are stubbornly blank. Nothing in the portal tells you why — Azure Migrate is deliberately quiet about the appliance’s own health, because the appliance is a machine you run inside your network, and Azure can only report what the appliance manages to send it. The gap between “I deployed it” and “it discovered everything” is where most migration projects lose their first week.
This is the diagnostic playbook for that gap. The Azure Migrate appliance is a lightweight, downloadable VM (or a script-installed Windows Server) running discovery and assessment agents that authenticate to your vCenter Server, Hyper-V hosts, or physical machines, pull configuration and performance data, and push it over HTTPS to your Azure Migrate project. Discovery breaks at one of five seams: the appliance can’t register with the project, it can’t reach the outbound URLs and ports it needs, it can’t authenticate to vCenter or the hosts, it can’t sign in to the guest OS for software inventory and dependency mapping, or the data flows but stalls or arrives partial. Each seam has a specific place that tells the truth — chiefly the appliance configuration manager web app, the appliance’s own services, and the Discovered servers blade with its per-server status column — and a precise fix. You will learn to localise a failure to exactly one seam and stop staring at an empty inventory blade hoping it fills in.
By the end you will stop re-running the setup wizard hoping “this time it works.” When discovery is empty or partial you will know whether you face a registration failure, a blocked URL or port, a proxy that strips authentication, a vCenter account without the right role, a guest credential that doesn’t match the OS, or simply discovery still in its normal first-cycle delay. Knowing which in ten minutes — instead of opening a support case and waiting two days — is what keeps a migration assessment on schedule.
What problem this solves
Azure Migrate sells a frictionless promise: deploy one appliance, and Azure builds a right-sized assessment of your whole estate — VM inventory, CPU and memory utilisation, installed software, and the network dependencies that tell you which servers must move together. That promise holds only when the appliance can do three things in order: register itself to the project, authenticate to your virtualisation layer, and reach Azure over HTTPS continuously. Break any one and the assessment you were promised never materialises, but the portal rarely says so in plain language — it just shows fewer servers than you have, or servers with no detail.
What breaks without this knowledge: a migration lead reports “discovery is done” based on a VM count that is actually missing 40% of hosts behind a second vCenter the appliance can’t reach; an assessment gets built on as-on-premises sizing because performance data never collected, over-provisioning the Azure target and blowing the cloud budget; dependency mapping shows nothing, so an app gets migrated without its database server and fails at cutover. The appliance was working “fine” the whole time — it just never had the credentials, the URL allow-list, or the time to finish.
Who hits this: every team doing a server-based migration assessment with Azure Migrate — VMware (the most common and richest discovery), Hyper-V, and physical/other-cloud servers via the same appliance in different modes. It bites hardest in locked-down networks (a default-deny firewall blocks the non-negotiable outbound URLs/ports), behind authenticating proxies (which break the token flow), in multi-vCenter estates (one appliance, one vCenter — scale is a planning decision), and anywhere guest credentials are needed for the deep data (software inventory and agentless dependency analysis require in-guest sign-in, which most first-time setups skip). The fix is almost never “redeploy the appliance” — it’s “find the blocked seam and unblock exactly that.”
To frame the whole field before the deep dive, here is every failure class this article covers, the question it forces, and the one place to look first:
| Failure class | What you actually see | First question to ask | First place to look | Most common single cause |
|---|---|---|---|---|
| Appliance won’t register | Setup stuck at “Register with Azure Migrate”; project never links | Did the appliance reach login + management URLs? | Appliance config manager → prerequisites; appliance browser test | Blocked Azure URLs / proxy / time skew |
| 0 servers / count stalls | Discovered servers = 0 or frozen below the real total | Did vCenter/host connection succeed, and has a full cycle run? | Config manager → “Add data sources” connection status | Wrong vCenter account role or scope |
| “Credentials not provided” | Servers listed but each row flagged, no OS/software detail | Are guest creds added and do they match the OS? | Discovered servers → per-server credential status | No guest OS credentials supplied |
| Software inventory empty | VM inventory present, “Installed software” blank | Is guest discovery enabled and the account privileged enough? | Server detail → software inventory status | VMware Tools / WinRM / SSH path blocked |
| Dependency mapping empty | No network connections shown for a server | Agentless analysis on? Guest sign-in working? | Discovered servers → dependencies column | Dependency analysis not enabled / no guest creds |
| Discovery stops updating | Was working, now stale; “last updated” frozen | Did connectivity, the project key, or vCenter creds change? | Config manager health + appliance services | Expired creds, blocked URL, or appliance off |
Learning objectives
By the end of this article you can:
- Map any Azure Migrate discovery failure to a specific seam — registration, outbound connectivity, virtualisation-layer authentication, guest-OS authentication, or data-flow stall — and name the most likely cause for each.
- Diagnose a registration failure as a blocked Azure URL, an authenticating proxy breaking the token flow, a time-skew certificate rejection, or a wrong project key — and confirm which from the appliance configuration manager.
- Enumerate the exact outbound URLs and ports the appliance needs (public and government clouds, with and without private endpoints) and prove connectivity from the appliance itself.
- Fix a 0-servers or stalled-count problem by validating the vCenter account’s role and scope, the host connection, and the normal first-cycle discovery timing.
- Resolve “Credentials not provided”, empty software inventory, and empty dependency mapping by supplying and validating the right guest-OS credentials (VMware Tools/WinRM/SSH paths) and enabling agentless dependency analysis.
- Drive the core diagnostic surfaces fluently: the appliance config manager, the appliance services (AzureMigrateTimerService, Gateway, discovery agents), the Discovered servers blade’s status columns, and
az/PowerShell checks for the project and connectivity. - Read the canonical connectivity, credential-priority and account-permission reference tables and pick the right appliance topology for a multi-vCenter or air-gapped estate.
Prerequisites & where this fits
You should already understand the Azure Migrate basics: a Migrate project is the Azure resource that collects discovery and assessment data; an appliance is the on-premises VM (deployed as an OVA for VMware, a VHD for Hyper-V, or via a PowerShell installer for physical/other-cloud) that you register to that project; and discovery is agentless by default for VM configuration and performance (it talks to vCenter/hosts, not to an agent inside each VM). If you have never stood the appliance up, deploy it first with Deploying the Azure Migrate Appliance: Discovering VMware, Hyper-V & Physical Estates and walk the happy path in Azure Migrate Discovery & Assessment: From Appliance Deployment to Your First Right-Sizing Report. You should be comfortable running az in Cloud Shell, reading JSON output, and have basic VMware/Hyper-V administrative literacy (a vCenter role, a Hyper-V host, WinRM/SSH).
This sits in the Migration → Discovery & Assessment track. It assumes you have decided Azure Migrate is the right tool (the Choosing Your Migration Tool: Azure Migrate vs Site Recovery vs Database Migration Service decision is upstream). The data this article helps you collect feeds Migration Wave Planning: Grouping Servers by Dependency, Risk & Business Cutover Windows and the strategy choice in The 6 Rs of Migration: Mapping Rehost, Replatform & Refactor to Real Azure Workloads. When discovery is solid, replication and cutover follow in Server Migration with Azure Migrate: Agentless Replication, Test Migration & Production Cutover. Because so many failures here are network failures, the diagnostic muscle from Diagnosing Connectivity with Network Watcher: Connection Monitor, Connection Troubleshoot and Next Hop transfers directly.
A quick map of who confirms what during a discovery incident, so you call the right person fast:
| Layer | What lives here | Who usually owns it | Failure classes it can cause |
|---|---|---|---|
| Azure Migrate project | Discovery/assessment data, project key | Cloud / migration team | Registration (wrong key, deleted project) |
| Appliance VM + services | Discovery agents, Gateway, TimerService | Migration team (runs the appliance) | Registration, stall, partial data |
| Network / firewall / proxy | Outbound URLs, ports 443, proxy auth | Network / security team | Registration, connectivity, stalls |
| vCenter / Hyper-V hosts | Inventory + performance source | Virtualisation team | 0 servers, stalled count, no perf data |
| Guest OS (each VM) | Software inventory, dependency data | Server / app owners | “Credentials not provided”, empty software/deps |
| Time / identity | Appliance clock, Entra ID auth | Platform team | Registration (cert/time skew), token failures |
Core concepts
Five mental models make every later diagnosis obvious.
The appliance is the only thing that talks to Azure — Azure never reaches in. Discovery is outbound-only: the appliance pulls inventory and performance from your virtualisation layer, then pushes it to the project over HTTPS (443). Azure never connects inbound to your network or VMs. So when the portal shows nothing, the question is never “can Azure see my servers?” — it is “did the appliance collect the data and successfully push it?” Every diagnosis starts on the appliance.
Registration is a distinct prerequisite — identity plus connectivity. Before any discovery, the appliance must register to the project: you sign in with an Entra ID account that has access to the project, and it establishes trust using the project’s resources. Registration needs the login/identity URLs, the management URLs, correct time (TLS and token validation reject a skewed clock), and a path through any proxy. If registration fails, discovery never begins — and most “it discovered nothing” reports are really “it never registered.”
Discovery has two depths, and they need different credentials. Agentless VM discovery (configuration + performance) authenticates to vCenter / Hyper-V host / physical machine for the VM list, sizing and utilisation. Guest-level discovery (installed software inventory and agentless dependency analysis) additionally signs into the guest OS — via VMware Tools + WinRM/SSH for VMware, or WinRM/SSH directly for Hyper-V/physical. The two credential sets are independent: a perfect VM list with zero software/dependency detail just means you supplied vCenter credentials but no guest credentials. “Credentials not provided” is this second set missing.
The appliance tries every matching credential, and the account’s role decides how much you get. For each server it iterates the credentials of the right type until one works — but the account’s scope and privilege determine the result: a vCenter read-only role at the wrong inventory level discovers some VMs and not others; a non-admin guest account collects partial software inventory. Many “partial discovery” problems are really “the account works but isn’t privileged or scoped enough.”
Discovery is continuous and cyclical, not instant. After a successful connection, VM configuration appears within minutes, but performance, software inventory and dependencies build over subsequent cycles (tens of minutes to hours for the first meaningful pass; performance-based assessment wants days of samples). An empty inventory five minutes after setup is usually normal, not broken — knowing the timing stops you “fixing” something that was still working.
The vocabulary in one table
Before the deep sections, pin down every moving part. The glossary at the end repeats these for lookup; this table is the mental model side by side:
| Concept | One-line definition | Where it lives | Why it matters to discovery |
|---|---|---|---|
| Migrate project | Azure resource holding discovery/assessment data | Subscription / resource group | Registration target; wrong/deleted → no link |
| Appliance | On-prem VM running the discovery agents | Your network (OVA/VHD/script) | The only thing that talks to Azure |
| Config manager | The appliance’s local web app for setup/health | https://<appliance-name>:44368 |
Where you confirm every failure first |
| Registration | Appliance ↔ project trust + auth | One-time setup step | Must succeed before any discovery |
| Project key | The string that binds appliance to project | Project → appliance setup | Wrong/expired key → registration fails |
| Agentless discovery | Config + perf via vCenter/host, no in-VM agent | Appliance ↔ vCenter | Gives the VM list and sizing |
| Guest credentials | OS sign-in for software/deps | Added in config manager | Missing → “Credentials not provided” |
| Software inventory | Installed apps/roles per VM | Guest-level discovery | Needs VMware Tools/WinRM/SSH |
| Dependency analysis | Network connections between servers | Agentless (or agent-based) | Needs guest creds + enablement |
| AzureMigrateTimerService | Appliance service that drives discovery cycles | Appliance Windows service | Stopped → discovery stalls |
| Gateway / outbound | The appliance’s path to Azure URLs | Appliance + firewall/proxy | Blocked → registration/stall |
The registration and connectivity reference
Before the per-symptom anatomy, here is the lookup table you scan first: the failure signatures you realistically see during appliance bring-up and discovery, what each means, the likely cause, how to confirm it, and the first fix. The non-obvious ones are the proxy-with-auth failures (the appliance reaches the URL but the proxy strips or challenges the request) and time skew (a valid setup that fails TLS/token validation because the appliance clock drifted).
| Signature | What it means | Likely cause | How to confirm | First fix |
|---|---|---|---|---|
| Stuck at “Register with Azure Migrate” | Appliance can’t complete the project trust | Blocked URL, proxy, time skew, wrong key | Config manager → prerequisite check (red items); appliance browser to a test URL | Allow URLs/ports; set proxy; fix clock; re-paste key |
| “Failed to connect to Azure” / connectivity check red | Outbound HTTPS to required URLs is failing | Firewall default-deny, missing URL, TLS inspection | Run the appliance’s connectivity test; Test-NetConnection <url> -Port 443 |
Allow-list the URL set; exempt from TLS inspection |
| Sign-in loop / token error during register | Identity flow not completing | Proxy intercepting login URLs; conditional access | Config manager sign-in step; check proxy bypass for login URLs | Bypass login/identity URLs on proxy; check CA policy |
| “Discovery is in progress” forever, 0 servers | Connected, but no data source succeeded | vCenter not added, wrong creds, no permission | Config manager → data sources → connection status | Add vCenter; fix account role/scope |
| Servers appear, all “Credentials not provided” | VM list OK; guest sign-in not configured | No guest credentials added | Discovered servers → credential status column | Add domain/Windows/Linux guest credentials |
| “Installed software” blank for a server | Guest discovery can’t sign in / read | VMware Tools off, WinRM/SSH blocked, weak account | Server detail → software inventory status message | Start Tools; open WinRM/SSH; use privileged account |
| No dependencies for a server | Dependency analysis not collecting | Not enabled, or guest creds failing | Discovered servers → dependencies → “view dependencies” | Enable agentless dependency analysis; fix guest creds |
| Count or “last updated” frozen | Was working; cycle stopped | Appliance off, service stopped, creds expired, URL newly blocked | Config manager health; appliance services running | Start appliance/services; refresh creds; re-check URLs |
Three reading notes that save the most time:
| Distinction | The trap | How to tell them apart |
|---|---|---|
| Registration failure vs discovery failure | Treating “no servers” as a credential problem when the appliance never registered | If the project shows the appliance as not connected / never registered, fix registration first — credentials are irrelevant until then |
| VM-level vs guest-level discovery | Adding vCenter credentials and expecting software/dependencies to appear | vCenter creds give the list + sizing; software + dependencies need guest credentials. Two separate problems with two separate fixes |
| “Still warming up” vs “actually broken” | Re-running setup five minutes in because the inventory is empty | Configuration appears in minutes; performance, software, dependencies build over later cycles. Check the appliance shows a successful connection before assuming breakage |
Anatomy of a registration failure
Registration is the gate. If the appliance never completes it, the project shows no appliance and discovery never starts — and no amount of credential fiddling helps. Five distinct causes. Scan the matrix, then read the detail for whichever row matches:
| # | Registration cause | Tell-tale signal | Confirm with | Real fix |
|---|---|---|---|---|
| 1 | Required Azure URLs blocked | Connectivity check red; “failed to connect to Azure” | Config manager connectivity test; Test-NetConnection <url> -Port 443 |
Allow-list the full URL set on the firewall |
| 2 | Authenticating proxy breaks auth/token | Sign-in step loops or errors though network “works” | Proxy logs; config manager proxy config; bypass login URLs | Configure proxy in appliance; bypass/allow identity URLs |
| 3 | Time skew → TLS/token rejected | “Certificate” or token-validation errors at register | Compare appliance clock to real time; check NTP | Fix appliance time / NTP; re-run registration |
| 4 | Wrong or expired project key | “Invalid key” / key not accepted | Re-copy key from the project’s appliance setup blade | Generate/copy a fresh key; paste exactly |
| 5 | Account lacks rights on the project/subscription | Sign-in succeeds but project link fails | The Entra account’s role on the project/RG | Use an account with Contributor on the project + app registration rights |
Cause 1 — Required outbound URLs or ports are blocked
The appliance must reach a defined set of Azure endpoints over 443. In a default-deny enterprise network, none of them are open until someone adds them, and the appliance setup fails at the connectivity check. This is the single most common registration blocker.
Confirm. The config manager’s prerequisites / connectivity check lists each required endpoint and shows red on the ones it can’t reach. From the appliance itself, prove it at the network layer:
# On the appliance: prove outbound 443 to a representative required endpoint
Test-NetConnection -ComputerName management.azure.com -Port 443
Test-NetConnection -ComputerName login.microsoftonline.com -Port 443
# TcpTestSucceeded : True => the path is open; False => firewall/route is blocking
Fix. Allow-list the full required URL set on the firewall/proxy (a partial list fails — the appliance needs identity, management, storage and service-bus endpoints together). The canonical set differs by cloud and by whether you use public endpoints or private endpoints. Here is the shape of it (always reconcile against the current Microsoft “appliance URL” list for your cloud before you file the firewall ticket):
| Endpoint group | Example URL pattern | Purpose | Port |
|---|---|---|---|
| Identity / login | login.microsoftonline.com, login.windows.net |
Entra ID sign-in for registration | 443 |
| Resource management | management.azure.com |
ARM calls against the project | 443 |
| Azure Migrate service | *.<region>.migration.windowsazure.com / Migrate service URLs |
Discovery/assessment data plane | 443 |
| Service Bus | *.servicebus.windows.net |
Appliance ↔ Azure message channel | 443 |
| Storage | *.blob.core.windows.net |
Discovery payload / package upload | 443 |
| Agent / package download | Appliance auto-update + agent download URLs | Self-update of appliance components | 443 |
| Key Vault (some flows) | *.vault.azure.net |
Used in certain migrate flows | 443 |
For air-gapped or tightly-controlled networks, prefer private endpoints for the project (the appliance reaches the project over a private path) plus the minimal public identity/management URLs that still require internet — but the appliance still needs the login/identity URLs reachable for authentication. The public-vs-private decision at a glance:
| Connectivity model | What the appliance reaches | Best for | Watch-out |
|---|---|---|---|
| Public endpoints (default) | Full public URL set over 443 | Most estates with managed egress | Must allow-list the complete set; TLS-inspection breakage |
| Private endpoints (project) | Project data plane over a private link | Locked-down / no broad internet egress | Still needs identity/management URLs; DNS to private zone must resolve |
| Proxy (with/without auth) | URLs via an explicit forward proxy | Centralised egress control | Auth proxies break token flow unless identity URLs are bypassed |
Cause 2 — An authenticating proxy breaks the registration token flow
Many enterprises force all egress through a proxy. The appliance supports an explicit proxy, but two things bite: an authenticating proxy that challenges the appliance, and a proxy doing TLS inspection that swaps certificates the appliance doesn’t trust. The network “works” for a browser, yet the appliance’s sign-in/token exchange loops or errors.
Confirm. In the config manager, the proxy is configured (or not); the sign-in step is where it fails. The proxy’s own logs show the appliance’s requests being challenged or blocked, especially to the identity URLs.
Fix. Set the proxy explicitly in the appliance configuration (address, port, and credentials if required), and bypass/allow the identity and management URLs so the token flow isn’t intercepted:
# On the appliance: set a system-wide proxy for the appliance's outbound calls
netsh winhttp set proxy proxy-server="http://proxy.corp.local:8080" bypass-list="login.microsoftonline.com;management.azure.com;*.servicebus.windows.net"
netsh winhttp show proxy
If the proxy does TLS inspection, exempt the Azure Migrate URL set from inspection — a re-signed certificate breaks the appliance’s validation of Azure endpoints. The four proxy traps, in order of how often they bite: no proxy configured when egress requires one (all checks fail), an authenticating proxy challenging the appliance (sign-in loops, 407 in the proxy logs), TLS inspection re-signing Azure certs (trust errors), and a proxy rule that lets a browser through but not the appliance’s service account (manual test passes, appliance fails).
Cause 3 — Time skew on the appliance
TLS handshakes and token validation are time-sensitive. If the appliance’s clock has drifted (common on a freshly imported OVA/VHD, or a VM whose host time sync is off), certificates appear not-yet-valid or expired and tokens fail validation — registration errors that look like a trust problem but are really a clock problem.
Confirm. Compare the appliance’s clock to real time; check the time source:
# On the appliance: is the clock correct and syncing?
Get-Date
w32tm /query /status
w32tm /resync
Fix. Correct the time and ensure NTP/host-time sync is healthy, then re-run registration. A few minutes of skew is enough to break TLS — this is a fast check that saves hours.
Cause 4 — Wrong or expired project key
You bind the appliance to the project by pasting a project key generated in the project’s appliance-setup blade. Paste a truncated key, an old key from a different project, or a key that has since been regenerated, and registration is rejected outright.
Confirm. Re-open the project → discover / appliance setup and copy the key fresh. (The project itself must exist — a key from a deleted/renamed project will never bind.) Verify the project is there:
# Confirm the Azure Migrate project exists in the expected resource group
az resource list --resource-group rg-migrate-prod \
--resource-type "Microsoft.Migrate/migrateProjects" \
--query "[].{name:name, location:location}" -o table
Fix. Generate/copy a fresh key from the correct project and paste it exactly (no leading/trailing whitespace). Keys are project-scoped — one appliance, one project key.
Cause 5 — The sign-in account lacks rights on the project
Registration signs you in with an Entra ID account and then creates/links resources for the appliance. If that account can authenticate but lacks the role to act on the project (or to create the required app registration), sign-in “succeeds” but the link step fails.
Confirm. Check the account’s role on the project’s resource group and whether it can register apps in the tenant. Fix. The registration account needs three things: a valid Entra ID sign-in (tenant), at least Contributor on the Migrate project or its resource group (to link the appliance), and the permission to create the appliance’s app registration in the tenant (or have an admin pre-create it). Grant those and re-run registration.
Anatomy of a “0 servers / stalled count” failure
Registration succeeded, the appliance is connected, but the Discovered servers count is 0 or frozen below your real total. The appliance now needs a working data source — a vCenter, a set of Hyper-V hosts, or physical machines — and the right account to read inventory. Five causes:
| # | 0-servers / stall cause | Tell-tale signal | Confirm with | Real fix |
|---|---|---|---|---|
| 1 | No data source added (vCenter/host) | Connected appliance, but no source listed | Config manager → “Add data sources” empty | Add the vCenter/host with credentials |
| 2 | vCenter account wrong / unprivileged | Connection fails or partial VM list | Config manager connection status; vCenter role | Use a read-only role with the right propagation |
| 3 | Account scoped to a subtree | Some VMs discovered, others missing | Compare vCenter inventory scope vs role assignment | Assign the role at the right inventory level |
| 4 | Host/vCenter unreachable from appliance | Connection status “failed to connect” | Test-NetConnection <vcenter> -Port 443 from appliance |
Open the path; correct FQDN/IP/port |
| 5 | Still in the first discovery cycle | Count is 0 minutes after a successful connection | Config manager shows connection OK, discovery running | Wait one cycle; configuration fills in first |
Cause 1 — No data source added
The appliance registers independently of any vCenter. If you finished registration but never added a vCenter / Hyper-V host / physical source (or added it without saving credentials), there is simply nothing to discover.
Confirm. In the config manager, the “Manage credentials and discovery sources” section is empty or shows no successful source. Fix. Add the vCenter FQDN/IP and a vCenter account, save, and confirm the connection status goes to validated.
Cause 2 — The vCenter account is wrong or under-privileged
For VMware, the appliance needs a vCenter account with at least a read-only role at the right scope to enumerate VMs and read performance counters. A wrong password fails the connection outright; a role missing the needed privileges discovers nothing or can’t later enable software/dependency collection.
Confirm. The config manager shows the vCenter connection as failed (bad credentials/permission) or validated. From the appliance, prove network reachability to vCenter independently of credentials:
# On the appliance: can it even reach vCenter on 443?
Test-NetConnection -ComputerName vcenter01.corp.local -Port 443
Fix. Use a dedicated vCenter account with a read-only role (plus the specific privileges Azure Migrate documents for guest discovery and performance), assigned at the correct inventory object. The VMware account-permission tiers and what each unlocks:
| Discovery depth | vCenter privilege level | What you get | What’s missing without it |
|---|---|---|---|
| VM configuration + performance | Read-only role at the inventory scope | VM list, sizing, CPU/RAM utilisation | Nothing — this is the baseline |
| Software inventory (guest) | Read-only plus guest-operations privileges + guest creds | Installed software/roles per VM | Empty “Installed software” |
| Agentless dependency analysis | Read-only plus guest-operations privileges + guest creds | Network dependencies between servers | Empty dependency view |
Cause 3 — The account is scoped to the wrong inventory subtree
In vCenter, a role assigned at a folder/datacenter level only sees objects under it (with propagation). Assign Azure Migrate’s account at one cluster and it will discover that cluster’s VMs and silently miss the rest — a partial count that looks complete unless you reconcile against the true total.
Confirm. Compare the number discovered against the known VM count, and check where in the vCenter hierarchy the role is assigned versus where the missing VMs live. Fix. Assign the read-only role at a level (e.g., the vCenter root or the right datacenter) that propagates to every VM in scope for the assessment.
Cause 4 — The appliance can’t reach vCenter or the hosts
The appliance must reach vCenter (443) or Hyper-V hosts (WinRM, typically 5985/5986) or physical targets. A network segment, host firewall, or wrong FQDN/IP blocks the connection regardless of credentials.
Confirm. Test-NetConnection <target> -Port <port> from the appliance; the config manager connection status corroborates. Fix. Open the path (firewall/route), correct the FQDN/IP, and ensure name resolution from the appliance works. The source-to-port map per discovery mode:
| Discovery source | Appliance → source protocol/port | Also needs (for guest depth) |
|---|---|---|
| VMware (vCenter) | HTTPS 443 to vCenter | VMware Tools running + WinRM 5985/5986 (Win) / SSH 22 (Linux) in guest |
| Hyper-V hosts | WinRM 5985/5986 to each host | WinRM 5985/5986 (Win) / SSH 22 (Linux) in guest |
| Physical / other cloud | WinRM 5985/5986 (Win) or SSH 22 (Linux) to each server | Same channel serves config + guest depth |
Cause 5 — It’s still the first discovery cycle
After a successful vCenter connection, the very first cycle still takes minutes to populate configuration, and longer for performance/software/dependencies. A 0 count two minutes after connecting is expected. Confirm the connection shows validated and discovery is “in progress.” Fix: wait one cycle — configuration appears first, the deeper data follows. The expected timing, so you don’t fix a non-problem:
| Data type | Typically appears | Needs | Common misread |
|---|---|---|---|
| VM configuration (list, basic specs) | Minutes after first successful connection | vCenter/host creds | “0 servers” panic five minutes in |
| Performance (CPU/RAM/disk/network) | Builds over subsequent cycles; days for solid p95 | Continuous collection | Assessing too early → as-on-prem sizing |
| Software inventory | After guest discovery runs (tens of minutes+) | Guest creds + Tools/WinRM/SSH | Expecting it with only vCenter creds |
| Dependencies (agentless) | After enablement + guest sign-in, over cycles | Enabled + guest creds | Expecting it without enabling analysis |
Anatomy of a guest-discovery gap: credentials, software & dependencies
This is where most “discovery looks incomplete” tickets actually live. The VM list is fine, but servers show “Credentials not provided”, software inventory is blank, and dependency mapping shows nothing — all three are the guest-level depth that needs sign-in into the OS, a layer beyond the vCenter/host connection.
| # | Guest-gap cause | Tell-tale signal | Confirm with | Real fix |
|---|---|---|---|---|
| 1 | No guest credentials added at all | Every server flagged “Credentials not provided” | Discovered servers → credential status column | Add Windows (domain/local) + Linux guest creds |
| 2 | Credentials added but none match a server | Some servers validated, others not | Per-server credential status; which cred mapped | Add the matching domain/local/SSH credential |
| 3 | VMware Tools not running / out of date | Software/deps blank only on certain VMs | VM detail message; Tools status in vCenter | Install/start/update VMware Tools |
| 4 | WinRM / SSH blocked in the guest | Guest sign-in fails despite right password | Test WinRM/SSH from appliance to the VM | Enable WinRM / open SSH; allow appliance source |
| 5 | Dependency analysis not enabled | Deps blank for everything; software fine | Discovered servers → dependencies = not enabled | Enable agentless dependency analysis |
| 6 | Guest account too weak for software | Software partial/empty; sign-in “succeeds” | Software inventory status detail | Use an account with the documented guest privileges |
Cause 1 & 2 — Guest credentials missing or non-matching
Agentless software inventory and dependency analysis sign into the guest with credentials you add in the config manager — separate from the vCenter account. With none added, every server reads “Credentials not provided”; with some added, the appliance tries each credential of the right type per server and uses the first that works, leaving any server whose OS/domain matches none unvalidated. Confirm via the Discovered servers per-server credential status (the detail shows which credential mapped, or that none did); fix by adding a domain account for Windows fleets and one or more Linux accounts (password or key), then re-validating. How the appliance picks a credential:
| Credential type added | Used for | Match logic | Tip |
|---|---|---|---|
| Domain (Windows) | Domain-joined Windows guests | Tried against Windows servers; first that authenticates wins | Add the domain account once; covers many VMs |
| Local Windows | Workgroup / non-domain Windows | Tried per server | Needed for standalone Windows boxes |
| Linux (password) | Linux guests | Tried against Linux servers | Use a low-privilege account where possible |
| Linux (SSH private key) | Linux guests with key auth | Key-based sign-in | Preferred over passwords for Linux |
| vCenter / host (separate) | The VM-level connection, not guest | Not used for guest sign-in | Don’t confuse with guest creds — different layer |
Cause 3 — VMware Tools not running
For VMware guest discovery, the appliance reaches the guest through VMware Tools. If Tools is stopped, missing, or badly out of date on a VM, that VM’s software and dependency data won’t collect even with perfect credentials — and it’s exactly the Tools-less VMs that look “broken.” Confirm via the VM detail message and the Tools status in vCenter; fix by installing/starting/updating VMware Tools on the affected guests. It is a hard prerequisite for VMware agentless guest discovery.
Cause 4 — WinRM or SSH blocked inside the guest
Even with Tools and credentials, the guest must accept the management channel: WinRM (5985/5986) for Windows, SSH (22) for Linux. A host firewall, a disabled WinRM service, or an SSH config that blocks the appliance’s source stops guest discovery cold.
Confirm. From the appliance, test the channel to a failing guest:
# On the appliance: can it reach the guest's management channel?
Test-NetConnection -ComputerName web01.corp.local -Port 5985 # Windows WinRM
Test-NetConnection -ComputerName app02.corp.local -Port 22 # Linux SSH
Fix. Enable WinRM on Windows guests (e.g., winrm quickconfig / GPO) and open SSH on Linux, allowing the appliance’s IP as a source. This is frequently an estate-wide config (push via GPO/Ansible) rather than per-VM clicking.
Cause 5 — Dependency analysis not enabled
Agentless dependency analysis is not on by default — you enable it for the servers you care about. Until then, the dependencies column is empty for everything, even with perfect guest sign-in. (It also has a practical ceiling on how many servers you can run agentless dependency analysis against per appliance, so enable it for the wave you’re planning, not blindly for thousands.)
Confirm. Discovered servers → the Dependencies column shows “not enabled” / a “view dependencies” action that prompts enablement. Fix. Enable agentless dependency analysis on the target servers; mapped network connections then build over subsequent cycles. Software vs dependencies, side by side, so you target the right gap:
| Capability | Needs | Default state | Where it surfaces | If empty, check |
|---|---|---|---|---|
| Software inventory | Guest creds + Tools/WinRM/SSH | Collected once guest creds work | Server detail → installed software | Credentials, Tools, WinRM/SSH, account privilege |
| Agentless dependency analysis | Guest creds + explicit enablement | Off until enabled | Discovered servers → dependencies | Whether it’s enabled, then guest sign-in |
Cause 6 — The guest account isn’t privileged enough for software
Guest sign-in can “succeed” yet still read only partial software inventory if the account lacks the privileges the agentless method needs to enumerate installed software/roles. Sign-in works; the data is thin.
Confirm. The software-inventory status on the server detail indicates the collection result. Fix. Use a guest account with the documented privileges for agentless software inventory (sufficient to read the OS’s installed-software registry/roles on Windows and equivalent on Linux), then re-validate.
Architecture at a glance
Hold this mental model and every failure above has an obvious home. Picture three zones connected by two one-way data movements. Zone one is your virtualisation estate: vCenter Server (or Hyper-V hosts, or physical machines) and, inside each VM, a guest OS with VMware Tools and a WinRM/SSH endpoint. Zone two is the appliance — a single Windows Server VM running the configuration manager (its local web app on port 44368), the AzureMigrateTimerService that drives discovery cycles, the discovery and assessment agents, and a Gateway component that handles the outbound channel. Zone three is Azure: your Migrate project, fronted by the identity, management, Service Bus and storage endpoints the appliance must reach over 443.
Two one-way movements connect them. The first is pulled by the appliance: it authenticates to vCenter (443) to enumerate VMs and read performance, and — for the deep data — signs into each guest (Tools + WinRM/SSH) to read software and observe connections. The second is outbound to Azure over HTTPS, pushing everything collected to the project. The arrows only ever leave your network going up; Azure never reaches down. So the diagnostic path is a left-to-right walk mapping each failure to one boundary: registration and outbound failures live at the appliance↔Azure boundary; 0-servers failures at the appliance↔vCenter boundary; “Credentials not provided” and empty software/dependencies at the appliance↔guest boundary. The single most useful instrument sits in the middle — the appliance’s own configuration manager, which reports the health of every hop before you ever open the portal.
Real-world scenario
Aranta Logistics is mid-migration: a 620-VM VMware estate across two datacenters (Pune and Hyderabad), two vCenter Servers, a hard default-deny egress firewall, and a corporate forward proxy that authenticates every outbound request. Three engineers; the assessment is due to the steering committee in two weeks to unlock the cloud budget. They deployed the appliance OVA in Pune, pointed it at the Pune vCenter — and the trouble started.
The first symptom was registration failing: the appliance sat at “Register with Azure Migrate” with the connectivity check red on the identity and Service Bus URLs. The reflex was to re-run the wizard three times. The breakthrough came from running Test-NetConnection login.microsoftonline.com -Port 443 on the appliance — TcpTestSucceeded: False. The egress firewall had never been opened for the appliance, and the proxy was challenging its requests. The network team allow-listed the full URL set, and the appliance proxy was configured with credentials plus a bypass for the identity/management URLs. Registration completed in one try.
Then: 412 servers discovered, not 620. Panic — until they reconciled against vCenter and found the missing 208 were all in Hyderabad, behind the second vCenter the appliance had never been pointed at. One appliance discovers what it can reach; a second vCenter is a planning decision. A second appliance in Hyderabad, registered to the same project, took the count to 620.
The third symptom was the expensive one: the VM list was complete, but every server read “Credentials not provided,” software inventory was blank, and dependency mapping showed nothing — so the assessment was building on as-on-premises sizing with no dependency groups. They had supplied only vCenter credentials. Adding a domain account for Windows and an SSH key for Linux validated most servers within a cycle, but 30 Linux app servers still failed: Test-NetConnection app-h-07 -Port 22 returned False — a host firewall blocked SSH from the appliance’s IP. One rule fixed all 30. They then enabled agentless dependency analysis on the ~180 servers in the first wave (not all 620) and let it run for several days.
By day nine they had a complete 620-VM inventory, performance-based right-sizing that cut the projected Azure compute estimate by roughly 35% versus the as-on-prem first pass, and dependency groups that exposed two “standalone” app servers actually talking to a shared database slated for a later wave. They re-sequenced the waves before cutover instead of discovering it during an outage. The lesson on the wall: “An empty inventory blade is the appliance telling you which hop is blocked — read the appliance, not the portal, and never assess on a partial count.”
The incident as a timeline, because the order of moves is the lesson:
| Day | Symptom | Action taken | Effect | What it should have been |
|---|---|---|---|---|
| 1 | Registration stuck, URLs red | Re-ran the wizard 3x | No change | Test connectivity on the appliance first |
| 1 | TcpTestSucceeded: False |
Allow-list URL set; proxy + identity-URL bypass | Registration completes | Open egress before deploying the appliance |
| 2 | 412 of 620 servers | Reconciled count vs vCenter | Found Hyderabad behind 2nd vCenter | Plan one appliance per vCenter up front |
| 3 | Still 412 | Deploy 2nd appliance to same project | Count → 620 | — |
| 4 | All “Credentials not provided” | Add domain + SSH guest creds | Most validate; 30 Linux fail | Add guest creds in initial setup |
| 5 | 30 Linux still failing | Test-NetConnection :22 → firewall |
Open SSH from appliance IP | Open guest WinRM/SSH estate-wide via config mgmt |
| 6 | No dependency groups | Enable agentless dep analysis (wave 1 only) | Deps build over cycles | Enable for the wave, not all 620 |
| 9 | Complete assessment | Performance-based sizing + dep groups | Estimate −35%; waves re-sequenced | The payoff of doing discovery right |
Advantages and disadvantages
The single-appliance, agentless, outbound-only model both causes this class of problem and makes it diagnosable. Weigh it honestly:
| Advantages (why this model helps you) | Disadvantages (why it bites) |
|---|---|
| Agentless by default — no software to install on every VM for the base inventory | The base inventory’s depth (software, dependencies) still needs in-guest sign-in, which feels like a surprise second setup |
| Outbound-only, appliance-initiated — no inbound holes into your network or VMs | All connectivity rides on a precise outbound URL/port allow-list a default-deny firewall blocks |
| The configuration manager surfaces per-hop health locally, before the portal | The Azure portal stays quiet about appliance health, so newcomers stare at an empty blade instead of the appliance |
| One appliance discovers an entire reachable vCenter estate cheaply | One appliance = one vCenter’s reach; multi-vCenter/multi-site needs more appliances (a planning, not config, task) |
| Continuous collection yields real performance-based right-sizing | The continuity is the trap — assess too early and you ship as-on-prem sizing on thin data |
| Credentials are tried per server, so one domain account covers many VMs | Wrong/under-privileged accounts produce partial discovery that looks complete unless you reconcile |
| Private endpoints support locked-down, no-broad-egress estates | Private-endpoint setups add DNS/identity-URL nuances that cause their own registration failures |
The model is right for standard datacenter assessments where you want broad, low-touch discovery and real utilisation data. It bites hardest in heavily-segmented networks (URL/port and guest-channel blocks), multi-site estates (appliance fan-out), and teams that treat the VM count as “done” without the guest depth. Every disadvantage is manageable — but only if you know the seams exist, which is the entire point of this article.
Hands-on lab
You can’t spin up a full vCenter estate for free, so this lab validates the two things that block real projects most often — outbound connectivity and the project’s existence/key — using Cloud Shell and PowerShell checks you’d run on a real appliance. Free-tier-friendly; nothing here incurs meaningful cost.
Step 1 — Confirm (or create) a Migrate project in your subscription. In Cloud Shell (Bash):
RG=rg-migrate-lab
LOC=centralindia
az group create -n $RG -l $LOC -o table
# List any existing Migrate projects in the RG
az resource list --resource-group $RG \
--resource-type "Microsoft.Migrate/migrateProjects" \
--query "[].{name:name, location:location}" -o table
Expected: the resource group is created; the project list is empty (you’ll create the project in the portal, where the appliance key is generated — the key is a portal artifact). The point of the step is to prove you can see the project resource type the appliance will register against.
Step 2 — Enumerate the connectivity an appliance would need. From any Windows host that represents the appliance’s network position (or the appliance VM itself), test the representative endpoints:
# Run from the would-be appliance network location
"management.azure.com","login.microsoftonline.com","login.windows.net" |
ForEach-Object { Test-NetConnection -ComputerName $_ -Port 443 |
Select-Object ComputerName, TcpTestSucceeded }
Expected: TcpTestSucceeded : True for each. Any False is exactly the failure that stalls real registration — and now you’ve found it before deploying the appliance.
Step 3 — Simulate the time-skew check. Confirm the clock and sync state (skew silently breaks TLS at registration):
Get-Date
w32tm /query /status
Expected: current time and a healthy time source. On a real freshly-imported OVA, this is where you’d catch a drifted clock.
Step 4 — Dry-run the guest-channel reachability test. Pick any reachable Windows and Linux host on the network and test the guest management ports the appliance uses for software/dependency discovery:
Test-NetConnection -ComputerName <some-windows-host> -Port 5985 # WinRM
Test-NetConnection -ComputerName <some-linux-host> -Port 22 # SSH
Expected: True where the channel is open. This is the precise test you’ll run against any guest stuck on “Credentials not provided” with the channel blocked.
Validation checklist. You proved you can see the project resource type, that the appliance’s outbound 443 path to identity/management is open (or found exactly where it isn’t), that the clock is sane, and that the guest channels are reachable — the four checks that pre-empt the majority of real discovery failures. The lab steps mapped to what each proves:
| Step | What you did | What it proves | Real-world analogue |
|---|---|---|---|
| 1 | List the Migrate project resource type | The project layer exists and is visible | Confirming the registration target |
| 2 | Test-NetConnection to Azure URLs :443 |
Outbound registration path is open | The #1 registration blocker, caught early |
| 3 | Get-Date / w32tm |
The clock won’t break TLS | Catching OVA time skew before register |
| 4 | Test WinRM/SSH to a guest | The guest depth channel is reachable | Diagnosing “Credentials not provided” |
Cleanup.
az group delete -n $RG --yes --no-wait
Cost note. An empty resource group and a few Test-NetConnection calls cost effectively nothing; the real appliance runs inside your datacenter (your existing VMware/Hyper-V capacity), so Azure-side discovery and assessment with Azure Migrate carry no charge — you pay only when you later replicate and run servers in Azure.
Common mistakes & troubleshooting
This is the playbook — the part you bookmark. First as a scannable table you can read mid-incident, then the same entries with the full confirm-command detail underneath. It spans the basic blockers (URLs, keys, time) and the advanced ones (proxy token flow, scope, guest channel).
| # | Symptom | Root cause | Confirm (exact cmd / portal path) | Fix |
|---|---|---|---|---|
| 1 | Setup stuck at “Register with Azure Migrate” | Required Azure URLs/ports blocked outbound | Config manager connectivity check (red items); Test-NetConnection management.azure.com -Port 443 on appliance |
Allow-list the full URL set on 443; re-run register |
| 2 | Sign-in loops / token error at registration | Authenticating proxy intercepting identity URLs | Proxy logs (407 to login URLs); config manager proxy config | Set proxy + credentials; bypass identity/management URLs |
| 3 | “Certificate” / trust error at registration | Appliance clock skew (TLS/token invalid) | Get-Date; w32tm /query /status on appliance |
Fix time/NTP (w32tm /resync); re-register |
| 4 | “Invalid key” / key not accepted | Wrong/expired/truncated project key | Re-copy key from project → appliance setup blade | Paste a fresh key for the correct project |
| 5 | Sign-in OK but project won’t link | Entra account lacks rights on the project | Account’s role on the project/RG | Use Contributor on the project + app-registration rights |
| 6 | Connected appliance, but 0 servers | No vCenter/host data source added | Config manager → “manage discovery sources” empty | Add vCenter/host + credentials; validate connection |
| 7 | vCenter connection “failed to connect” | Wrong creds, no permission, or unreachable | Config manager connection status; Test-NetConnection vcenter -Port 443 |
Fix creds/role; open 443 to vCenter; correct FQDN |
| 8 | Some VMs discovered, many missing | vCenter role scoped to a subtree | Discovered count vs real total; role assignment level in vCenter | Assign read-only role at root/datacenter with propagation |
| 9 | Every server “Credentials not provided” | No guest-OS credentials added | Discovered servers → credential status column | Add domain (Windows) + Linux (password/SSH key) creds |
| 10 | Some servers validate, others don’t | No guest credential matches those servers | Per-server credential status; which cred mapped | Add the matching domain/local/SSH credential |
| 11 | “Installed software” blank on certain VMs | VMware Tools stopped/missing/outdated | vCenter Tools status; server detail message | Install/start/update VMware Tools on those guests |
| 12 | Guest sign-in fails despite correct password | WinRM/SSH blocked in the guest | Test-NetConnection <vm> -Port 5985 / -Port 22 from appliance |
Enable WinRM / open SSH; allow the appliance source IP |
| 13 | Dependencies empty for everything; software fine | Agentless dependency analysis not enabled | Discovered servers → dependencies = “not enabled” | Enable agentless dependency analysis for the wave’s servers |
| 14 | Count / “last updated” frozen; was working | Appliance off, service stopped, or creds expired | Config manager health; appliance services running | Start appliance/AzureMigrateTimerService; refresh creds |
| 15 | Discovery worked, now URLs failing again | Newly-blocked URL or rotated proxy creds | Re-run connectivity check; Test-NetConnection to the failing URL |
Re-allow the URL; update proxy credentials on appliance |
| 16 | Appliance auto-update / agents not updating | Update/agent download URLs blocked | Connectivity check on package URLs; appliance version | Allow appliance auto-update + agent download URLs |
The expanded form, with the full reasoning for the five entries that bite hardest and trip up even experienced teams:
Row 2 — sign-in loops at registration though the network “works.” An authenticating proxy challenges the appliance’s token requests (407), or TLS inspection re-signs the Azure certificates the appliance won’t trust — both invisible to a browser test. Confirm from the proxy logs (407/challenges to the login URLs); the config manager’s sign-in step is where it fails. Fix by configuring the proxy in the appliance with credentials and bypassing the identity/management URLs (netsh winhttp set proxy ... bypass-list="login.microsoftonline.com;management.azure.com"), and exempting the Azure Migrate URLs from TLS inspection.
Row 3 — a “certificate” or trust error at registration. Time skew on the appliance makes TLS certs appear not-yet-valid/expired and invalidates tokens — common on a freshly imported OVA/VHD. Get-Date is wrong and w32tm /query /status shows a bad sync source. Run w32tm /resync (and fix the NTP/host-time source), then re-register. A few minutes of skew is enough to break it, which is why it’s the cheapest first check.
Row 8 — some VMs discovered, many missing. The vCenter account’s read-only role is scoped to a subtree (one cluster/folder), so it can’t see the rest — a partial count that masquerades as complete because no error fires. Reconcile the discovered count against the true vCenter total and check where the role is assigned versus where the missing VMs live. Fix by assigning the role at the vCenter root or correct datacenter with propagation. (The other cause of a partial count — a second vCenter the one appliance can’t reach — needs a second appliance on the same project.)
Row 9 — every server reads “Credentials not provided.” No guest-OS credentials were added; you supplied only the vCenter/host account, which discovers the list and sizing but not the guest depth. The Discovered servers credential-status column flags every row. Add guest credentials — a domain account for Windows, and Linux accounts (password or SSH key) — and let the appliance re-validate. This single gap is the most common “discovery looks incomplete” ticket.
Row 12 — guest sign-in fails even with the correct password. WinRM (5985/5986) or SSH (22) is blocked inside the guest (host firewall, disabled service, source restriction). From the appliance, Test-NetConnection <vm> -Port 5985 (Windows) or -Port 22 (Linux) returns False. Enable WinRM (winrm quickconfig / GPO) or open SSH, allowing the appliance’s IP as a source — usually pushed estate-wide via GPO/Ansible rather than per-VM. Pair this with row 13: once sign-in works, dependencies still need agentless dependency analysis enabled (it’s off by default, per-server), and a frozen count later (row 14) usually means the AzureMigrateTimerService stopped or credentials expired.
Best practices
- Open egress before you deploy the appliance. Allow-list the complete URL set on 443 (and the proxy bypass for identity URLs) as a prerequisite ticket — most lost days are a firewall change that should have preceded the OVA import.
- Confirm connectivity from the appliance itself, not a laptop.
Test-NetConnection <url> -Port 443on the appliance is the ground truth; a browser passing proves nothing about the service account’s path. - Fix the clock first on any registration error. A 30-second
Get-Date/w32tmcheck rules out time skew before you chase phantom certificate-trust problems. - Plan one appliance per vCenter (and per site) up front, and reconcile the discovered count against the real VM total on day one — a “complete-looking” partial count is the most dangerous failure because no error fires.
- Add guest credentials during initial setup, not as an afterthought — a domain account plus Linux key/credentials immediately, so software and dependencies collect from the first cycles instead of leaving you with half a discovery.
- Use dedicated, least-privilege service accounts — a read-only vCenter role at the right scope and a guest account with only the documented software-inventory privileges; never reuse a human admin account.
- Enable WinRM/SSH on guests estate-wide via GPO/Ansible, allowing the appliance source — far faster than chasing blocked channels VM by VM.
- Enable agentless dependency analysis only for the wave you’re planning, respect the per-appliance ceiling, and let it run several days before grouping.
- Don’t assess on thin data — wait for a multi-day performance window so right-sizing is performance-based, not as-on-premises; that accuracy is where the real Azure-cost savings come from.
- Keep the appliance updated, running and monitored (it auto-updates over the package URLs — blocked, its components drift), and rotate credentials deliberately: update a changed service-account password in the config manager the same day, or discovery silently goes stale.
Security notes
- Least-privilege everywhere. The vCenter account needs only a read-only role (plus the specific guest-operations privileges for software/dependency depth); guest accounts need only what agentless software inventory requires. Never point the appliance at vCenter or guests with a full admin account.
- Protect the appliance host. It holds credentials for vCenter and guest OSes; the config manager runs locally on it. Treat it as a sensitive management server — restrict who can log in, patch it, and keep it on a controlled management network.
- Prefer key-based auth for Linux guests. Add an SSH private key rather than passwords where possible, and scope the guest account narrowly.
- Use private endpoints in locked-down estates. Where broad internet egress is unacceptable, configure the project for private-endpoint connectivity so the appliance reaches the data plane over a private link — while still allowing the minimal identity/management URLs required for sign-in.
- Exempt, don’t disable. If a proxy does TLS inspection, exempt the Azure Migrate URLs rather than disabling inspection broadly — keep the security control, carve out the appliance’s required endpoints.
- Scope the project’s RBAC. Registration needs Contributor on the project; grant it on the project/resource group, not subscription-wide, and remove standing access once appliances are registered.
- Guard the project key. It binds an appliance to your project — treat it like a secret, don’t paste it into tickets or chat, and regenerate it if exposed.
The security knobs that also prevent discovery incidents — secure and reliable pull in the same direction here:
| Control | Setting / mechanism | Secures against | Also prevents |
|---|---|---|---|
| Read-only vCenter role at right scope | vCenter role + propagation | Over-privileged discovery account | Partial/over-broad discovery |
| Least-privilege guest accounts | Documented guest-operations privileges | Excess in-guest access | Thin software inventory from weak/over-scoped accounts |
| Private endpoints for the project | Project private link + private DNS | Broad internet egress exposure | URL-allow-list sprawl on the firewall |
| TLS-inspection exemption (not disable) | Proxy carve-out for Migrate URLs | Losing inspection org-wide | Cert-trust registration failures |
| Project RBAC scoped to the project | Contributor on project/RG only | Subscription-wide standing access | Registration link failures from wrong scope |
| SSH key auth for Linux guests | Key instead of password | Password reuse/leak | Auth failures from rotated/expired passwords |
Cost & sizing
The good news: Azure Migrate discovery and assessment are free. The appliance runs on your existing on-premises VMware/Hyper-V capacity, and Azure charges nothing for collecting inventory, building assessments, or analysing dependencies. The bill only starts when you replicate and run servers in Azure — a later phase. So “cost” here is really sizing and footprint.
- Appliance footprint. A modestly-sized Windows Server VM on your hypervisor (a few vCPU, several GB RAM, plus disk for collected data) — your on-prem capacity, not Azure spend. Size it per Microsoft’s appliance requirements for the estate scale.
- Scale by appliance count, not SKU. One appliance covers a bounded server count and one vCenter’s reach; large or multi-site estates need multiple appliances (each free on-prem). The cost of scale is operational, not a per-server license.
- Dependency analysis has a practical ceiling — a per-appliance server limit; enable it per wave rather than for thousands at once.
- The real money is downstream. Doing discovery right yields performance-based right-sizing that routinely cuts the projected Azure compute estimate substantially versus an as-on-premises guess — the savings land in the replication/run phase, funded by this phase’s accuracy.
A rough picture of the footprint and where money actually appears:
| Item | What you pay / consume | Magnitude | Notes |
|---|---|---|---|
| Azure Migrate discovery + assessment | Azure charge | Free | Inventory, sizing, dependencies at no cost |
| Appliance VM (on-prem) | Your hypervisor capacity | A few vCPU + several GB RAM + disk | One per vCenter/site; not Azure spend |
| Additional appliances for scale | More on-prem capacity + ops | Per vCenter/site | Operational, not licensing, cost |
| Dependency analysis | Appliance/guest load | Within the per-appliance ceiling | Enable per wave to stay within limits |
| Downstream replication + run | Azure compute/storage/egress | The actual bill | Right-sizing here cuts this materially |
Interview & exam questions
1. The appliance is stuck at “Register with Azure Migrate.” What’s your first diagnostic move? Confirm outbound connectivity from the appliance, not a laptop: run Test-NetConnection management.azure.com -Port 443 (and the identity/Service Bus/storage URLs). The most common cause is a default-deny firewall blocking the required URL set; a TcpTestSucceeded: False points straight at it. Allow-list the full set on 443 and re-register.
2. Why does an authenticating proxy break registration even when browsing works? The appliance’s token/identity flow to the login URLs gets challenged (407) or intercepted by TLS inspection, which a browser session masks. Fix by configuring the proxy in the appliance with credentials and bypassing the identity/management URLs, and by exempting the Azure Migrate URLs from TLS inspection so re-signed certificates don’t break trust.
3. The appliance registered fine but the project shows 0 servers. What’s wrong? Registration and discovery are separate: registering binds the appliance to the project, but you must still add a data source (vCenter/Hyper-V/physical) with valid credentials. With no source added — or one that fails to connect/authenticate — the inventory stays at 0. Add the vCenter with a read-only account and confirm the connection validates.
4. You discovered 412 of 620 known VMs. Most likely cause? Either the appliance only reaches one of multiple vCenters (one appliance, one vCenter’s reach — deploy another appliance to the same project), or the vCenter account’s read-only role is scoped to a subtree and can’t see the rest. Reconcile the missing VMs against the vCenter hierarchy; fix by adding an appliance per vCenter and/or assigning the role at the right level with propagation.
5. Every discovered server shows “Credentials not provided.” What does that mean and how do you fix it? The appliance has the VM-level connection (vCenter) but no guest-OS credentials, so it can list and size the VMs but can’t sign in for software inventory or dependencies. Add guest credentials — a domain account for Windows, Linux password/SSH-key accounts — in the config manager; the appliance tries each per server and validates.
6. Software inventory is blank on some VMware VMs but fine on others. Why? The blank ones are missing or running stale VMware Tools, the channel agentless guest discovery uses on VMware. Confirm Tools status per VM in vCenter; install/start/update Tools on the affected guests. (Credentials and the vCenter connection being fine is what makes it confusing.)
7. Guest sign-in fails despite the correct password. What do you check? The guest’s management channel: WinRM (5985/5986) for Windows, SSH (22) for Linux, which a host firewall or disabled service can block. From the appliance, Test-NetConnection <vm> -Port 5985 / -Port 22; if it’s False, enable WinRM / open SSH and allow the appliance’s source IP — typically via GPO/Ansible across the estate.
8. Dependency mapping is empty even though software inventory works. Why? Agentless dependency analysis is off by default and must be enabled per server, independent of guest credentials. With guest sign-in working, software collects but dependencies won’t until you enable the analysis. Enable it for the servers in your migration wave and let connections build over subsequent cycles.
9. Difference between a registration failure and a discovery failure? A registration failure means the appliance never established trust with the project (blocked URLs, proxy/token issue, time skew, wrong key, insufficient RBAC) — discovery can’t even begin. A discovery failure means the appliance is registered but isn’t collecting (no/failed data source, wrong vCenter scope, missing guest credentials, blocked guest channel). If the project shows the appliance as not connected, it’s the former — fix it first.
10. The appliance was discovering fine, then the count froze. What are the usual causes? The appliance or its AzureMigrateTimerService stopped, the vCenter/guest credentials expired (a rotated service-account password), or a previously-open URL got newly blocked (firewall/proxy change). Check the config manager health and the appliance services, and re-validate credentials and connectivity. Discovery is continuous — it goes stale the moment any of those breaks.
11. Why might you deliberately NOT enable dependency analysis for all servers at once? Agentless dependency analysis has a per-appliance server ceiling and adds guest-channel load, so enabling it estate-wide can exceed limits and strain hosts. Enable it for the current migration wave’s servers, where the dependency groups actually inform sequencing, and expand wave by wave.
12. How do you avoid over-provisioning the Azure target from discovery data? Don’t assess on the first few minutes of data — wait for a performance window of several days so right-sizing is performance-based (real CPU/RAM/disk utilisation, e.g. p95) rather than as-on-premises (the VM’s allocated specs). Assessing too early ships the on-prem allocation to Azure and inflates the estimate, often by a large margin.
These map to AZ-305 (Designing Microsoft Azure Infrastructure Solutions) — design a migration strategy, assessment and dependency analysis — and the practical migration motions in AZ-104 (Administrator) where Azure Migrate, appliances and assessments appear. The networking-connectivity angle (outbound URLs, proxy, private endpoints) reinforces AZ-700 thinking. A compact cert-mapping for revision:
| Question theme | Primary cert | Objective area |
|---|---|---|
| Registration, appliance, project key | AZ-305 / AZ-104 | Design/perform migration; Azure Migrate setup |
| Outbound URLs, proxy, private endpoints | AZ-700 / AZ-305 | Connectivity for migration tooling |
| vCenter role/scope, guest credentials | AZ-104 | Configure and run discovery |
| Software inventory & dependency mapping | AZ-305 | Assessment depth & wave planning |
| Performance-based right-sizing | AZ-305 | Cost-optimised target design |
Quick check
- The appliance is stuck on “Register with Azure Migrate.” Where do you run your first connectivity test, and what’s the single most common cause?
- You added the vCenter account and see a full VM list, but every server says “Credentials not provided.” What’s missing, and where do you add it?
- True or false: one Azure Migrate appliance can discover every VM across two separate vCenter Servers.
- Software inventory is blank on a handful of VMware VMs but works on the rest. Name the most likely cause.
- Dependency mapping shows nothing even though guest sign-in and software inventory work. Why, and what’s the fix?
Answers
- Run
Test-NetConnection management.azure.com -Port 443(and the identity/Service Bus/storage URLs) on the appliance itself — a browser on a laptop proves nothing about the appliance’s path. The most common cause is a default-deny firewall blocking the required outbound URL set; allow-list the complete set on 443 and re-register. - Guest-OS credentials are missing — vCenter credentials give the VM list and sizing but not the guest depth. Add a domain account (Windows) and Linux password/SSH-key credentials in the appliance configuration manager, and the appliance re-validates each server.
- False. One appliance covers one vCenter’s reach; a second vCenter needs a second appliance registered to the same project. A partial count that looks complete is exactly the multi-vCenter trap.
- VMware Tools is stopped, missing, or out of date on those VMs — VMware agentless guest discovery rides on Tools. Confirm Tools status per VM in vCenter and install/start/update it on the affected guests.
- Agentless dependency analysis is off by default and must be enabled per server, independent of guest credentials. Enable it for the servers in your migration wave; the network connections build over subsequent collection cycles.
Glossary
- Azure Migrate project — the Azure resource that collects discovery and assessment data; the appliance registers to it.
- Appliance — the on-premises VM (VMware OVA, Hyper-V VHD, or script-installed Windows Server) that runs the discovery agents and is the only component that communicates with Azure.
- Configuration manager — the appliance’s local web app (
https://<appliance-name>:44368) where you register, add data sources and credentials, and read per-hop health; the first place to confirm any failure. - Registration — the one-time step that establishes trust between the appliance and the project; requires identity/management URL reachability, correct time, a valid project key, and sufficient RBAC.
- Project key — the project-scoped string you paste into the appliance to bind it to the project; wrong/expired keys fail registration.
- Agentless discovery — collection of VM configuration and performance via the vCenter/host connection, with no agent installed inside each VM.
- Guest-level discovery — the deeper data (installed software inventory and dependencies) that requires signing into the guest OS via VMware Tools + WinRM/SSH.
- Guest credentials — OS sign-in credentials (domain/local Windows, Linux password/SSH key) added to the appliance for guest-level discovery; their absence yields “Credentials not provided.”
- Software inventory — the list of installed applications/roles per VM, collected by guest-level discovery.
- Agentless dependency analysis — discovery of network connections between servers (for wave grouping), off by default and enabled per server; needs working guest sign-in.
- AzureMigrateTimerService — the appliance Windows service that drives recurring discovery cycles; if stopped, discovery stalls.
- VMware Tools — the in-guest agent on VMware VMs through which the appliance performs guest-level discovery; must be installed and running.
- WinRM / SSH — the guest management channels (Windows 5985/5986, Linux 22) the appliance uses for guest sign-in; blocked channels stop software/dependency collection.
- Private endpoint (project) — a private-link path to the project’s data plane for locked-down estates; reduces required public URLs but still needs identity/management endpoints.
- Performance-based right-sizing — Azure target sizing derived from collected utilisation (e.g. p95 CPU/RAM/disk) rather than the VM’s allocated specs (as-on-premises), the basis of accurate cost estimates.
Next steps
You can now localise any Azure Migrate discovery failure to a hop and fix it. Build outward:
- Next: Azure Migrate Discovery & Assessment: From Appliance Deployment to Your First Right-Sizing Report — the happy-path end-to-end once discovery is healthy.
- Related: Deploying the Azure Migrate Appliance: Discovering VMware, Hyper-V & Physical Estates — the appliance deployment this article troubleshoots.
- Related: Migration Wave Planning: Grouping Servers by Dependency, Risk & Business Cutover Windows — turn the dependency data you collected into safe migration waves.
- Related: Server Migration with Azure Migrate: Agentless Replication, Test Migration & Production Cutover — the replication phase that follows a solid assessment.
- Related: Choosing Your Migration Tool: Azure Migrate vs Site Recovery vs Database Migration Service — confirm Azure Migrate is the right tool for each workload.
- Related: Diagnosing Connectivity with Network Watcher: Connection Monitor, Connection Troubleshoot and Next Hop — deeper network diagnostics for the connectivity failures above.