By the end of this you can install and govern an extension, stand up monitoring with the Azure Monitor Agent and a data collection rule, run a PowerShell script on a machine from Azure with Run Command, open a session over the agent with no inbound port, and set the local blocklist that lets a sensitive server refuse all of it. This is the operations surface made concrete, the part where Arc stops being an onboarding story and becomes a way of working. The portal walk comes first, then the same thing as a script, and two of these capabilities are in preview at the time of writing, which the steps call out where it matters.
Before Step 1: Arc-connected machines; the Azure Connected Machine Resource Administrator role for extensions and Run Command; a Log Analytics workspace for the monitoring step; the Azure CLI with its SSH extension, and the Microsoft.HybridConnectivity resource provider registered, for the remote-access step. The agent should be current, because several of these capabilities gained fixes through the 2026 releases.
Feature status, checked July 2026
Three of the capabilities below are preview features and one is generally available with restrictions, so this sheet dates its claims rather than saying “at the time of writing” and leaving you to guess when that was. Re-check each line before you build a runbook on it.
| Capability | Status, July 2026 | What that means for this sheet |
|---|---|---|
| Run Command for Arc-enabled servers (Step 3) | Public preview | Command line and REST only, no portal path. Treat the interface as unstable even though the capability works |
| Windows Admin Center in the Azure portal for Arc (end-to-end test) | Public preview | Works with no inbound port, but preview terms apply, and enabling it replaces any Windows Admin Center already installed on the machine |
| Connected Machine agent automatic upgrade | Public preview | Agent 1.57 and later, Azure public cloud only, set with --enable-automatic-upgrade at connect or by policy afterward. This is not the same thing as extension automatic upgrade in Step 1, which is generally available |
| Windows Server 2025 Entra sign-in for Arc (Step 4c) | Generally available | Generally available and still restricted: no Conditional Access support, and enabling it Entra joins the server, which excludes Active Directory domain join |
| Default guest metrics with no ingestion charge (Step 2) | Preview | Assume the classic agent and rule path is billed until the preview path is generally available |
Step 1: Install an extension, and expect version drift
Extensions are how Arc grows past management into capability, and installing one is the same shape every time. In the portal, open the machine’s Extensions node and add the extension you need, for example the Azure Monitor Agent. The publisher and type must match the extension exactly, which is the one detail people get wrong.
| Setting | Value | Why |
|---|---|---|
| Publisher and type | Must match the extension, e.g. Microsoft.Azure.Monitor / AzureMonitorWindowsAgent | A mismatched publisher or type simply fails to install; these are exact product nouns, not descriptions |
| Automatic upgrade | On by default | The right default, and the reason your fleet will run a spread of versions rather than one |
| Rollout expectation | Up to eight weeks for a normal version to reach every machine | Version heterogeneity is the normal state; design monitoring to tolerate it |
The same as a script, installing the Azure Monitor Agent on one machine:
az connectedmachine extension create \
--resource-group "rg-arc-servers" \
--machine-name "SVR-APP-01" \
--extension-name "AzureMonitorWindowsAgent" \
--publisher "Microsoft.Azure.Monitor" \
--type "AzureMonitorWindowsAgent" \
--location "eastus"
Expected result: the extension provisions and reports succeeded on the machine’s Extensions node. Failure mode: if your operational model assumes every server runs the same extension build on the same day, it will raise false alarms, because staged rollout guarantees a spread. Plan for heterogeneity rather than chasing it.
Step 2: Turn the agent into monitoring with a data collection rule
Installing the Azure Monitor Agent collects nothing on its own. The agent is the pipe; a data collection rule is what decides what flows through it and where it lands, and until you create one and associate it with the machine, no data moves. In the portal, create a data collection rule that names its data sources, the performance counters and Windows event logs you actually want, and its destination, a Log Analytics workspace, then add the Arc machine as a resource so the association is created.
| Setting | Value | Why |
|---|---|---|
| Data sources | Only the counters and logs you will actually use | Every signal is collected inside the guest and billed as ingestion; a firehose rule is a line item |
| Destination | A Log Analytics workspace | The rule routes the data; the workspace is where it is queried and retained |
| Association | The Arc machine added as a resource on the rule | The association is what actually binds the rule to the machine; without it the agent sits idle |
Two cost and direction notes matter here. An Arc server has no free host-level metrics the way an Azure virtual machine does, because there is no hypervisor Azure owns to read it from the outside, so everything you want is collected in the guest and billed as ingestion. Scope the rule deliberately for that reason. A preview metrics pipeline is starting to offer some default guest metrics at no charge, but treat the classic agent-and-rule path as billed until that is generally available. And do not build on the dependency map or service map that older monitoring guidance leans on, because onboarding new machines to them has already closed and they are being retired; build on the current agent-and-rule model instead.
Step 3: Run a PowerShell script on a machine, from Azure
This is the capability people are really asking for when they ask how to do something on the box. Run Command executes a script on the server through the agent, with nothing to install, because it is built into the Connected Machine agent itself. Two things to know before you use it: at the time of writing it is a preview feature, and it is driven from the command line and REST, not the portal. You give it a script inline or by URI, and it runs on the machine and returns the output.
# Run an inline PowerShell script on one machine
az connectedmachine run-command create \
--resource-group "rg-arc-servers" \
--machine-name "SVR-APP-01" \
--name "restart-time-service" \
--location "eastus" \
--script "Restart-Service W32Time; Get-Service W32Time | Format-List Status"
# Or run a script hosted at a URI, and run it as a named account
az connectedmachine run-command create \
--resource-group "rg-arc-servers" \
--machine-name "SVR-APP-01" \
--name "apply-fix" \
--location "eastus" \
--script-uri "https://example.blob.core.windows.net/scripts/fix.ps1" \
--run-as-user "svc-maint"
Expected result: the command executes and its output is returned with the run-command resource. Failure mode to avoid: reach for the inline script with --script or a hosted one with --script-uri, and do not look for a --source flag, because that belongs to the PowerShell cmdlet, not this CLI, and guessing it wastes a cycle. By default the script runs on the machine in a high-privilege local context, so treat every Run Command as code execution on the server; use --run-as-user when you need it to run as a specific account instead.
The permission to run one command on a machine is, in practice, permission to run any code on it. That is the power Run Command gives, and the reason Step 5 exists.
Be clear-eyed about what this is. The single action that authorizes Run Command, the write permission carried by the Azure Connected Machine Resource Administrator role, is effectively remote arbitrary code execution as a high-privilege account on the server. The Custom Script Extension is the older, extension-based way to do the same thing. Both are enormously useful and both are exactly why the machine keeps a local veto, which is the final step.
Step 4: Open a session with no inbound port, three ways
SSH through Arc tunnels a session to the server over the agent’s existing outbound connection, with no public IP and no inbound port opened, which is a genuinely better posture than the jump box it replaces. It rides the HybridConnectivity capability, and you enable it once per machine before the first connection: register the Microsoft.HybridConnectivity provider, create the default connectivity endpoint on the machine, and add an SSH service configuration on that endpoint for port 22. Then you connect from your own workstation with the Azure CLI.
# Connect over the agent tunnel as a local account
az ssh arc \
--resource-group "rg-arc-servers" \
--name "SVR-APP-01" \
--local-user "svc-admin"
# Tunnel RDP over the same channel instead of an interactive shell
az ssh arc --resource-group "rg-arc-servers" --name "SVR-APP-01" --local-user "svc-admin" --rdp
Failure mode on the mechanics, before we get to identity: if the connection is refused, it is almost always because the default connectivity endpoint or its SSH service configuration was never created, not because the credential is wrong.
Arc supplies the transport. What governs the session is decided by the authentication method, and there are three separate cases here that the platform is often described as if they were one. Choose deliberately, because they do not carry the same controls or the same consequences.
| Case | What authenticates | What governs it |
|---|---|---|
| 4a. Local-account SSH or RDP tunnel, Windows or Linux | A local operating system account on the machine, reached with az ssh arc --local-user or the same command with --rdp | Azure role-based access control governs who may open the tunnel. The sign-in itself is a local credential, so Conditional Access does not apply to it and never will. This is the default path and the one most sheets leave unexamined |
| 4b. Linux server with Entra SSH | A Microsoft Entra identity, through the AADSSHLoginForLinux extension and a system-assigned managed identity, with the Virtual Machine Administrator Login or Virtual Machine User Login role | Azure role-based access control and Conditional Access both apply, including multifactor and device checks. One documented caveat: Conditional Access that requires device compliance or Entra hybrid join is enforced only when the Azure CLI runs on Windows or macOS, not on Linux and not in Azure Cloud Shell |
| 4c. Windows Server 2025 Entra sign-in | A Microsoft Entra identity over RDP, through the AADLoginForWindows extension and a system-assigned managed identity, with the same two Azure roles | Azure role-based access control applies. Conditional Access is not currently supported. Enabling this Entra joins the server, and see the warning below before you enable it anywhere |
Warning, and this is the one that bites hardest: enabling Entra sign-in on a Windows Server 2025 machine makes that machine Microsoft Entra joined, and an Entra-joined machine cannot also be joined to on-premises Active Directory or to Entra Domain Services. It is mutually exclusive with domain join, not additive to it. Reversing it means uninstalling the extension to disconnect the device from Entra. So this is not a sign-in preference you toggle on a domain-joined file server to try it out; it is an identity architecture decision for machines that have already left the domain or never joined it. Treat it as belonging to the same conversation as the fleet sorting in the capstone article, not to this step’s convenience.
| Setting | Value | Why |
|---|---|---|
| Entra sign-in on Windows Server 2025 | Enable only on machines that are not, and will not be, Active Directory domain joined | The extension Entra joins the machine, which excludes AD and Entra Domain Services join. Enabling it on a domain-joined server is a rollback exercise, not a test |
| Conditional Access expectation, case 4c | Assume none, and compensate elsewhere | Conditional Access is not supported for Windows Server Entra sign-in through Arc. Do not promise a security review that device compliance covers this path |
| Conditional Access expectation, case 4b | Real, with a client-platform caveat | Linux Entra SSH does carry Conditional Access. Device-compliance and hybrid-join conditions hold only with the Azure CLI on Windows or macOS, so document the client platform your operators actually use |
| Azure roles for 4b and 4c | Virtual Machine Administrator Login or Virtual Machine User Login | Owner and Contributor do not grant sign-in by design. The separation between who controls a machine and who can log into it is deliberate, and useful |
Expected result: case 4a opens a shell or an RDP session with a local credential and no inbound port. Case 4b signs a named Entra user in and satisfies your Conditional Access policy on the way. Case 4c signs a named Entra user in over RDP and satisfies no Conditional Access policy, because none applies. Failure mode to plan for on 4b and 4c: an operator with Owner on the subscription who still cannot sign in has not hit a bug, they are missing one of the two login roles.
Step 5: Set the local blocklist, the refusal the cloud cannot override
Everything in Steps 3 and 4 is cloud-granted power to reach inside a machine, and the compensating control is that the machine keeps a local veto the cloud cannot override. On a server where that reach is unacceptable, you set the agent’s own configuration, where no Azure role can reverse it. Block the Run Command and Custom Script handlers so no one can push code, refuse the inbound connections that SSH and Windows Admin Center use, or put the whole agent in monitor mode, which is a read-only lockdown that also blocks extension installs.
# Block code-execution handlers (block takes precedence over any allowlist)
azcmagent config set extensions.blocklist "Microsoft.Cplat.Core/RunCommandHandlerWindows,Microsoft.Compute/CustomScriptExtension"
# Refuse the inbound connections used by SSH and Windows Admin Center
azcmagent config set incomingconnections.enabled false
# Or lock the machine read-only, blocking configuration and extension changes
azcmagent config set config.mode monitor
# See what this agent version supports and what is currently set
azcmagent config info
azcmagent config list
Expected result: a blocked handler cannot be installed and an inbound session is refused, regardless of what role the caller holds in Azure. Failure mode: a veto set by hand on one machine drifts the moment someone rebuilds it, so enforce these through configuration management, because a blocklist that silently lapses is worse than none.
A worked example
Two servers, two deliberately opposite postures. A payment-processing server must be observable but never remotely mutated, so you install the Azure Monitor Agent and a tightly scoped data collection rule, three performance counters and the security event log, so you can watch it closely, and then you set extensions.blocklist to the Run Command and Custom Script handlers and incomingconnections.enabled false. The result is a machine that reports fully to the cloud and refuses every cloud-driven code path and interactive session, by its own configuration. A lab server gets the mirror image: Run Command left enabled so you can push a PowerShell fix in seconds, and SSH through Arc on for quick access. Same platform, same tools, two postures chosen on purpose rather than by default, which is exactly what an operations surface should let you do.
Naming convention
Leave extensions their canonical publisher and type names so they are recognizable across the fleet. Name data collection rules for what they gather and the ring they serve, for example dcr-servers-baseline and dcr-servers-security, so a glance at the rule list reads as a monitoring plan. Document the local accounts you use for SSH so access is auditable, and keep the blocklist and monitor-mode settings in your configuration baseline rather than on individual machines, so the posture survives a rebuild.
The end-to-end test
Prove both the capability and its refusal, because on this surface the refusal is half the point. On a test machine that permits it, run a harmless Run Command such as returning the hostname and confirm you receive the output in Azure. Then run the same command against a machine where you set the blocklist and confirm it is refused. A capability that works where you allowed it and is blocked where you forbade it is the proof that the operations surface and its local veto are both real. For a fuller browser console without opening a port, Windows Admin Center in the Azure portal gives you services, events, the registry, and an in-portal PowerShell tab, though it is still preview for Arc at the time of writing, so use it without building a runbook that assumes it is generally available.
Rolling it back
Everything in this sheet is reversible, which is worth knowing before you pilot it rather than after. Undo it in the order the dependencies run, outermost first, and remember that removing the Azure-side object does not always undo what it put inside the guest.
- Remove the extension you installed in Step 1:
az connectedmachine extension delete --machine-name "SVR-APP-01" --resource-group "rg-arc-servers" --extension-name "AzureMonitorWindowsAgent". Uninstalling an extension in Azure does not necessarily uninstall the software it delivered inside the guest, so confirm on the machine if that matters. - Disassociate the data collection rule from the machine, then delete the rule if nothing else uses it:
az monitor data-collection rule association delete --name "<association>" --resource "<machine resource id>", thenaz monitor data-collection rule delete --name "dcr-servers-baseline" --resource-group "rg-arc-servers". Deleting the rule with--delete-associations truedoes both at once, which is convenient and also a wider blast radius than you may intend. - Delete the Run Command resources you created, because they persist on the machine as objects after the script has finished:
az connectedmachine run-command delete --name "restart-time-service" --machine-name "SVR-APP-01" --resource-group "rg-arc-servers". - Disable the remote-access path. Remove the SSH service configuration and the connectivity endpoint on the machine if you no longer want tunneled sessions, and for cases 4b or 4c remove the Entra login extension, which is also how you disconnect a Windows Server 2025 machine from Entra join.
- Clear the local settings you made in Step 5, and mind the order, because it is not arbitrary. Return the agent to full mode first with
azcmagent config set config.mode full, since monitor mode refuses edits to the allow list and block list while it is active. Thenazcmagent config clear extensions.blocklistandazcmagent config set incomingconnections.enabled true. Runazcmagent config listafterward and actually read it, because a half-cleared veto is the kind of thing that looks fine until an extension install fails for no visible reason six weeks later. - Remove the same settings from your configuration baseline, or the baseline will re-apply the veto you just cleared and you will spend an afternoon blaming the agent.
Before you scale it
- Extension installed with matching publisher and type, and the monitoring model built to tolerate an eight-week version spread.
- Monitoring wired: the Azure Monitor Agent plus a deliberately scoped data collection rule associated to the machine, with ingestion understood as the cost and the retiring dependency map avoided.
- Run Command exercised from the command line with
--scriptor--script-uri, understood as remote code execution and marked preview. - SSH through Arc enabled per machine via the HybridConnectivity endpoint and SSH service configuration, and the authentication case chosen on purpose: local account (no Conditional Access), Linux Entra SSH (Conditional Access applies), or Windows Server 2025 Entra sign-in (no Conditional Access, and Entra join excludes domain join).
- Local blocklist, inbound-connection, or monitor-mode settings applied to sensitive servers and enforced through configuration management.
- End-to-end test passed: a Run Command that works where allowed and is refused where blocked.
With the management and operations surface now covered end to end, the series turns to the reason many organizations adopt Arc in the first place, which is not management at all but money: Extended Security Updates, pay-as-you-go licensing, and the waiver matrix that decides what any of this costs. The dates there are close and the rules are specific, and that is the next article.
Azure Arc
‹ Previous: [ARC 5] The Operations Surface: Extensions, Monitoring, and Remote Access
Next: [ARC 6] ESUs and Licensing: The Plane Pays for Itself ›




