PowerCLI script that joins a standalone ESXi host to Active Directory and grants a specified AD group the built-in Admin role, so administrators can sign in to the host with domain credentials instead of root.

For anyone who wants to sign in to an ESXi host with their own domain account instead of sharing the local root password, here is a small PowerCLI helper that joins the host to Active Directory and grants a named AD group the built-in Admin role on the host object.
What the script does
- Connects to a single ESXi host as root using PowerCLI.
- Joins the host to the specified Active Directory domain if it is not already a member.
- Resolves the AD group via
Get-VIAccountso we have a proper principal object. - Creates a vSphere permission granting that group the Admin role on the host, propagating to children.
- Disconnects cleanly. Re-running it is safe: each mutating step has an exists-check first.
PowerShell
#requires -Version 5.1
#requires -Modules VMware.VimAutomation.Core
<#
.SYNOPSIS
Joins an ESXi host to Active Directory and grants an AD group the Admin role.
.DESCRIPTION
Idempotent PowerCLI helper for standalone ESXi hosts. Connects as root,
performs an AD domain join if the host is not already a member, then
assigns the built-in Admin role on the host to a named AD group.
.PARAMETER ESXiHost
Fully qualified DNS name of the ESXi host (for example esx01.contoso.local).
.PARAMETER VICredential
PSCredential for a local ESXi account with full privileges (typically root).
.PARAMETER DomainCredential
PSCredential for an Active Directory account permitted to join computers
to the target domain.
.PARAMETER Domain
Active Directory DNS domain name, for example contoso.local.
.PARAMETER AdminGroup
AD group to grant Admin on the host, in DOMAIN\Group form, for example
CONTOSO\ESXi Admins.
.EXAMPLE
$root = Get-Credential root
$join = Get-Credential CONTOSO\svc-esxjoin
.\Add-ESXiAdGroupAdmin.ps1 `
-ESXiHost esx01.contoso.local `
-VICredential $root `
-DomainCredential $join `
-Domain contoso.local `
-AdminGroup 'CONTOSO\ESXi Admins'
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory)] [string] $ESXiHost,
[Parameter(Mandatory)] [pscredential] $VICredential,
[Parameter(Mandatory)] [pscredential] $DomainCredential,
[Parameter(Mandatory)] [string] $Domain,
[Parameter(Mandatory)] [string] $AdminGroup
)
$ErrorActionPreference = 'Stop'
# Confirm PowerCLI is loaded.
if (-not (Get-Module -ListAvailable VMware.VimAutomation.Core)) {
throw "VMware.VimAutomation.Core is not installed. Run: Install-Module VMware.PowerCLI -Scope CurrentUser"
}
Import-Module VMware.VimAutomation.Core
# Disable certificate warnings on standalone hosts that use self-signed certs.
# Remove this line if your host already presents a trusted certificate.
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false -Scope Session | Out-Null
Write-Host "Connecting to $ESXiHost as $($VICredential.UserName)..." -ForegroundColor Cyan
$server = Connect-VIServer -Server $ESXiHost -Credential $VICredential
try {
$vmHost = Get-VMHost -Server $server
$auth = Get-VMHostAuthentication -VMHost $vmHost
# 1. Join the host to AD if it is not already a member of the target domain.
if ($auth.Domain -and $auth.Domain -ieq $Domain) {
Write-Host "Host is already joined to $Domain. Skipping domain join." -ForegroundColor Yellow
}
else {
if ($PSCmdlet.ShouldProcess($ESXiHost, "Join domain $Domain")) {
Write-Host "Joining $ESXiHost to $Domain..." -ForegroundColor Cyan
$auth | Set-VMHostAuthentication `
-JoinDomain `
-Domain $Domain `
-Credential $DomainCredential `
-Confirm:$false | Out-Null
Write-Host "Domain join complete." -ForegroundColor Green
}
}
# 2. Resolve the AD group to a principal known to the host.
Write-Host "Resolving principal $AdminGroup..." -ForegroundColor Cyan
$principal = Get-VIAccount -Group -Domain $Domain -Id ($AdminGroup -replace '^.*\\','') -ErrorAction SilentlyContinue
if (-not $principal) {
throw "Could not resolve AD group $AdminGroup on $ESXiHost. Confirm the host can query the domain and that the group exists."
}
# 3. Grant the Admin role if not already granted.
$existing = Get-VIPermission -Entity $vmHost -Principal $AdminGroup -ErrorAction SilentlyContinue
if ($existing -and $existing.Role -eq 'Admin') {
Write-Host "$AdminGroup already has the Admin role on $ESXiHost." -ForegroundColor Yellow
}
else {
if ($PSCmdlet.ShouldProcess($ESXiHost, "Grant Admin role to $AdminGroup")) {
Write-Host "Granting Admin role to $AdminGroup..." -ForegroundColor Cyan
New-VIPermission `
-Entity $vmHost `
-Principal $AdminGroup `
-Role Admin `
-Propagate $true | Out-Null
Write-Host "Permission created." -ForegroundColor Green
}
}
}
finally {
Disconnect-VIServer -Server $server -Confirm:$false -ErrorAction SilentlyContinue
}
How to use it
# 1. Install PowerCLI on the workstation you are running this from.
Install-Module VMware.PowerCLI -Scope CurrentUser -Force
# 2. Prompt once for each credential rather than hard-coding them.
$root = Get-Credential -UserName root -Message 'ESXi root password'
$join = Get-Credential -UserName 'CONTOSO\svc-esxjoin' -Message 'AD account allowed to join computers'
# 3. Run the script.
.\Add-ESXiAdGroupAdmin.ps1 `
-ESXiHost esx01.contoso.local `
-VICredential $root `
-DomainCredential $join `
-Domain contoso.local `
-AdminGroup 'CONTOSO\ESXi Admins'
Add -WhatIf to preview both the domain join and the permission assignment without making changes.
Notes and modern alternatives
- PowerCLI module name change. Since PowerCLI 6.5.1 the cmdlets ship in a single
VMware.PowerCLImeta-module. The legacyAdd-PSSnapin VMware.VimAutomation.Coreline from the 2014 script is no longer required, and on PowerShell 7 / PowerCLI 13 the snap-in form will not load at all. - ESXi 7 and 8. The same cmdlets still work. The script has been tested against ESXi 7.0 U3 and 8.0 U2. The Broadcom takeover of VMware moved customer downloads from
my.vmware.comtosupport.broadcom.com; there is no longer a Fling-style alternate distribution. - Lockdown mode. If the host is in normal or strict lockdown mode,
New-VIPermissionwill still succeed for principals on the Exception Users list. Add your AD group there (Host > Configure > Security Profile > Lockdown Mode > Exception Users) so the AD group can log in when lockdown is active. - Prefer vCenter inventory permissions where you have vCenter. For ESXi hosts managed by vCenter, set the permission at the vCenter folder or cluster level instead of on each host. This script is aimed at standalone hosts or scenarios where direct host access is required (DR, troubleshooting, recovery).
Security notes
- Do not embed credentials. The 2014 version had
$HostPW,$DomainPW, and the AD group hard-coded in the script body. The modernised script takesPSCredentialobjects so secrets are never written to disk. - Least-privilege join account. The AD account passed as
-DomainCredentialonly needs the rights to join a computer to the target OU. Do not reuse Domain Admin for this. - Group, not user. Granting a group rather than individual users means starters and leavers are handled by your normal AD lifecycle, not by editing host permissions.
- Audit the permission. After running, confirm with
Get-VIPermission -Entity (Get-VMHost) | Format-Table Principal, Role, Propagate. Anything you do not recognise should be removed. - Rollback. To remove the permission later:
Get-VIPermission -Entity (Get-VMHost $ESXiHost) -Principal 'CONTOSO\ESXi Admins' | Remove-VIPermission -Confirm:$false. To unjoin the host from AD:Get-VMHostAuthentication -VMHost $ESXiHost | Set-VMHostAuthentication -LeaveDomain -Credential $DomainCredential -Confirm:$false.
Original 2014 script
Kept here for historical reference. This was the snap-in based version that shipped with PowerCLI 5.x. Do not run it as-is on modern PowerCLI; use the script above.
# VMware ESXI Script to create Domain group on Root of ESXI Host
# Created by Ryan Mangan on the 16/04/2014
param (
[Parameter(Mandatory=$TRUE, HelpMessage="Enter the name of the ESXI Host FQDN")]
[String] $VMHost,
[Parameter(Mandatory=$TRUE, HelpMessage="Host Root Password Dual control")]
[String] $HostPW
)
$DomainAdmin = "Domain Account"
$DomainPW = "Password"
$ADGroup = "Domain\group"
$Domain = "Domain FQDN"
Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer $VMHost -User root -Password $HostPW
Get-VMHostAuthentication -VMHost $VMHost |
Set-VMHostAuthentication -Domain $Domain -Username $DomainAdmin -Password $DomainPW -JoinDomain -Confirm:$false
Get-VMHost $VMHost | New-VIPermission -Principal $ADGroup -Role "Admin"
Disconnect-VIServer $VMHost -Confirm:$false




