Azure Troubleshooting

Troubleshooting Arc-Enabled Servers: Disconnected Agents, Missing Heartbeats & Extension Failures

The Arc portal blade says the worst single word in hybrid operations: Disconnected. The server itself is up — you are SSH’d into it right now — but Azure has stopped hearing from it, so every Arc capability silently degrades: Azure Policy compliance goes stale, Azure Monitor Agent stops shipping logs, Defender for Servers loses coverage, and any extension you queue just sits there. Azure Arc is the control plane that projects a non-Azure machine — an on-prem VM, a bare-metal box, an EC2 or GCE instance — into Azure Resource Manager as a first-class Microsoft.HybridCompute/machines resource, kept alive by a small local agent phoning home. When the call stops, the resource is still in the portal, but it is a ghost.

This is the diagnostic playbook for when that agent misbehaves. We treat the three classic failures — a Disconnected agent, a missing heartbeat (looks connected but status fields are stale), and extension failures (AMA, Custom Script, Defender stuck in Creating or Failed) — not as random gremlins but as a short list of concrete causes you confirm with specific commands. You read the local side (himds, the azcmagent CLI, the agent logs) and the cloud side (the resource’s status, the extension state, Resource Graph) to localise any failure to one layer.

By the end you will stop restarting the agent and hoping. When the blade says Disconnected you will know within minutes whether the himds service died, egress is blocked, the identity token failed to renew, the clock skewed, or onboarding was never completed. Knowing which is the difference between a one-command fix and a day of guessing — and it is almost never “delete the resource and re-onboard,” the expensive reflex this article exists to prevent.

What problem this solves

Arc’s promise — one inventory, policy engine, identity model and monitoring agent across clouds and on-prem — rests entirely on a slim local agent maintaining a continuous, authenticated connection. When it breaks the failure is uniquely frustrating: the machine is fine and serving traffic, but Azure has gone blind to it, and every governance and security control on top quietly stops working.

What breaks without this knowledge: an operator sees Disconnected, restarts himds, watches it flip to Connected for a few minutes, then go stale again — because the real cause (an expired service principal, a proxy dropping long-lived TLS, a firewall change that closed *.his.arc.azure.com) was never addressed. Or they disconnect and re-onboard, minting a new resource ID that orphans the old one, breaks every policy and RBAC grant scoped to it, and double-counts the machine in inventory and Defender billing. The machine looks fixed for a day; the governance debt lingers for months.

Who hits this: anyone running Arc at any scale. It bites hardest on proxy-mandated networks (the endpoint requirements are unforgiving), machines onboarded with a short-lived service principal secret that later expired, fleets where TLS interception mangles the agent’s calls, and anyone who layered AMA or Defender on Arc then wondered why a connected machine ships no data. The fix is almost never re-onboarding — it is finding the one layer that’s lying and making it tell the truth.

To frame the field, here is every symptom class this article covers, the question it forces, and where to look first:

Symptom class What Azure is telling you First question to ask First place to look Most common single cause
Agent Disconnected “I haven’t heard from this machine recently” Is the local service up, or is egress blocked? azcmagent show (local) + portal Status himds stopped, or Arc endpoints firewalled
Missing heartbeat / stale status “Connected, but the last contact is old” Is the agent running but failing to send? azcmagent check + agent logs Proxy drops the connection; clock skew
Onboarding failed “The connect attempt errored out” Identity, network, or already-connected? azcmagent connect exit + connect log Bad/expired service principal or RBAC
Extension stuck/failed “The machine is fine but the extension won’t go healthy” Is it the agent, the extension, or its config? Extension provisioningState + extension log AMA needs a DCR; CSE script returned non-zero
Identity/token failure “Calls that need a token are 401/403” Has the system-assigned identity expired? IMDS token endpoint on the machine Token endpoint blocked or clock skew

Learning objectives

By the end of this article you can:

Prerequisites & where this fits

You should understand Arc at a control-plane level — that it projects a non-Azure machine into Azure as a Microsoft.HybridCompute/machines resource so policy, RBAC, monitoring and Defender apply like an Azure VM. If that’s new, read Azure Arc Explained: One Control Plane for Servers, Kubernetes & Data Across Any Cloud first. You should also have onboarded at least one machine; the bulk-enrolment mechanics and onboarding credential are covered in Onboarding Servers to Azure Arc: Connected Machine Agent, Service Principals & Bulk Enrollment, and we refer back to that credential as a root cause.

You should be comfortable running az in Cloud Shell and getting a root/Administrator shell on the machine to run azcmagent and inspect services and logs, with basic familiarity with TLS, proxies and DNS. Because so many failures here are really identity failures, a mental model of managed identities helps — see Managed Identities Demystified: System vs User-Assigned and When to Use Each.

This sits in the Hybrid & Troubleshooting track, upstream of every Arc capability: a machine that isn’t reliably Connected can’t be governed by Remediate Non-Compliant Resources: Remediation Tasks and Managed Identity Setup, monitored via No Logs Showing Up? Troubleshooting Empty Log Analytics Tables and Ingestion Gaps, or protected by Defender. Six layers can each cause a distinct failure, and knowing which tells you who to call: the machine OS (service down, clock skew), the agent (himds/extension manager), network/proxy (firewall, TLS inspection), Entra identity (SPN, system identity), the ARM resource (stale status, extension Failed), and extension config (DCR, CSE script).

Core concepts

Five mental models make every later diagnosis obvious.

Arc is a connection, not an install. Onboarding performs a connect that registers the machine in ARM, provisions a system-assigned managed identity in Entra ID, and stores a local certificate the agent uses to authenticate every subsequent call. The machine’s value is the live connection, maintained by the local himds daemon. When you see Disconnected, the resource still exists — but the connection that made it useful has lapsed.

The status is a heartbeat verdict, not a health check of your server. The agent sends a status roughly every 5 minutes; Azure marks it Connected while those arrive and flips to Disconnected once the machine stops reporting for long enough. “Disconnected” never means “the server is down” — it means “the connection lapsed,” and your app can be serving traffic happily on a machine Azure considers disconnected.

The agent is three cooperating parts. The himds daemon maintains the connection, renews the identity, and exposes a local IMDS token endpoint for on-machine code; the extension manager installs and reports on extensions; the azcmagent CLI is your control surface. A failure almost always lives in exactly one of these three, and knowing which narrows the fix instantly.

Egress is the lifeline, and it is specific. The agent needs only outbound 443 — no inbound — but to a defined set of endpoints (detailed in the network section). Block one, or have a proxy intercept TLS by re-signing the agent’s certificate-validated calls, and the connection fails in ways that look like the machine’s fault. This is the single most common root-cause class in real estates.

The system-assigned identity is the machine’s passport, and it expires. The agent renews the credential automatically — but if the renewal can’t reach Entra or the clock skews beyond the token’s tolerance (a few minutes), token validation fails, and anything needing a token — the agent’s own status calls, the AMA/Defender data plane — returns 401/403. A surprising share of “Disconnected” and “no data” incidents are really clock-skew or token-renewal failures in a network costume.

The agent status and error reference

Before the per-symptom anatomy, here is the lookup table you scan first: the status and error situations you realistically see from an Arc machine, what each means, how to confirm it, and the first fix. The non-obvious ones are Disconnected (heartbeat lapsed) versus Expired (the credential itself lapsed), and the proxy-induced failures that present as generic connection errors.

Status / error Meaning Likely cause How to confirm First fix
Disconnected No heartbeat within the window himds stopped, egress blocked, token failing azcmagent show; systemctl status himds Start service; run azcmagent check; unblock egress
Expired The machine’s credential/cert expired Machine offline > ~45 days; renewal never reached Entra azcmagent show shows expired; portal flag Reconnect with azcmagent connect (same resource)
AZCM0061 / connection failed Agent can’t reach a required endpoint Firewall/proxy blocking an Arc URL azcmagent check lists the failing URL Allow the URL; set the proxy
AZCM0143 / TLS / cert error TLS handshake to an endpoint failed SSL inspection re-signing the cert azcmagent check shows TLS failure Bypass inspection for Arc URLs
401 / 403 on token Identity token rejected Clock skew; identity not provisioned; egress to login blocked Curl the local IMDS endpoint; check time sync Fix clock (NTP); confirm egress to login.microsoftonline.com
AuthorizationFailed (onboard) The connect principal lacks rights SPN missing Azure Connected Machine Onboarding azcmagent connect error; az role assignment list Grant the onboarding role at the RG
Resource already exists (onboard) A resource with that name/ID exists Re-onboarding without disconnect Portal shows the machine; az connectedmachine show Disconnect first, or reuse the existing resource
Extension provisioningState: Failed The extension install/run failed Bad settings, script non-zero, missing DCR az connectedmachine extension show; extension log Fix config; re-push; read the per-extension log
Extension stuck Creating Extension manager can’t complete Agent unhealthy, egress to guestconfig blocked Extension state + agent status Fix the agent first; unblock guestconfig endpoint
AMA installed, no data Agent healthy but logs/metrics missing No DCR association, or workspace/egress issue DCR association list; Heartbeat table query Associate a DCR; verify workspace + egress

One reading note saves the most time: if azcmagent show says Connected but an extension is Failed or no logs arrive, the connection is fine — it’s an extension/DCR problem, so read the extension log, not the agent log.

Anatomy of a Disconnected agent

A Disconnected status means Azure hasn’t received a heartbeat within its window. Four distinct causes — scan the matrix, then read the matching detail:

# Disconnected cause Tell-tale signal Confirm with Real fix Band-aid that masks it
1 Local himds service stopped/crashed Agent Status local = Disconnected; service not running azcmagent show; systemctl status himds Start/enable the service; fix the crash cause Restart only (recurs if root cause stands)
2 Egress to Arc endpoints blocked azcmagent check flags a failing URL azcmagent check; agent himds log Allow the endpoints; configure the proxy None — it never reconnects
3 Onboarding credential / identity expired Status Expired; machine was offline long azcmagent show; portal expiry flag azcmagent connect again (same resource)
4 Clock skew breaks token validation 401/403 in logs; system time off timedatectl / w32tm; IMDS curl Fix NTP; resync time Restart (drifts again without NTP)

Cause 1 — The local agent service stopped or crashed

Services stop: a reboot without auto-start, an OS patch that broke a dependency, a disk-full condition, or a manual stop someone forgot to undo. With himds down, no heartbeat goes out and Azure flips the machine to Disconnected — even though the server is otherwise healthy.

Confirm. Ask the agent first (azcmagent show reports status, version and last attempt), then the service:

# Linux — the agent self-report, then the service
azcmagent show
systemctl status himds
journalctl -u himds --since "1 hour ago" --no-pager

On Windows the service is “Azure Hybrid Instance Metadata Service” (himds): Get-Service himds | Format-List Status, StartType.

Fix. Start and enable the service so it survives reboots, then re-check (Set-Service himds -StartupType Automatic; Start-Service himds on Windows):

# Linux
sudo systemctl enable --now himds
azcmagent show --query 'status' -o tsv   # expect: Connected (allow a few minutes)

If it starts then dies, read journalctl -u himds / the Windows Event Log for the crash reason (commonly disk full, a corrupt config, or a failed dependency) rather than restarting in a loop. The agent is really three services — himds (connection/identity), the extension manager (GCArcService on Windows), and guest configuration — so a Disconnected symptom is himds, a stuck-Creating symptom the extension manager.

Cause 2 — Egress to the Arc endpoints is blocked

The agent needs outbound 443 to a specific set of hosts. A firewall change, a new proxy mandate, or an over-zealous security baseline closes one, and the heartbeat can’t get out — the machine online, the service running, but the call failing. This is the most common Disconnected cause, and the one most often misdiagnosed as “the agent is broken.”

Confirm. The agent’s built-in connectivity checker tests every required endpoint and names the one that fails:

# Tests DNS + TLS reachability to every required Arc endpoint for your region
azcmagent check
# Add the cloud/region if needed:
azcmagent check --location centralindia --cloud AzureCloud

A pass prints each URL as reachable; a failure names the URL and the reason (DNS, connection, or TLS). If ambiguous, corroborate from the agent log (sudo tail -n 100 /var/opt/azcmagent/log/himds.log).

Fix. Allow the endpoints (full list below); if the machine uses a proxy, tell the agent:

# Point the agent at an outbound proxy (persists in agent config)
azcmagent config set proxy.url "http://proxy.corp.local:3128"
# Exclude hosts that must NOT go via proxy (e.g. local IMDS, internal):
azcmagent config set proxy.bypass "Arc,WireServer"   # known bypass keywords

Read the azcmagent check failure by layer: DNS = blocked/split-horizon DNS (or a missing Private DNS zone); connection = the firewall blocking 443; TLS/certificate = the most damaging, TLS interception re-signing the agent’s calls (bypass inspection for the Arc endpoints, don’t trust the CA). If every endpoint is reachable yet still Disconnected, move to Cause 3 (expired) or Cause 4 (clock).

Cause 3 — The onboarding credential or machine identity expired

Arc tolerates going offline, but not forever. If a machine is off for a long stretch (the documented window is around 45 days), its credential lapses and the status becomes Expired — the agent can no longer authenticate with the stored certificate, so even with perfect egress it can’t reconnect itself.

Confirm. azcmagent show reports whether the credential is valid; the portal surfaces an Expired indicator. From Azure, the resource status confirms it:

az connectedmachine show -n srv-onprem-01 -g rg-arc-prod \
  --query "{status:status, lastStatusChange:lastStatusChange, agentVersion:agentVersion}" -o json

Fix. Re-run connect. Reconnecting the same machine to the same resource does not mint a duplicate — it re-establishes the identity for the existing resource (no disconnect first for an expired recovery):

# Re-establish identity for the SAME resource (service-principal onboarding)
azcmagent connect --resource-group rg-arc-prod --subscription-id <sub-id> \
  --location centralindia --service-principal-id <appId> --service-principal-secret <secret>

This is the one place reconnecting is correct — bindings are preserved, unlike the wrong reflex (disconnect + re-onboard a merely-Disconnected machine) which orphans the resource. The distinction in three: a lapsed heartbeat with a valid credential is Disconnected (it reconnects itself once you fix service/egress/clock); an expired credential needs azcmagent connect (same resource ID); a decommissioned machine is azcmagent disconnect’d and deleted.

Cause 4 — Clock skew breaks token validation

Entra tokens are time-bound; if the machine’s clock drifts beyond the allowed tolerance (a few minutes), the agent’s tokens are rejected as not-yet-valid or expired and authenticated calls — including the heartbeat — fail with 401/403. The machine looks network-healthy (azcmagent check passes) but won’t connect, which is maddening until you check the clock. VMs resumed from a long pause/snapshot and machines with broken NTP are the usual victims.

Confirm and fix. Check the offset, then restore sync — once the clock is correct, validation succeeds and the agent reconnects on its next cycle (Windows: w32tm /query /status, then w32tm /resync /force):

# Linux — check the offset, then enable NTP and step the clock immediately
timedatectl status
chronyc tracking 2>/dev/null || ntpq -p 2>/dev/null
sudo systemctl enable --now chronyd && sudo chronyc makestep

A quick probe ties clock to identity: ask the local IMDS endpoint for a token. A 401 asking for the challenge token is expected (a security guard — see Security notes); a timeout means himds is down or blocked; a nbf/time/expiry error is clock skew; a 403 after the challenge is RBAC on the target, not Arc.

# A 401 asking for the challenge token here is EXPECTED and healthy.
# A timeout, or a time/nbf error in the body, points at the real problem.
curl -s -D - -H "Metadata:true" \
  "http://localhost:40342/metadata/identity/oauth2/token?api-version=2020-06-01&resource=https://management.azure.com/" \
  -o /dev/null

Anatomy of a missing heartbeat

Sometimes the portal says Connected but lastStatusChange is hours old and a Heartbeat query shows the machine fell silent and came back — the agent running but failing to send reliably. Three causes share one spine (gaps in the Heartbeat table) but diverge on what the log shows around the gap:

# Missing-heartbeat cause Heartbeat table Agent log around the gap Real fix
1 Proxy/firewall drops the connection Periodic gaps, clean recovery Connection reset/timeout/proxy errors Align proxy idle timeout; correct bypass list
2 Time jitter (two competing time sources) Sporadic gaps Occasional 401/token errors One authoritative time source (NTP or host)
3 Host resource starvation Gaps tied to host load Quiet (the agent just didn’t run) Relieve CPU/IO pressure; right-size the box

Confirm. The Heartbeat table records each agent check-in, so a gap is unambiguous:

// Gaps in Arc agent heartbeats over the last day (a healthy machine has steady beats)
Heartbeat
| where TimeGenerated > ago(1d)
| where Category == "Azure Monitor Agent" or ResourceType == "machines"
| summarize beats = count() by bin(TimeGenerated, 5m), Computer
| where beats == 0
| order by TimeGenerated desc

Then read the agent log around those timestamps to tell them apart:

# Connection resets/timeouts → Cause 1; 401/token → Cause 2; silence → Cause 3 (check host CPU/IO)
sudo grep -iE "reset|timeout|proxy|401|unauthorized|token" /var/opt/azcmagent/log/himds.log | tail -n 40
chronyc tracking   # 'System time' offset should be tiny and stable; jitter points at Cause 2

Fix per the matrix: align the proxy idle timeout (and make any TLS-inspection bypass consistent — partial inspection produces exactly this flicker), pick one authoritative time source, or relieve a starved host. The agent is innocent in all three; it just needs to reach Azure on schedule.

Anatomy of a failed onboarding

When azcmagent connect fails, the machine never becomes a healthy resource. Three cause families — identity, network, state — scan then read the detail:

# Onboarding failure Tell-tale signal Confirm with Real fix
1 Onboarding principal lacks rights AuthorizationFailed on connect connect error; az role assignment list Grant Azure Connected Machine Onboarding at the RG
2 Service principal secret expired/wrong Auth error before any resource is made connect error; SPN credential dates Rotate the secret; re-run connect
3 Endpoint/proxy blocked at connect time AZCM0061/connection error to a URL azcmagent check before connect Open endpoints / set proxy, then connect
4 Resource already exists / stale Resource already exists or duplicate Portal; az connectedmachine show Reuse or disconnect the old one first

Cause 1 — The onboarding principal lacks the right role

Bulk onboarding uses a service principal that must hold Azure Connected Machine Onboarding on the target scope; without it, connect fails with an authorization error before any resource exists.

Confirm. The connect output names the failure; verify the assignments:

# What roles does the onboarding SPN actually hold at the RG?
az role assignment list \
  --assignee <appId> \
  --resource-group rg-arc-prod \
  --query "[].{role:roleDefinitionName, scope:scope}" -o table

Fix. Grant the onboarding role at the resource group (least privilege — not subscription Owner):

az role assignment create \
  --assignee <appId> \
  --role "Azure Connected Machine Onboarding" \
  --scope /subscriptions/<sub-id>/resourceGroups/rg-arc-prod

There are two Arc roles, scoped to the RG: Azure Connected Machine Onboarding (create/read machines, install the agent) is all the onboarding SPN needs — not Owner — while Azure Connected Machine Resource Administrator (manage machines and extensions) is for ongoing fleet management.

Cause 2 — The service principal secret is wrong or expired

The most common bulk-onboarding failure isn’t permissions — it’s an expired secret. The SPN was created with a 1- or 2-year secret, the script still carries the old value, and connect fails with no resource created. The tell is that it hits en masse — every machine in a wave fails identically. Confirm the validity window, rotate the secret, update the onboarding store, and re-run:

# When does the SPN secret expire? A past end date is the cause.
az ad app credential list --id <appId> --query "[].{end:endDateTime}" -o table

A short-lived secret baked into a script is a time bomb — treat it as a vaulted, rotated credential. (For bulk-enrolment mechanics, see Onboarding Servers to Azure Arc: Connected Machine Agent, Service Principals & Bulk Enrollment.)

Cause 3 — Endpoints blocked, or a stale resource already exists

The last two are quick to rule out. Blocked egress at connect time gives a connection error (often AZCM0061) naming the unreachable host — onboarding has the same endpoint requirements as steady state, so run azcmagent check before connect, and pass --proxy-url if you onboard through a proxy:

azcmagent check --location centralindia --cloud AzureCloud   # pre-flight before connect

A Resource already exists error means a resource with that identity is already there — how teams accidentally create duplicates by re-onboarding instead of reconnecting. Check with az connectedmachine show -n <name> -g <rg>: if it’s the same machine, fix the connection in place (or reconnect for an expired credential); only if it’s a stale leftover from a decommissioned machine do you azcmagent disconnect (or az connectedmachine delete) first and onboard cleanly.

Anatomy of an extension failure

Once a machine is reliably Connected, the next pain is extensions — AMA, Custom Script, Defender, the Dependency agent. The connection is fine; the extension won’t go healthy. Cardinal rule: if azcmagent show says Connected, read the extension log, not the agent log. Five causes — scan, then detail:

# Extension failure Tell-tale signal Confirm with Real fix
1 AMA installed but no data Healthy extension, empty tables DCR association list; Heartbeat query Associate a Data Collection Rule
2 Custom Script Extension non-zero exit provisioningState: Failed after run Extension status message; CSE stdout/stderr log Fix the script; make it idempotent; re-push
3 Extension stuck Creating/Transitioning Never reaches Succeeded Extension state + agent health + egress Fix agent; unblock guestconfiguration endpoint
4 Wrong settings / version mismatch Fails immediately on push Extension settings vs schema; log Correct settings; pin a supported version
5 Defender extension unhealthy Defender coverage gap on the machine Defender for Servers plan + extension state Enable the plan; let auto-provision install it

Cause 1 — Azure Monitor Agent installed but shipping no data

The number-one extension confusion: AMA installs cleanly, shows Succeeded, the agent is Connected — yet Heartbeat, Syslog and Perf are empty. AMA collects nothing until a Data Collection Rule (DCR) is associated. Unlike the legacy Log Analytics agent, it’s inert without a DCR telling it what to collect and where.

Confirm. The extension shows Succeeded — so check the DCR association, almost always the missing piece:

# Are any DCRs associated with this machine? (empty = the smoking gun)
az monitor data-collection rule association list \
  --resource "$(az connectedmachine show -n srv-onprem-01 -g rg-arc-prod --query id -o tsv)" -o table

An empty list is the smoking gun; an empty Heartbeat table confirms it.

Fix. Associate a DCR (create one targeting your workspace and data sources, then associate it):

az monitor data-collection rule association create \
  --name "dcra-srv-onprem-01" \
  --resource "$(az connectedmachine show -n srv-onprem-01 -g rg-arc-prod --query id -o tsv)" \
  --rule-id "$(az monitor data-collection rule show -n dcr-linux-syslog -g rg-arc-prod --query id -o tsv)"

As a short decision: no DCR = inert, associate one; DCR but no Heartbeat = downstream (workspace/egress/data-plane); only some tables = the DCR’s sources are too narrow; Failed = AMA didn’t install, read its log. (For the full empty-tables tree, see No Logs Showing Up? Troubleshooting Empty Log Analytics Tables and Ingestion Gaps.)

Cause 2 — Custom Script Extension exits non-zero

CSE runs your script; a non-zero exit makes the extension Failed, the message being whatever the script wrote to stderr plus the exit code. People stare at the extension state when the answer is in the script’s output log.

Confirm. Read the status from Azure, then the script’s stdout/stderr on the machine:

az connectedmachine extension show \
  --machine-name srv-onprem-01 -g rg-arc-prod --name customScript \
  --query "{state:provisioningState, status:instanceView.status}" -o json

The on-machine CSE output (Linux) lives under the extension’s directory:

sudo find /var/lib/GuestConfig /var/lib/waagent -iname "*stdout*" -o -iname "*stderr*" 2>/dev/null

Fix. Make the script exit 0 and idempotent (CSE may re-apply; a mkdir without -p that fails on re-run creates phantom failures), then re-push. By fingerprint: a first-run failure is a script bug; a re-run-only failure is non-idempotency; a timeout is a hanging script; a download error is an expired blob SAS or blocked storage egress.

Cause 3 — Stuck Creating, wrong settings, or an unhealthy Defender extension

An extension stuck in Creating/Transitioning means the extension manager can’t complete — usually the agent is unhealthy, or egress to *.guestconfiguration.azure.com is blocked while the agent’s own endpoint is open. Verify agent health first (a stuck extension on a Disconnected agent is downstream), confirm the guestconfig URL with azcmagent check, then delete and re-push:

azcmagent show --query 'status' -o tsv        # must be Connected first
azcmagent check                               # confirm the guestconfiguration URL is reachable
az connectedmachine extension delete --machine-name srv-onprem-01 -g rg-arc-prod --name <ext> --yes

Wrong settings or an unsupported version fail immediately on push, the message quoting the offending field — correct to the documented schema and pin a supported version (settings are reviewed Bicep). And an unhealthy Defender extension is a security gap behind a green agent: it’s auto-provisioned when Defender for Servers is enabled, so if the plan or auto-provisioning is off, a Connected machine has no protection — enable both at the subscription. The extensions you’ll most often manage, and what each needs:

Extension Purpose The thing it needs beyond “installed” Confirm it’s working via
Azure Monitor Agent Ship logs/metrics A DCR association Heartbeat rows for the machine
Custom Script Extension Run a script An idempotent, exit-0 script provisioningState: Succeeded
Dependency agent (VM Insights) Process/connection maps AMA + the VM Insights DCR The Map in VM Insights
Microsoft Defender Threat protection Defender for Servers plan enabled Defender coverage = On
Guest configuration Policy-in-guest audit Policy assignment + agent health Guest assignment = Compliant

The network and endpoint requirements

Half of all Arc agent incidents are an egress problem, so keep this reference open. The agent needs only outbound TCP 443 — no inbound — to these hosts (region-specific subdomains apply; azcmagent check validates your exact set):

Endpoint (host) Purpose Required for If blocked you see
*.his.arc.azure.com Hybrid Identity Service (agent) Heartbeat, identity Disconnected; onboarding fail
*.guestconfiguration.azure.com Guest config / extensions Extensions, policy-in-guest Extensions stuck Creating
login.microsoftonline.com Entra ID token issuance Identity, all auth 401/403; onboarding auth fail
management.azure.com Azure Resource Manager Registration, status Onboarding fail; status not updating
*.guestnotificationservice.azure.com Notifications / Connect-to-machine Some interactive features Certain features unavailable
*.servicebus.windows.net Notification channel (WebSocket) Real-time features (SSH, Win Admin) Connect-to-machine features fail
pas.windows.net Privileged access (some scenarios) RBAC for certain features Feature-specific auth issues
Data ingestion (AMA) endpoints Log/metric ingestion (DCE/workspace) AMA data plane AMA “no data” despite healthy agent

Three hard truths the table can’t convey. Private endpoints change the URL set: with an Azure Arc Private Link Scope the agent talks to private endpoints, and a missing Private DNS zone shows up as DNS failures in azcmagent check (see Diagnosing Connectivity with Network Watcher: Connection Monitor, Connection Troubleshoot and Next Hop). TLS inspection is the silent killer — exclude the Arc endpoints rather than trusting the inspection CA. And tell the proxy to the agent: azcmagent config set proxy.url, proxy.bypass "Arc,WireServer" so IMDS/local traffic skips it, and --proxy-url on azcmagent connect.

The diagnostic toolkit: exact commands

Knowing where to look is half the battle. The tools matrix:

Tool What it shows Where you run it Best for
azcmagent show Agent status, version, resource ID, last attempt On the machine First look: is the connection up locally?
azcmagent check DNS/TLS reachability to every required endpoint On the machine Egress/proxy/TLS-inspection problems
azcmagent logs Bundles all agent logs into a zip On the machine Collecting evidence; support tickets
Agent log files himds.log, extension logs, raw detail On the machine (/var/opt/azcmagent/log) Crash reasons, connection resets, token errors
az connectedmachine show The ARM resource: status, lastStatusChange Cloud Shell Azure’s view; Disconnected vs Expired
az connectedmachine extension ... Extension state, settings, status Cloud Shell Extension Failed/Creating triage
Azure Resource Graph Fleet-wide status across machines Cloud Shell / portal Finding all Disconnected machines at once
Heartbeat table (KQL) Per-machine check-in history Log Analytics Heartbeat gaps; AMA data-flow proof
Local IMDS curl Token issuance from the machine identity On the machine Identity/clock probe

Two earn extra emphasis: azcmagent show (Connected locally but Disconnected in the portal = a send problem, ruling out half the causes) and azcmagent check (resolves most incidents on its own by naming the blocked URL and distinguishing DNS from TCP from TLS). For every Disconnected machine across subscriptions at once, Azure Resource Graph is the fleet view:

// All Arc machines and their connection status, newest status-change first
// (run in the portal's Resource Graph Explorer, or via `az graph query -q "..."`)
resources
| where type =~ "microsoft.hybridcompute/machines"
| extend status = tostring(properties.status), lastChange = todatetime(properties.lastStatusChange)
| project name, resourceGroup, status, agentVersion = tostring(properties.agentVersion), lastChange
| order by lastChange desc

Architecture at a glance

Hold this mental model and every diagnosis falls into place. Inside the machine — anywhere — the agent’s core himds daemon loops three things: sends a heartbeat every few minutes, renews the system-assigned identity against Entra ID, and exposes a local IMDS token endpoint (localhost:40342) for on-box code; alongside it the extension manager runs extensions. From the machine, only outbound 443 leaves — no inbound — fanning to the Hybrid Identity Service (*.his.arc.azure.com) for heartbeat and identity, Entra for tokens, ARM for the resource status, and guest configuration (*.guestconfiguration.azure.com) for extensions. Those heartbeats keep the Microsoft.HybridCompute/machines resource Connected; the moment they stop, ARM flips it to Disconnected — regardless of your server’s health.

That picture localises every failure to one hop: a dead himds = no heartbeat leaves the box; a firewall on the 443 fan-out = it can’t reach Azure; a skewed clock or blocked Entra = tokens rejected so even reachable calls fail; a blocked guestconfiguration hop = the connection is fine but extensions hang; an inert extension (AMA without a DCR) = both green while no data flows. Read the symptom, name the hop, run the one command that interrogates it.

Real-world scenario

Northwind Logistics runs a hybrid estate: 240 servers across two on-prem data centres and a VMware cluster, all onboarded to Azure Arc so a team of three can apply Remediate Non-Compliant Resources: Remediation Tasks and Managed Identity Setup, ship logs via AMA, and get Defender coverage. Onboarding was done eighteen months earlier with a service principal whose secret expires in two years. Monthly Arc-adjacent spend (Monitor + Defender) ran about ₹140,000.

The incident surfaced on a Monday: the dashboard showed 38 machines Disconnected — all in the same data centre, all gone within the same two-hour weekend window. The on-call engineer restarted himds on one; it flipped to Connected for about four minutes, then went straight back. Second reflex: disconnect and re-onboard it — which worked, but minted a brand-new resource, orphaning the old one and breaking its three policy assignments. Across 38 machines, that path would have created 38 governance messes.

The breakthrough came from the right first question: local service, or egress? azcmagent show said Connected locally — service fine — yet Azure said Disconnected, ruling out Cause 1. azcmagent check was decisive: it failed on *.his.arc.azure.com and login.microsoftonline.com with a TLS/certificate error while DNS resolved fine — the fingerprint of TLS inspection. The network team had rolled out SSL inspection on the proxy for “all outbound HTTPS” that weekend, silently re-signing the agent’s calls. The restart “fixed” it for four minutes only because the cached token outlived the next failed renewal.

The fix had two parts. Immediately: a bypass rule excluding the Arc endpoints from inspection, after which machines flipped back to Connected within one heartbeat cycle — no re-onboarding, all bindings intact — and the one wrongly re-onboarded machine was reverted (delete the duplicate, reconnect to the original). The following week: they rotated the onboarding secret (four months from its own expiry) into Key Vault and added a Resource Graph alert firing when any machine stays Disconnected over 15 minutes, so the next change is caught in minutes, not on a Monday dashboard.

The lesson on the wall: “Disconnected is a network verdict until the local agent proves otherwise — azcmagent check before you touch the service, and never re-onboard a machine you can reconnect.” The incident as a timeline, because the order is the lesson:

Time Symptom Action taken Effect What it should have been
Mon 09:10 38 machines Disconnected, one DC (dashboard) Ask: local service, or egress?
09:20 Same Restart himds on one Connected 4 min, then Disconnected Run azcmagent show first
09:35 Same Disconnect + re-onboard one Worked, but minted a duplicate resource Don’t re-onboard a reconnectable machine
10:05 Root cause hunt azcmagent show (Connected) + azcmagent check TLS error on his/login URLs This was the breakthrough
10:20 TLS inspection confirmed Network adds Arc bypass to inspection Machines reconnect on their own Correct fix
10:40 Cleanup Delete duplicate; reconnect to original Governance intact
+1 week Hardening Rotate SPN secret to Key Vault; add RG status alert Next change caught in minutes The durable fix is detection + secret hygiene

Advantages and disadvantages

The agent-maintains-a-connection model both causes this class of problem and makes it diagnosable. Weigh it honestly:

Advantages (why this model helps you) Disadvantages (why it bites)
One slim agent, outbound-443-only, brings any machine into Azure governance — no inbound exposure The status you see (Disconnected) is a connection verdict, not server health; you must dig to find which hop failed
azcmagent check pinpoints the exact blocked endpoint — egress problems are named, not guessed The endpoint/proxy requirements are specific and unforgiving; one closed URL silently disconnects the fleet
Reconnecting an expired machine reuses the same resource — policy/RBAC bindings survive The wrong reflex (disconnect + re-onboard) mints a duplicate and orphans bindings — easy to do under pressure
The system-assigned identity gives the machine a passwordless Azure identity for scripts A clock skew or blocked Entra call breaks tokens — and presents as a confusing network/Disconnected issue
Extensions (AMA, Defender, CSE) deploy uniformly across the hybrid fleet from Azure An extension can be green while inert — AMA ships nothing without a DCR; coverage gaps hide behind healthy agents
Resource Graph gives a single fleet-wide view of every machine’s status Without a Disconnected alert, you find out from a dashboard on Monday, not when it happens
TLS-only, certificate-authenticated calls are secure by design TLS inspection breaks exactly those calls — a common “security improvement” that silently kills Arc

The model is right for any organisation wanting Azure governance over machines it can’t move — hybrid, multicloud, edge. It bites hardest on tightly-controlled networks, fleets onboarded with short-lived secrets, and teams that bolt on AMA/Defender without wiring the DCR or plan. Every disadvantage is manageable — but only if you know it exists.

Hands-on lab

Onboard one machine, watch a healthy connection, break it the way real estates do (block egress), confirm with azcmagent check, and fix it. We use a free-tier-friendly Azure VM as the “non-Azure” machine (Arc happily manages an Azure VM for labs), so no external hardware is needed. Run az in Cloud Shell and azcmagent on the VM.

Step 1 — A resource group and a small Linux VM to act as the machine.

RG=rg-arc-lab
LOC=centralindia
VM=vm-arc-lab
az group create -n $RG -l $LOC -o table
az vm create -n $VM -g $RG --image Ubuntu2204 --size Standard_B1s \
  --admin-username azureuser --generate-ssh-keys -o table

Step 2 — Create the onboarding service principal with least privilege.

SUB=$(az account show --query id -o tsv)
az ad sp create-for-rbac --name "sp-arc-lab-onboard" \
  --role "Azure Connected Machine Onboarding" \
  --scopes /subscriptions/$SUB/resourceGroups/$RG -o json
# Note the appId and password from the output for Step 4.

Step 3 — Install the agent on the VM. SSH in, then fetch and run the install script:

# On the VM (over SSH)
wget https://aka.ms/azcmagent -O install_linux_azcmagent.sh
sudo bash install_linux_azcmagent.sh
azcmagent version

Expected: the agent installs and prints a version; himds is present but not yet connected.

Step 4 — Pre-flight, then connect. Always check before connecting:

# On the VM
azcmagent check --location centralindia --cloud AzureCloud   # expect all endpoints reachable
sudo azcmagent connect \
  --resource-group rg-arc-lab --subscription-id <SUB> --location centralindia \
  --service-principal-id <appId> --service-principal-secret <password> \
  --tenant-id "$(az account show --query tenantId -o tsv)"

Expected: Connected to Azure. Confirm both sides:

azcmagent show --query 'status' -o tsv          # on the VM → Connected
# In Cloud Shell:
az connectedmachine show -n $VM -g $RG --query status -o tsv   # → Connected

Step 5 — Break it: block egress. Add an NSG rule denying outbound 443 to simulate a firewall closing the Arc endpoints:

# Cloud Shell — deny outbound HTTPS on the VM's NIC subnet (simulate the firewall change)
NSG=$(az network nsg list -g $RG --query "[0].name" -o tsv)
az network nsg rule create -g $RG --nsg-name $NSG -n deny-https-out \
  --priority 100 --direction Outbound --access Deny --protocol Tcp \
  --destination-port-ranges 443 --destination-address-prefixes Internet

Wait several minutes, then observe: azcmagent check now fails on the Arc endpoints and the machine drifts to Disconnected — Cause 2 reproduced exactly, the service running but egress gone.

azcmagent show --query 'status' -o tsv   # still Connected locally for a bit, then the heartbeat fails
azcmagent check                          # endpoints now unreachable — the smoking gun

Step 6 — Restore egress. Remove the deny rule; the agent reconnects on its own — no re-onboarding:

az network nsg rule delete -g $RG --nsg-name $NSG -n deny-https-out
# Wait one heartbeat cycle, then:
az connectedmachine show -n $VM -g $RG --query status -o tsv   # → Connected again

Validation checklist. You onboarded with a least-privilege SPN, confirmed the connection from both sides, reproduced a Disconnected purely from blocked egress, identified it with azcmagent check, and fixed it by restoring the network — the agent self-recovering with resource and identity preserved. No re-onboarding. The steps mapped to what each proves:

Step What you did What it proves Real-world analogue
2 SPN with onboarding role only Least privilege onboards fine Don’t grant Owner to onboard
4 azcmagent check before connect Pre-flight catches egress early The pre-onboarding firewall review
5 Block outbound 443 Disconnected can be pure network The weekend firewall/TLS change
5 azcmagent check fails on URLs The confirming signal is specific The 2-minute diagnosis
6 Restore egress; agent self-heals No re-onboarding needed Fixing the network, not the resource

Cleanup (avoid lingering charges).

az group delete -n $RG --yes --no-wait
az ad sp delete --id <appId>

Cost note. A Standard_B1s VM is a few rupees per hour; this lab is well under ₹50, and deleting the resource group stops everything. (Arc itself is free for the connected-machine resource — this lab enables no billed services.)

Common mistakes & troubleshooting

This is the playbook — the part you bookmark. Every row maps a symptom to its root cause, the way to confirm it, and the fix; the most-misdiagnosed entries are detailed in the Anatomy sections above.

# Symptom Root cause Confirm (exact cmd / portal path) Fix
1 Portal shows Disconnected; server is up and fine himds service stopped/crashed On machine: azcmagent show; systemctl status himds sudo systemctl enable --now himds; fix crash cause (disk full, dependency)
2 Disconnected; service is running; restart only helps briefly Egress to Arc endpoints blocked azcmagent check names the failing URL Allow the URL on 443; set azcmagent config set proxy.url
3 Disconnected fleet-wide after a security change; TLS errors SSL/TLS inspection re-signing agent calls azcmagent check → TLS/cert error on *.his.arc.azure.com Bypass Arc endpoints from inspection (don’t trust the CA)
4 Status shows Expired; machine was offline for weeks Credential lapsed (offline > ~45 days) azcmagent show (Expired); az connectedmachine show --query status azcmagent connect again — same resource, not re-onboard
5 Reachable network but still won’t connect; 401 in logs Clock skew breaks token validation timedatectl / w32tm /query /status; offset large Fix NTP: chronyc makestep / w32tm /resync /force
6 Onboarding fails with AuthorizationFailed SPN lacks Azure Connected Machine Onboarding connect error; az role assignment list --assignee <appId> Grant the onboarding role at the RG scope
7 Whole onboarding wave fails identically with auth error Service principal secret expired az ad app credential list --id <appId> (end date passed) Rotate the secret; update the onboarding store; re-run
8 Onboarding errors with Resource already exists Re-onboarding without disconnect az connectedmachine show -n <name> -g <rg> returns a resource Reuse it (fix in place) or disconnect/delete the stale one first
9 AMA extension Succeeded but Heartbeat/Syslog empty No Data Collection Rule associated az monitor data-collection rule association list --resource <id> (empty) Associate a DCR targeting the workspace + sources
10 Custom Script Extension shows Failed Script exited non-zero / not idempotent az connectedmachine extension show ... instanceView.status; on-machine stdout/stderr Fix the script to exit 0 and be idempotent; re-push
11 Extension stuck in Creating/Transitioning forever Agent unhealthy or guestconfig endpoint blocked azcmagent show (status); azcmagent check (guestconfiguration URL) Fix agent first; unblock *.guestconfiguration.azure.com; delete + re-push
12 Defender coverage gap on a Connected machine Defender for Servers plan/auto-provision off az connectedmachine extension list (no Defender ext) Enable Defender for Servers + auto-provisioning at the subscription
13 az connectedmachine calls fail / agent very old Agent version unsupported / not upgraded azcmagent show (version); compare to current Upgrade the agent (azcmagent upgrade / package manager)
14 Heartbeat flickers: Connected, brief gaps, recovers Proxy idle-timeout or partial TLS inspection Heartbeat KQL gaps; agent log reset/timeout entries Align proxy timeout; fix bypass list; consistent inspection bypass
15 Token works locally but a script gets 403 to a resource Identity lacks RBAC on the target (not Arc) IMDS curl returns a token; az role assignment list --assignee <principalId> Grant the machine identity the role on the target resource

When in doubt the order is the same: azcmagent show to split send from service, then azcmagent check to name the blocked hop, then the resource/extension state in Azure.

Best practices

The signals worth alerting on before the next incident — the leading indicators, not the lagging “machine down”:

Alert on Signal / source Threshold (starting point) Why it’s leading
Machine Disconnected Resource Graph / Activity Log status flip Disconnected > 15 min Catches a network/agent break in minutes
Heartbeat gap Heartbeat table absence No beat for 10 min Catches flicker before full Disconnect
Agent credential nearing expiry Status approaching Expired window Offline approaching ~45 days Reconnect before the credential lapses
SPN secret expiry Entra app credential end date < 30 days remaining Prevents the wave-wide onboarding failure
Extension Failed Extension provisioningState Any Failed Surfaces AMA/CSE/Defender problems early
AMA data flow Heartbeat rows per machine 0 rows for an “enabled” machine Catches the inert-agent monitoring gap

Security notes

Cost & sizing

The bill drivers. The Arc connected-machine resource is free — resource, agent, identity and inventory cost nothing; you pay for the capabilities you layer on top, where the spend (and the troubleshooting motivation) lives. Azure Monitor ingestion is usually the largest line, billed per GB; a too-broad DCR balloons it, so scoping to what you query also cuts the noise during incidents. And Defender for Servers is per-server, per-month, with a cost trap in duplicates — a machine re-onboarded as a second resource is double-counted and pays twice, another reason never to re-onboard a reconnectable machine.

A rough monthly picture for a 100-server estate: Arc resources free; Defender (Plan 2) at a few hundred rupees per server adds up; Monitor ingestion depends entirely on DCR scope. The cost drivers and what each buys you:

Cost driver What you pay for Rough INR / month (100 servers) What it buys Watch-out
Arc connected machine Nothing ₹0 Inventory, identity, policy, control plane The free foundation everything sits on
Azure Monitor ingestion (AMA) Per-GB into Log Analytics Wildly DCR-dependent Logs/metrics/alerts A broad DCR balloons the bill
Defender for Servers Per server / month Per-server × 100 Threat protection, vuln assessment Duplicates double-bill — avoid re-onboarding
Update Manager / extras Per usage/feature Variable Patch orchestration, guest config Check pricing before fleet enablement
Private Link Scope Endpoint hourly + per-GB ₹1,500–3,000+ Private agent traffic Needs correct Private DNS

The sizing lesson mirrors the troubleshooting one: the platform is cheap; the spend (and the pain) comes from the layered services — fix the cause (a duplicate resource, a sloppy DCR) rather than paying around it.

Interview & exam questions

1. The Arc portal shows Disconnected but you’re SSH’d into the machine and it’s healthy. What does Disconnected mean, and your first command? It means Azure hasn’t received the agent’s heartbeat within its window — a connection verdict, not server health. Run azcmagent show first; if it’s locally Connected you have a send problem (egress/identity), and azcmagent check is next. Don’t restart the service blindly.

2. Difference between a Disconnected and an Expired Arc machine, and why it matters for the fix? Disconnected = a recent heartbeat gap, credential still valid, usually fixable in place (the agent reconnects itself). Expired = offline ~45 days so the credential lapsed; you must run azcmagent connect again, which reuses the same resource. It matters because the wrong fix (disconnect + re-onboard) mints a duplicate and orphans policy/RBAC.

3. A whole data centre goes Disconnected after a network change and azcmagent check shows TLS/certificate errors. What happened? A proxy/NGFW started TLS/SSL inspection, re-signing outbound HTTPS and breaking the agent’s certificate-validated calls — DNS resolves and TCP opens, but the handshake is tampered. Fix by excluding the Arc endpoints from inspection, not by trusting the interception CA.

4. What network access does the agent require, and any inbound? Only outbound TCP 443 to a defined set — the Hybrid Identity Service (*.his.arc.azure.com), guest configuration (*.guestconfiguration.azure.com), Entra (login.microsoftonline.com), ARM (management.azure.com), plus a few supporting hosts. No inbound at all. azcmagent check validates the exact set for your region.

5. AMA shows Succeeded on an Arc machine but no logs arrive. Why? AMA is inert without a Data Collection Rule — unlike the legacy agent, it collects nothing until a DCR is associated. Confirm with az monitor data-collection rule association list --resource <machine-id> (empty = the cause) and the empty Heartbeat table, then associate a DCR.

6. Onboarding fails with AuthorizationFailed. Cause and least-privilege fix? The onboarding SPN lacks the Azure Connected Machine Onboarding role at the target scope. Confirm with az role assignment list --assignee <appId> and grant that role at the resource group — not Owner, not subscription-wide.

7. An entire onboarding wave fails with the same auth error. What do you check first? The service principal secret has expired — the tell is that every machine fails identically at once. Check az ad app credential list --id <appId> for a past end date, rotate it, update the onboarding store, and re-run. Treat the secret as vaulted and rotated.

8. A machine passes azcmagent check but still won’t connect, with 401s in the log. Cause? Clock skew beyond Entra’s token tolerance — tokens are rejected as not-yet-valid or expired, failing the heartbeat and any authenticated call. Confirm with timedatectl / w32tm /query /status; fix NTP, step the clock, and ensure a single time source.

9. A Custom Script Extension shows Failed. Where do you look, and the two common script-side causes? Read the extension status (az connectedmachine extension show ... instanceView.status) for the exit code, then the script’s stdout/stderr on the machine. The two causes are a non-zero exit (script bug/missing dependency) and non-idempotency (fails on re-apply). Fix it to exit 0 and be safe to re-run.

10. Why is re-onboarding a Disconnected machine usually wrong? Disconnect + re-onboard creates a new resource with a new ID, orphaning the old one — breaking every policy assignment and RBAC grant scoped to it, double-counting inventory, and double-billing Defender. Fix a Disconnected machine in place; reconnect an Expired one (reusing the resource). Re-onboarding is only for genuinely new or replaced machines.

11. An extension is stuck in Creating and never reaches Succeeded. Your sequence? Confirm the agent is healthy first (azcmagent show = Connected) — a stuck extension on a Disconnected agent is downstream. Then confirm egress to *.guestconfiguration.azure.com with azcmagent check, since the extension manager needs it. Then delete and re-push.

12. How does code on an Arc machine get an Azure token, and what guards that endpoint? It calls the local IMDS endpoint at http://localhost:40342 for the machine’s system-assigned identity. The endpoint requires a challenge file readable only by privileged users before issuing a token, so a random local process can’t silently impersonate the machine. The identity must hold the right RBAC on the target it calls.

These map to AZ-800 / AZ-801 (Windows Server Hybrid Administrator)manage hybrid servers with Azure Arc, onboarding, agents and extensions — and AZ-104 (Administrator)Arc-enabled servers, monitoring and Defender coverage. The identity and network angles touch AZ-500 (Security Engineer). A compact cert-mapping for revision:

Question theme Primary cert Exam objective area
Agent status, azcmagent, Disconnected vs Expired AZ-800/801 Manage servers with Azure Arc
Onboarding, SPN roles, bulk enrolment AZ-800/801 Onboard and configure Arc agents
Endpoints, proxy, TLS inspection AZ-500 / AZ-700 Secure & connect hybrid networks
AMA + DCR, Heartbeat, no-data triage AZ-104 Monitor Azure & hybrid resources
Managed identity, IMDS, RBAC AZ-500 Manage identity & access
Defender for Servers coverage AZ-500 Secure hybrid compute

Quick check

  1. The portal says a machine is Disconnected but you’re logged into it and it’s healthy. What does Disconnected mean, and what’s the single first command you run on the machine?
  2. azcmagent check reports DNS resolves and TCP connects, but the TLS handshake fails on *.his.arc.azure.com. What is almost certainly happening, and what’s the fix?
  3. True or false: when a Disconnected machine won’t recover, the correct fix is to disconnect it and onboard it again.
  4. An Azure Monitor Agent extension on an Arc machine shows Succeeded, yet Heartbeat is empty for that machine. Name the most likely cause and the one command that confirms it.
  5. Your onboarding pipeline suddenly fails for every machine in a wave with an authentication error. What’s the most probable cause, and where do you check?

Answers

  1. Disconnected means Azure hasn’t received the agent’s heartbeat within its window — a connection verdict, not server health. The first command is azcmagent show on the machine: if it reports Connected locally, the service is fine and you have a send (egress/identity) problem; run azcmagent check next.
  2. A proxy/NGFW is doing TLS/SSL inspection, re-signing the agent’s certificate-validated calls and breaking the handshake (DNS and TCP are fine; only TLS is tampered). The fix is to exclude the Arc endpoints from inspection — not to trust the interception CA.
  3. False. Disconnect + re-onboard mints a new resource and orphans the old one’s policy/RBAC bindings (and can double-bill Defender). For a Disconnected machine you fix the connection in place; only an Expired machine needs azcmagent connect, which reuses the same resource.
  4. No Data Collection Rule (DCR) is associated — AMA collects nothing without one. Confirm with az monitor data-collection rule association list --resource <machine-id> (an empty result is the smoking gun). Associate a DCR to fix it.
  5. The service principal’s secret has expired — the tell is that every machine fails identically at once. Check az ad app credential list --id <appId> for a past end date; rotate the secret, update the onboarding store, and re-run.

Glossary

Next steps

You can now localise any Arc agent failure to a layer — service, egress, identity, or extension — and fix it without minting a duplicate. Build outward:

AzureAzure ArcHybridConnected Machine AgentTroubleshootingazcmagentExtensionsAzure Monitor Agent
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading