Cloud & infrastructure

Onboard Servers to Azure Arc at Scale with a Service Principal

Connect hundreds of on-premises Windows and Linux servers to Azure Arc with a least-privilege service principal, a scripted azcmagent install and connect, and a repeatable verification step.

12 min read
On this page

To onboard many on-premises servers to Azure Arc, register the Arc resource providers, create a dedicated Microsoft Entra service principal with only the Azure Connected Machine Onboarding role on the target resource group, and run a script on each server that installs the Connected Machine agent, runs azcmagent check, and connects with azcmagent connect using the service principal's ID, secret and tenant ID. Microsoft recommends passing the secret through a --config file rather than the command line so it doesn't appear in console logs. Push the script with Group Policy, Configuration Manager, Ansible or PowerShell remoting, then confirm the servers show Connected in Azure.

Who this is for and what you will have at the end

This guide is for server and cloud teams that need to bring a large on-premises or multicloud estate under Azure management: inventory, Azure Policy, Azure Monitor Agent, Update Manager and Extended Security Updates all start with an Arc connection. It assumes local administrator or root access to the servers and Owner or User Access Administrator on the target subscription to assign roles.

At the end you will have:

  • A landing resource group, tags and a registered set of resource providers.
  • A least-privilege onboarding service principal with a known secret expiry.
  • Windows and Linux onboarding scripts that keep the secret out of command lines.
  • A wave-based rollout method, a Resource Graph query to track progress, and the error codes you are most likely to hit.

Plan before the first server

Microsoft's at-scale guidance recommends a pilot on representative, non-critical machines before production, with a minimum of 30 days to assess impact. Use the pilot to settle the decisions below.

  • Resource groups. Microsoft's plan starts with a dedicated resource group that contains only Arc-enabled servers, which keeps RBAC, policy and monitoring assignments simple.
  • Region. The region you choose stores the servers' metadata; it doesn't have to match the resource group's region.
  • Tags. Decide on tags such as datacenter, environment and owner up front, because azcmagent connect can apply them at onboarding.
  • Scale. There's no limit on Arc-enabled servers per resource group, subscription or tenant, but each server creates a Microsoft Entra object that counts against the directory quota.
  • SQL Server. Servers running SQL Server have their instances connected to Arc automatically. To opt out, add the tag ArcSQLServerExtensionDeployment with the value Disabled at connect time.

Operating system support

x86-64 is fully supported; Arm64 supports a subset of features, and 32-bit systems aren't supported. Windows Server 2016, 2019, 2022 and 2025 are supported, as are current releases of RHEL, Rocky Linux, AlmaLinux, Oracle Linux, SLES, Ubuntu and Debian. Several older releases, including Windows Server 2012 and 2012 R2, Ubuntu 20.04, RHEL 7 and SLES 15 SP3 to SP6, are marked as approaching the end of Arc support in November 2026; check the prerequisites page for the current list. Extended Security Updates for Windows Server 2012 and 2012 R2 end on October 13, 2026.

Avoid onboarding golden images, clones and servers restored as a second instance: two agents with the same identity behave unpredictably. Onboard after cloning, and don't use Arc for short-lived servers or VDI machines.

Prerequisites

  • Local rights. Members of the local Administrators group on Windows, root on Linux.
  • Linux packages. systemd, wget, openssl, and gnupg on Debian-based systems.
  • Windows logon right. The agent's NT SERVICE\himds virtual account needs Log on as a service. If Group Policy manages that user right, add NT SERVICE\himds to it.
  • Azure roles. Azure Connected Machine Onboarding (or Contributor) on the resource group to onboard; Azure Connected Machine Resource Administrator to manage machines afterwards. Creating the service principal requires that users can register applications, or the Application Administrator or Cloud Application Administrator role.
  • Outbound TCP 443 to the Arc endpoints. The core set for public Azure is below; allow the service tags AzureActiveDirectory, AzureTrafficManager, AzureResourceManager, AzureArcInfrastructure, Storage and AzureFrontDoor.Frontend if your firewall works with tags.
EndpointWhen required
download.microsoft.comWindows package download (installation and automatic updates)
packages.microsoft.comLinux package download (installation and automatic updates)
login.microsoftonline.com, *.login.microsoft.com, pas.windows.netAlways (Microsoft Entra ID)
management.azure.comWhen connecting or disconnecting a server
*.his.arc.azure.comAlways (metadata and hybrid identity)
*.guestconfiguration.azure.comAlways (extensions and machine configuration)
guestnotificationservice.azure.com, *.guestnotificationservice.azure.com, *.servicebus.windows.netAlways (notifications)

Use TLS 1.2 or 1.3. A Log Analytics gateway can't be used as the agent's proxy. Azure Arc gateway can reduce the number of endpoints you have to open, and private link scopes are available if traffic must stay private.

Step 1: Register the resource providers

Register the providers once per subscription that will hold Arc servers. Microsoft.Compute is also listed for Azure Update Manager and automatic extension upgrades.

Connect-AzAccount
Set-AzContext -SubscriptionId '<subscription-id>'
'Microsoft.HybridCompute','Microsoft.GuestConfiguration','Microsoft.HybridConnectivity','Microsoft.AzureArcData','Microsoft.Compute' |
  ForEach-Object { Register-AzResourceProvider -ProviderNamespace $_ }

If you skip this, onboarding fails with The subscription isn't registered to use namespace 'Microsoft.HybridCompute'.

Step 2: Create the onboarding service principal

Create one service principal per landing zone and scope it to the resource group rather than the whole subscription. In the portal, go to Azure Arc > Additional setup > Service principals > Add, choose resource group scope, set the client secret duration, and select the Azure Connected Machine Onboarding role. With the Azure CLI:

az ad sp create-for-rbac \
  --name "sp-arc-onboarding-weu" \
  --role "Azure Connected Machine Onboarding" \
  --scopes "/subscriptions/<subscription-id>/resourceGroups/rg-arc-servers-weu"

The output contains appId (used for --service-principal-id), password (the secret) and tenant. Store the secret in your vault, record its expiry date, and plan to remove the secret or the service principal when the rollout ends. The service principal is used only during onboarding, so deleting it later doesn't disconnect servers.

If you can, use a certificate instead of a secret. The agent accepts --service-principal-cert with a PFX or PEM file that contains the private key (password-protected files aren't supported), or --service-principal-cert-thumbprint for a certificate in the Windows certificate store.

Step 3: Build the onboarding package

You have two starting points.

Portal-generated script. In Azure Arc > Infrastructure > Machines, select Onboard/Create > Onboard existing machines. Choose subscription, resource group, region, operating system, connectivity (public endpoint, private endpoint, proxy URL or Arc gateway), then under Authentication select Authenticate machines automatically and pick your service principal. Add tags and download OnboardingScript.ps1 or OnboardingScript.sh. The Windows script only runs in 64-bit Windows PowerShell. Treat any script that contains the secret as a credential.

Your own wrapper. For large rollouts a small wrapper gives you logging, error handling and secret clean-up. Put the connection settings in a configuration file; each key matches an azcmagent connect option, and command-line values take precedence over the file.

{
  "service-principal-id": "<app-id>",
  "service-principal-secret": "<secret>",
  "tenant-id": "<tenant-id>",
  "subscription-id": "<subscription-id>",
  "resource-group": "rg-arc-servers-weu",
  "location": "westeurope",
  "tags": "Datacenter=AMS1,Environment=Production"
}

The Windows wrapper installs the agent from a staged MSI (download the latest AzureConnectedMachineAgent.msi from https://aka.ms/AzureConnectedMachineAgent), checks connectivity, connects, and deletes the configuration file whatever the outcome:

# Install-Arc.ps1 - run elevated in 64-bit Windows PowerShell on the target server
$ErrorActionPreference = 'Stop'
$stage  = 'C:\ArcOnboarding'
$msiLog = Join-Path $stage 'azcmagent-setup.log'
 
$install = Start-Process msiexec.exe -Wait -PassThru `
  -ArgumentList "/i `"$stage\AzureConnectedMachineAgent.msi`" /qn /l*v `"$msiLog`""
if ($install.ExitCode -ne 0) { throw "Agent install failed ($($install.ExitCode)). See $msiLog" }
 
$azcmagent = "$env:ProgramFiles\AzureConnectedMachineAgent\azcmagent.exe"
 
# Optional: agent-specific proxy (agent 1.13 or later)
# & $azcmagent config set proxy.url "http://proxy.contoso.com:8080"
 
& $azcmagent check --location "westeurope"
 
try {
    & $azcmagent connect --config "$stage\arc-config.json"
    if ($LASTEXITCODE -ne 0) { throw "azcmagent connect failed with exit code $LASTEXITCODE" }
}
finally {
    Remove-Item "$stage\arc-config.json" -Force -ErrorAction SilentlyContinue
}

The Linux equivalent, run as root:

#!/usr/bin/env bash
set -euo pipefail
 
wget https://aka.ms/azcmagent -O ~/Install_linux_azcmagent.sh
bash ~/Install_linux_azcmagent.sh            # add --proxy "proxy.contoso.com:8080" if needed
 
azcmagent check --location "westeurope"
trap 'rm -f /root/arc-config.json' EXIT
azcmagent connect --config /root/arc-config.json

azcmagent check tests every required endpoint and shows whether a proxy, private endpoint or Arc gateway was used. Run it before connect so network problems surface as a readable table rather than a failed onboarding.

Step 4: Roll out in waves

Pick the distribution method you already operate. Microsoft documents these at-scale options:

MethodPlatforms
Group Policy with the ArcEnabledServersGroupPolicy scriptsWindows, domain-joined
Configuration Manager (PowerShell script or custom task sequence)Windows
Ansible (Azure Arc onboarding role)Windows and Linux
PowerShell or a service principal script from your own toolingWindows and Linux
Azure Arc-enabled VMware vSphere guest managementVMware VMs with VMware Tools
Multicloud connectorAWS EC2 instances

Group Policy. Host the agent MSI and configuration on a share that domain computers can change and domain admins fully control, download the latest release of ArcEnabledServersGroupPolicy from GitHub, and run DeployGPO.ps1 on a domain controller:

.\DeployGPO.ps1 -DomainFQDN contoso.com -ReportServerFQDN Server.contoso.com -ArcRemoteShare AzureArcOnBoard `
  -ServicePrincipalSecret $ServicePrincipalSecret -ServicePrincipalClientId $ServicePrincipalClientId `
  -SubscriptionId $SubscriptionId -ResourceGroup $ResourceGroup -Location $Location -TenantId $TenantId

Link the generated [MSFT] Azure Arc Servers (datetime) GPO to the target OU. It creates a scheduled task that onboards the machines. After the wave is confirmed, disable the GPO so the task doesn't run again at every reboot or policy refresh.

PowerShell remoting. For workgroup servers or smaller waves, copy the files into each session and run the wrapper. Copying with -ToSession avoids the second-hop problem of reading a file share from inside a remote session.

$servers = Get-Content .\wave-01.txt
foreach ($server in $servers) {
    $session = New-PSSession -ComputerName $server
    try {
        Invoke-Command -Session $session -ScriptBlock { New-Item -ItemType Directory -Path 'C:\ArcOnboarding' -Force | Out-Null }
        Copy-Item -ToSession $session -Path .\AzureConnectedMachineAgent.msi, .\arc-config.json -Destination 'C:\ArcOnboarding\'
        Invoke-Command -Session $session -FilePath .\Install-Arc.ps1
    }
    finally {
        Remove-PSSession $session
    }
}

Keep waves small enough to troubleshoot the same day, and widen them once the failure rate is close to zero.

Verification

On a server, azcmagent show reports the agent status and the effective proxy configuration. In Azure, open Azure Arc > Machines and check Arc agent status. To track a whole wave, query Resource Graph:

Resources
| where type == 'microsoft.hybridcompute/machines'
| where resourceGroup =~ 'rg-arc-servers-weu'
| project name, status = tostring(properties.status), osName = tostring(properties.osName), domain = tostring(properties.domainName)
| summarize Machines = count() by status, osName

Run it in Resource Graph Explorer, with az graph query -q "<query>", or with Search-AzGraph -Query "<query>". Compare the count with your wave list to find servers that never connected.

After onboarding

  • Create a Resource Health alert for Azure Arc-enabled servers that fires when the status changes from Available to Unavailable. A server that stops sending heartbeats for more than 15 minutes may be offline, have its network connection blocked, or have a stopped agent.
  • Create an Azure Advisor alert for Upgrade to the latest version of the Azure Connected Machine agent, or enable automatic agent upgrade (preview).
  • Deploy monitoring next: Azure Monitor Agent with data collection rules works the same way on Arc-enabled servers as on Azure VMs.
  • Bring the servers into a patch schedule with Azure Update Manager.
  • Rotate or delete the onboarding secret when the last wave completes.

Troubleshooting

Add --verbose to any azcmagent command. Logs are written to %ProgramData%\AzureConnectedMachineAgent\Log\azcmagent.log on Windows and /var/opt/azcmagent/log/azcmagent.log on Linux; the Windows MSI writes to the path you pass with /l*v.

ErrorProbable causeFix
AZCM0018Command not run as administrator or rootRerun elevated
AZCM0026Network configuration error or required endpoint unreachableRun azcmagent check; for private link, pass --private-link-scope
AZCM0041Invalid credentialsCheck the app ID, secret and expiry, and that the service principal is in the same tenant as the target subscription
AZCM0042Arc resource creation failedCheck the role assignment on the resource group
AZCM0044A resource with the same name existsUse --resource-name or delete the stale Arc resource
AZCM0067Machine already connectedRun azcmagent disconnect first if you really want to reconnect
AZCM0141 (Linux), AZCM0147 (Windows)Installing on an Azure VMDon't onboard Azure VMs; on Linux, AZCM0147 instead means the requested agent version wasn't found

Messages you may see in the verbose log:

  • Failed to acquire authorization token from SPN: Invalid client secret is provided means the secret is wrong or expired.
  • Application with identifier '...' wasn't found in the directory '...' points to a wrong app ID or tenant ID.
  • A 403 for Microsoft.HybridCompute/machines/read means the service principal lacks Azure Connected Machine Onboarding at that scope.
  • Forbidden responses for login.windows.net or management.azure.com mean a proxy or firewall is blocking the endpoint; azcmagent check confirms which one.
  • When creating the service principal, ServiceManagementReference field is required for Create, but is missing in the request means your account needs the Application Administrator or Cloud Application Administrator role, or your tenant's app registration policy must be satisfied.

Checklist

  • Pilot completed on representative, non-critical servers.
  • Resource providers registered; landing resource group, region and tags decided.
  • Service principal scoped to the resource group with only Azure Connected Machine Onboarding; secret expiry recorded, or a certificate used.
  • Endpoints and service tags allowed; azcmagent check passes from each network segment.
  • Wrapper scripts connect with --config and delete the file afterwards.
  • Waves rolled out; Group Policy object disabled after each wave.
  • Resource Graph count matches the wave lists; Resource Health and Advisor alerts in place.
  • Onboarding secret rotated or removed after the final wave.

References

Questions people ask

What role does the Azure Arc onboarding service principal need?

Assign the built-in Azure Connected Machine Onboarding role, scoped to the resource group (or subscription) where the server resources will be created. The service principal is only used during onboarding; to read, modify or delete Arc-enabled servers afterwards you need Azure Connected Machine Resource Administrator.

How long is the onboarding service principal secret valid?

When you create the service principal with az ad sp create-for-rbac or New-AzADServicePrincipal as shown in Microsoft's guide, the secret is valid for one year. After that you must generate a new secret and update any scripts that use it. Certificate-based authentication is the more secure alternative.

Is there a limit on how many Arc-enabled servers a resource group can hold?

No. Microsoft states there's no limit on the number of Arc-enabled servers per resource group, subscription or tenant. Each server is associated with a Microsoft Entra object, though, and counts against your directory object quota.

Can I install the Connected Machine agent on an Azure VM?

No. Azure VMs already have equivalent capabilities, and the agent can't be installed on them: error AZCM0141 on Linux and AZCM0147 on Windows report this case. Microsoft only supports it for evaluation scenarios that simulate on-premises machines.

Azure ArcConnected Machine AgentEntra IDAzure PolicyWindows Server
  1. Azure Update Manager: Schedule Patching for Azure VMs and Arc Servers

    Replace Automation Update Management or WSUS-only patching with Azure Update Manager: periodic assessment, maintenance configurations, dynamic scopes and scheduled patching for Azure and Arc servers.

  2. A practical Azure landing zone for small and mid-size companies

    Set up Azure management groups, subscriptions, hub-and-spoke networking, Azure Policy, RBAC and budgets the right way from day one, scaled down from Microsoft's landing zone architecture.

  3. AWS IAM Identity Center SSO with Entra ID: SAML and SCIM provisioning

    Connect AWS IAM Identity Center to Microsoft Entra ID so users sign in to AWS accounts with their Entra credentials, and users and groups are provisioned automatically over SCIM.