Azure VM Auto-Discovery for Management Groups
This guide shows you how to configure Teleport to automatically enroll Azure virtual machines across multiple subscriptions using management groups.
If you only want to discover VMs in specific subscriptions, read Manual Azure VM Auto-Discovery.
How it works
The Teleport Discovery Service authenticates to Azure as a service principal with permissions assigned at the management group scope. This allows it to list all subscriptions under that management group and discover virtual machines in each one.
For each discovered VM, the Discovery Service executes a script using the Azure Run Command feature that installs Teleport, starts it and joins the cluster.
You can also enroll VMs across your entire Azure environment, including any additional subscriptions and management groups added later, using the Tenant root group. The Tenant root management group ID is the same as your Azure tenant ID.
Discovery for Azure using management groups is currently only supported for virtual machines and virtual machine scale sets.
Prerequisites
-
A running Teleport cluster. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.
-
The
tctlandtshclients.Installing
tctlandtshclients-
Determine the version of your Teleport cluster. The
tctlandtshclients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at/v1/webapi/findand use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:- Mac/Linux
- Windows - Powershell
TELEPORT_DOMAIN=teleport.example.com:443TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"$TELEPORT_DOMAIN = "teleport.example.com:443"$TELEPORT_VERSION = (Invoke-RestMethod -Uri "https://${TELEPORT_DOMAIN}/v1/webapi/find").server_version -
Follow the instructions for your platform to install
tctlandtshclients:- Mac
- Windows - Powershell
- Linux
Download the signed macOS .pkg installer for Teleport, which includes the
tctlandtshclients:curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkgIn Finder double-click the
pkgfile to begin installation.dangerUsing Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.
curl.exe -O https://cdn.teleport.dev/teleport-v$TELEPORT_VERSION-windows-amd64-bin.zipUnzip the archive and move the `tctl` and `tsh` clients to your %PATH%
NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
All of the Teleport binaries in Linux installations include the
tctlandtshclients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our installation page.curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gztar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gzcd teleportsudo ./installTeleport binaries have been copied to /usr/local/bin
-
- Azure management group or tenant containing subscriptions for discovery.
- Permissions to create managed identities, custom role definitions, and role assignments at the management group scope.
- Azure virtual machines to join the Teleport cluster, running Ubuntu/Debian/RHEL if making use of the default Teleport install script. (For other Linux distributions, you can install Teleport manually.)
- Check that you can connect to your Teleport cluster and verify that you can run
tctlandtshcommands using your current credentials.-
Assign teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and [email protected] to your Teleport username.
-
Authenticate to your Teleport cluster. This depends on whether your shell is interactive or not.
In an interactive shell: Run the following command. By default, this triggers a multi-factor authentication prompt:
tsh login --proxy=teleport.example.com --user=[email protected]tctl statusCluster teleport.example.com
Version 19.0.0-dev
CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
On non-interactive environments: If you are running
tshandtctlas an AI agent, in a CI/CD environment, or similar, make sure theTELEPORT_IDENTITY_FILEenvironment variable is assigned to a valid file path with credentials for your cluster.tshandtctlread the file path from the environment variable and do not require a separate authentication step. If there is no identity file available, we recommend that you set up Machine ID to provision one automatically.When executing
tctlcommands with an identity file, you must pass the--auth-serverflag to provide the Teleport Auth Service address, which is not included in the identity file. If you provide the Proxy Service address,tctlconnects to the Proxy Service, which forwards traffic to and from the Teleport Auth Service. Update 443 to3025if you are contacting the Auth Service directly withtctl:tctl status --auth-server=teleport.example.com:443For
tshcommands that read an identity file, you must pass the--proxyflag, which pointstshto the address of the Teleport Proxy Service:tsh status --proxy=teleport.example.comEnsure client commands can access your identity file. Replace path/to/identity/file with the path to your identity file:
export TELEPORT_IDENTITY_FILE="${TELEPORT_IDENTITY_FILE:-path/to/identity/file}"Add the
--auth-serveror--proxyflags to all subsequenttctlandtshcommands.
tctl statuscommand, you can use your current credentials to run subsequenttctlcommands from your workstation. If you host your own Teleport cluster, you can also runtctlcommands on the computer that hosts the Teleport Auth Service for full permissions. -
Step 1/5. Create an Azure join token
When discovering Azure virtual machines, Teleport uses Azure join tokens for authenticating joining SSH Service instances. Using an allow rule scoped to the tenant allows VMs from any subscription in the tenant to join the cluster.
Create a file called token.yaml:
# token.yaml
kind: token
version: v2
metadata:
name: azure-discovery-token
expires: "3000-01-01T00:00:00Z"
spec:
roles: [Node]
join_method: azure
azure:
allow:
# specify the Azure tenant which Nodes may join from.
# this allows joining from any subscription in the tenant.
- tenant: "tenant-id"
Assign tenant-id to your Azure tenant ID.
Add the token to the Teleport cluster with:
tctl create -f token.yaml
Step 2/5. Configure IAM permissions for Teleport
The Teleport Discovery Service needs Azure IAM permissions to discover and register Azure virtual machines.
Configure an Azure service principal
There are a couple of ways for the Teleport Discovery Service to access Azure resources:
- The Discovery Service can run on an Azure VM with attached managed identity. This is the recommended way of deploying the Discovery Service in production since it eliminates the need to manage Azure credentials.
- The Discovery Service can be registered as a Microsoft Entra ID application and configured with its credentials. This is only recommended for development and testing purposes since it requires Azure credentials to be present in the Discovery Service's environment.
- Using managed identity
- Using app registrations
Go to the Managed Identities page in your Azure portal and click Create to create a new user-assigned managed identity:
Pick a name and resource group for the new identity and create it:
Take note of the created identity's Client ID:
Next, navigate to the Azure VM that will run your Discovery Service instance and add the identity you've just created to it:
Attach this identity to all Azure VMs that will be running the Discovery Service.
Registering the Discovery Service as a Microsoft Entra ID application is suitable for test and development scenarios, or if your Discovery Service does not run on an Azure VM. For production scenarios prefer to use the managed identity approach.
Go to the App registrations page in Microsoft Entra ID and click on New registration:
Pick a name (e.g. DiscoveryService) and register a new application. Once the app has been created, take note of its Application (client) ID and click on Add a certificate or secret:
Create a new client secret that the Discovery Service agent will use to authenticate with the Azure API:
The Teleport Discovery Service uses Azure SDK's default credential provider chain to look for credentials. Refer to Azure SDK Authorization to pick a method suitable for your use-case. For example, to use environment-based authentication with a client secret, the Discovery Service should have the following environment variables set:
export AZURE_TENANT_ID=
export AZURE_CLIENT_ID=
export AZURE_CLIENT_SECRET=
Create a custom role
Teleport requires the following permissions to discover and enroll Azure VMs across a management group:
Microsoft.Compute/virtualMachines/readMicrosoft.Compute/virtualMachines/runCommands/writeMicrosoft.Compute/virtualMachines/runCommands/readMicrosoft.Compute/virtualMachineScaleSets/readMicrosoft.Compute/virtualMachineScaleSets/virtualMachines/readMicrosoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/readMicrosoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/writeMicrosoft.Resources/subscriptions/read
The Microsoft.Resources/subscriptions/read permission is required so the
Discovery Service can list subscriptions under the management group when using a
wildcard subscription matcher.
Here is a sample role definition allowing Teleport to read and run commands on Azure virtual machines at the management group scope:
{
"properties": {
"roleName": "TeleportDiscovery",
"description": "Allows Teleport to discover Azure virtual machines",
"assignableScopes": [
"/providers/Microsoft.Management/managementGroups/<management-group-id>"
],
"permissions": [
{
"actions": [
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/runCommands/write",
"Microsoft.Compute/virtualMachines/runCommands/read",
"Microsoft.Compute/virtualMachineScaleSets/read",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/write",
"Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/read",
"Microsoft.Resources/subscriptions/read"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
]
}
}
Replace <management-group-id> with your management group ID. The
assignableScopes field determines where the role can be assigned — set it to
the management group that contains the subscriptions you want to discover.
Azure allows only one management group in
assignableScopes. To
discover VMs across multiple management groups, set assignableScopes to a
management group at the top of your resource hierarchy and create a role
assignment for each management group you wish to discover.
To discover VMs across all subscriptions in the tenant, use the tenant ID as the management group ID, which targets the Tenant root group.
Using the tenant ID as the management group ID targets the Tenant root group, which requires elevated access.
If you have recently elevated privileges in the Azure CLI or Azure portal, you may need to refresh your Azure CLI credentials before proceeding:
az logout && az login
Navigate to the Management Groups page and select your management group. Click on Access control (IAM) and select Add > Add custom role, then paste the JSON role definition above.
Using the role definition above grants Teleport access to enroll VMs and VMs from Virtual Machine Scale Sets (VMSSs).
VMSSs have two orchestration modes: Uniform and, the recommended, Flexible.
If you are not using or don't want to enroll VMSSs with Uniform orchestration mode, you can further limit the permissions granted to Teleport by removing the Microsoft.Compute/virtualMachineScaleSets/* permissions.
Navigate to the Azure portal and look for the Orchestration mode column to check the orchestration mode of your VMSSs and make sure to adjust the role permissions accordingly.
Create a role assignment for the Teleport Discovery Service principal
To grant Teleport permissions, the custom role you created must be assigned to the Teleport service principal at the management group level.
Navigate to the Management Groups page, select your management group, and click Access control (IAM). Select Add > Add role assignment. Choose the custom role you created as the role and the Teleport service principal as a member.
The Discovery Service will discover VMs in all subscriptions under the assigned management group scope.
Step 3/5. Set up an identity for discovered nodes
Every Azure VM to be discovered must have an identity assigned to it: either system assigned or user assigned managed identity.
- Azure Portal
- Azure CLI
To set up a Managed Identity:
- Navigate to Virtual machines view if you're hosting Teleport on an Azure VM, or navigate to Virtual machine scale sets view if you're hosting Teleport on an Azure VMSS.
- Select the VM or VMSS hosting your Teleport Service.
- In the right-side panel, click the Security/Identity tab.
- Under the Identity section, select the System assigned tab.
- Toggle the Status switch to On.
- Click Save.
If you're using VMSS and it is configured with manual upgrade mode, you must update the VM instances for the identity changes to take effect:
- Click the Instances tab in the right panel.
- Select the VM instances to update.
- Click Restart.
To attach a system-assigned identity to a regular VM, run:
az vm identity assign --resource-group <resource-group> --name <vm-name>
To attach a system-assigned identity to an Azure VMSS, run:
az vmss identity assign --resource-group <resource-group> --name <vmss-name>
If you're using VMSS and it is configured with manual upgrade mode, you must update the VM instances for the identity changes to take effect. Run the following command to propagate the identity change:
az vmss update-instances --resource-group <resource-group> --name <vmss-name> --instance-ids *
If the VMs to be discovered have no system-managed identity and more than one user-managed identity assigned to them, copy the client ID of one of your user-managed identities for Step 5.
Step 4/5. Install the Teleport Discovery Service
If you plan on running the Discovery Service on a host that is already running another Teleport service (Auth or Proxy, for example), you can skip this step.
Install Teleport on the virtual machine that will run the Discovery Service:
To install Teleport binaries on your Linux server, the recommended installation method is the cluster install script. This script is served by your Teleport cluster's Proxy Service and automatically selects the correct version, edition, and installation mode to match your cluster.
-
Remove any existing Teleport binaries on your system:
sudo rm -f /usr/local/bin/{tsh,teleport,tctl,tbot,fdpass-teleport,teleport-update} -
Assign teleport.example.com:443 to your Teleport cluster hostname and port, but not the scheme (https://).
-
Run your cluster's install script:
curl "https://teleport.example.com:443/scripts/install.sh" | sudo bash
Step 5/5. Configure Teleport to discover Azure instances
If you are running the Discovery Service on its own host, the service requires a valid join token to connect to the cluster. Generate one by running the following command:
tctl tokens add --type=discovery
Save the generated token in /tmp/token on the virtual machine that will run
the Discovery Service.
Discovery Service exposes a configuration parameter - discovery_service.discovery_group -
that allows you to group discovered resources into different sets. This parameter
is used to prevent Discovery Agents watching different sets of cloud resources
from colliding against each other and deleting resources created by another services.
When running multiple Discovery Services, you must ensure that each service is configured
with the same discovery_group value if they are watching the same cloud resources
or a different value if they are watching different cloud resources.
It is possible to run a mix of configurations in the same Teleport cluster meaning that some Discovery Services can be configured to watch the same cloud resources while others watch different resources. As an example, a 4-agent high availability configuration analyzing data from two different cloud accounts would run with the following configuration.
- 2 Discovery Services configured with
discovery_group: "prod"polling data from Production account. - 2 Discovery Services configured with
discovery_group: "staging"polling data from Staging account.
Assign teleport.example.com:443 to the host and port of the Teleport Proxy Service in your cluster, and azure-prod to a name that identifies a group of resources that you will enroll:
# teleport.yaml
version: v3
teleport:
join_params:
token_name: "/tmp/token"
method: token
proxy_server: "teleport.example.com:443"
auth_service:
enabled: false
proxy_service:
enabled: false
ssh_service:
enabled: false
discovery_service:
enabled: true
discovery_group: azure-prod
Create a matcher for the resources you want to enroll.
Dynamic configuration uses Discovery Configs which can be managed using Terraform.
See the Terraform discovery_config reference for more information.
Static configuration while simpler at first, has less flexibility because enrollment changes require edits to teleport.yaml and the restart of the Discovery Service.
- Dynamic configuration (recommended)
- Static configuration
Create a Discovery Config resource, that has the same discovery group you configured earlier, to enable Azure VM discovery.
Create a file named discovery-azure-prod.yaml with the following content:
kind: discovery_config
version: v1
metadata:
name: example-discovery-config
spec:
discovery_group: azure-prod
azure:
- types: ["vm"]
# Only exact matches or wildcard (*) are supported.
subscriptions: ["*"]
regions: ["<region>"]
tags:
"env": "prod" # Match virtual machines where tag:env=prod
install:
azure:
# Optional: If the VMs to discover have more than one managed
# identity assigned to them, set the client ID here to the client
# ID of the identity created in step 3.
client_id: "<client-id>"
Adjust the keys under spec.azure to match your Azure environment,
specifically the regions and tags you want to associate with the Discovery Service.
Create the Discovery Config by running the following command:
tctl create -f discovery-azure-prod.yaml
Matching instances will be added to the Teleport cluster automatically.
You can update the Discovery Config at any time, and the service will automatically re-apply the changes.
In order to enable Azure VM discovery the discovery_service.azure section
of teleport.yaml must include at least one entry:
# teleport.yaml
# ...
discovery_service:
enabled: true
discovery_group: azure-prod
azure:
- types: ["vm"]
# Only exact matches or wildcard (*) are supported.
subscriptions: ["*"]
regions: ["<region>"]
tags:
"env": "prod" # Match virtual machines where tag:env=prod
install:
azure:
# Optional: If the VMs to discover have more than one managed
# identity assigned to them, set the client ID here to the client
# ID of the identity created in step 3.
client_id: "<client-id>"
Adjust the keys under discovery_service.azure to match your Azure environment,
specifically the regions and tags you want to associate with the Discovery Service.
To configure Terraform for VM discovery across subscriptions in a management group, see Discover VMs in multiple subscriptions using management groups in the Terraform Azure VM Auto-Discovery guide.
Start the Discovery Service. The instructions depend on how you installed the Discovery Service and whether your system supports systemd:
- Package Manager
- TAR Archive
- No systemd
Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Discovery Service, enable and start Teleport:
sudo systemctl enable teleportsudo systemctl start teleport
You can check the status of the Discovery Service with systemctl status teleport
and view its logs with journalctl -fu teleport.
Configure the Discovery Service to start automatically when the host boots up by creating a systemd service for it. On the host where you will run the Discovery Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:
sudo teleport install systemd -o /etc/systemd/system/teleport.servicesudo systemctl enable teleportsudo systemctl start teleport
You can check the status of the Discovery Service with systemctl status teleport
and view its logs with journalctl -fu teleport.
On the host where you will run the Discovery Service, start Teleport:
sudo teleport start --config=/etc/teleport.yaml
Teleport runs in the foreground and outputs logs for the services it is running.
Once you have started the Discovery Service, Azure virtual machines matching the tags you specified earlier will begin to be added to the Teleport cluster automatically across all subscriptions under the management group.
Auto-discovery labels
Teleport applies a set of default labels to resources on AWS, Azure, and Google Cloud that join a cluster via auto-discovery. See the auto-discovery labels reference
Advanced configuration
This section covers configuration options for discovering and enrolling servers.
Install multiple Teleport agents on the same instance
When using blue-green deployments or other multiple clusters setups, you might want to access your instances from different clusters.
Teleport supports installing and running multiple agents on the same instance, using a suffixed installation which allows you to isolate each installation.
- Dynamic configuration (recommended)
- Static configuration
To configure the Discovery Service to use a suffixed installation, edit the Discovery Config and set the spec.azure.install.suffix key:
kind: discovery_config
# ...
spec:
azure:
- install:
suffix: "blue-cluster"
To configure the Discovery Service to use a suffixed installation, specify the install.suffix key in your Discovery Service configuration:
# teleport.yaml
version: v3
# ...
discovery_service:
enabled: true
azure:
- install:
suffix: "blue-cluster"
Requires agent managed updates to be enabled.
Define the group for Managed Updates
If you are using Teleport Agent managed updates, you can configure the update group so that you can control which instances get updated together.
- Dynamic configuration (recommended)
- Static configuration
To set the update group, edit the Discovery Config and set the spec.azure.install.update_group key:
kind: discovery_config
# ...
spec:
azure:
- install:
update_group: "update-group-1"
To set the update group, specify the install.update_group key in your Discovery Service configuration:
# teleport.yaml
version: v3
# ...
discovery_service:
enabled: true
azure:
- install:
update_group: "update-group-1"
Configure HTTP Proxy during installation
For instances which require a proxy to access the installation files, you can configure HTTP Proxy settings in the Discovery Service.
- Dynamic configuration (recommended)
- Static configuration
To set the HTTP proxy settings, edit the Discovery Config and set the spec.azure.install.http_proxy_settings key:
kind: discovery_config
# ...
spec:
azure:
- install:
http_proxy_settings:
https_proxy: http://172.31.5.130:3128
http_proxy: http://172.31.5.130:3128
no_proxy: my-local-domain
You must set the install.http_proxy_settings key in your configuration:
# teleport.yaml
version: v3
# ...
discovery_service:
enabled: true
azure:
- install:
http_proxy_settings:
https_proxy: http://172.31.5.130:3128
http_proxy: http://172.31.5.130:3128
no_proxy: my-local-domain
Use a custom installation script
(!docs/pages/includes/server-access/custom-installer-editing.mdx!)
Multiple installer resources can exist and be specified in the
azure.install.script_name section:
- Dynamic configuration (recommended)
- Static configuration
Edit the Discovery Config to specify a custom installer script:
kind: discovery_config
# ...
spec:
azure:
- types: ["vm"]
tags:
- "env": "prod"
install: # optional section when default-installer is used.
script_name: "default-installer"
- types: ["vm"]
tags:
- "env": "devel"
install:
script_name: "devel-installer"
Edit the teleport.yaml configuration to specify a custom installer script:
discovery_service:
# ...
azure:
- types: ["vm"]
tags:
- "env": "prod"
install: # optional section when default-installer is used.
script_name: "default-installer"
- types: ["vm"]
tags:
- "env": "devel"
install:
script_name: "devel-installer"
The installer resource has the following templating options:
{{ .MajorVersion }}: the major version of Teleport to use when installing from the repository.{{ .PublicProxyAddr }}: the public address of the Teleport Proxy Service to connect to.{{ .RepoChannel }}: Optional package repository (apt/yum) channel name. Has format<channel>/<version>e.g. stable/v19. See installation for more details.{{ .AutomaticUpgrades }}: indicates whether Automatic Updates are enabled or disabled. Its value is eithertrueorfalse. See Automatic Agent Updates for more information.{{ .TeleportPackage }}: the Teleport package to use. Its value is eitherteleport-entorteleportdepending on whether the cluster is enterprise or not.
These can be used as follows:
kind: installer
metadata:
name: default-installer
spec:
script: |
echo {{ .PublicProxyAddr }}
echo Teleport-{{ .MajorVersion }}
echo Repository Channel: {{ .RepoChannel }}
version: v1
Which, when retrieved for installation, will evaluate to a script with the following contents:
echo teleport.example.com
echo Teleport-19.0.0-dev
echo Repository Channel: stable/v19.0.0-dev
The default installer will take the following actions:
- Add an official Teleport repository to supported Linux distributions.
- Install Teleport via
aptoryum. - Generate the Teleport config file and write it to
/etc/teleport.yaml. - Enable and start the Teleport service.
If client_id is set in the Discovery Service config, custom installers will
also have the {{ .AzureClientID }} templating option.
Troubleshooting
No credential providers error
If you see the error DefaultAzureCredential: failed to acquire a token. in Discovery Service logs then Teleport
is not detecting the required credentials to connect to the Azure SDK. Check whether
the credentials have been applied in the machine running the Teleport Discovery Service and restart
the Teleport Discovery Service.
Refer to Azure SDK Authorization
for more information.
Inspect Azure discovery status
Run tctl discovery status to check the state of dynamic Discovery Service
configurations, when each Discovery Service instance last reported, and the latest
Azure enrollment totals:
tctl discovery status --cloud=azure
The following example shows a healthy configuration that discovered and enrolled two resources:
Discovery config example-discovery:
Discovery group: production
Status: healthy
Last run: 1 minute ago
Service (00000000-0000-0000-0000-000000000000):
Poll interval: 5 minutes
Last update: 1 minute ago
example-integration:
Azure VM:
Previous sync: 1 minute ago (took 12s)
Result: 2 found, 2 enrolled, 0 failed
A persistent error or not reporting yet status, a message that no Discovery
Service instances are running, or a nonzero failed count indicates a discovery
or enrollment problem.
The command reports dynamic discovery_config resources. It does not include
static discovery matchers configured in teleport.yaml.
See tctl discovery status
for the full flag reference.
Inspect instance enrollment status
The tctl discovery nodes command lists Teleport's recent attempts to enroll
Azure VMs and reports whether each succeeded. It reads azure.run audit
events emitted by the Discovery Service.
tctl discovery nodes --cloud=azuretctl discovery nodes --cloud=azure --failures-onlytctl discovery nodes --cloud=azure --last=24htctl discovery nodes --cloud=azure --format=json
Sample output:
Cloud Account Region Instance Time Status Details----- ---------------------------------- ------- ------------- -------------------- ---------------------- ------------------------------------------------Azure abcdef01-2345-6789-abcd-ef01234... EastUS example-vm-0 2026-04-29T15:25:48Z OnlineAzure abcdef01-2345-6789-abcd-ef01234... EastUS example-vm-1 2026-04-29T15:06:08Z Failed (exit code=103) Enrollment failed. Script output: "insufficien...Azure abcdef01-2345-6789-abcd-ef01234... EastUS example-vm-2 2026-04-29T15:05:56Z Failed (API error) VM agent not available. API error: "PUT https...Azure abcdef01-2345-6789-abcd-ef01234... EastUS example-vm-3 2026-04-29T15:05:54Z Failed (exit code=104) Enrollment failed. Script output: "proxy is u...
Each row's Status column tells you what stage the instance reached:
Online: the VM joined the cluster.Installed (offline): the install script succeeded but the agent isn't currently connected. Either the agent installed but never joined the cluster (bad join token, misconfiguration, or network), or it joined and later went offline.Failed (exit code=N): the install script ran and exited non-zero. The Details column shows the script output.Failed (API error): the install command never executed because the Azure run command API rejected it, typically a missingrunCommands/writepermission or a VM without the agent installed.
Use --last to widen the audit-event lookback window past the default one
hour (e.g. --last=24h) when investigating older failures or retries.
Use --format=json for machine-readable output that includes the full script
output, the originating user task ID, and Azure-specific instance metadata.
See tctl discovery nodes
for the full flag reference.
Teleport reports no error but VM does not join
Check your Discovery Service config and make sure that the VM you want to discover matches. In debug mode, Teleport will log the Subscription IDs and names of VMs it discovers.
The Azure run command API does not report the output of commands,
so Teleport has no way of knowing if a command succeeded or failed. Run command
logs can be found on the targeted VM at
/var/log/azure/run-command-handler/handler.log.
Next steps
- Read Joining Nodes via Azure Managed Identity for more information on Azure tokens.
- Full documentation on Azure discovery configuration can be found through the config file reference documentation.