Configure the Local Active Directory connector
- One domain-joined Windows host to run the connector — a member server is recommended over a Domain Controller.
- Domain Admin (or equivalently delegated) rights to create a gMSA and delegate OU permissions.
- The connector host can reach a Domain Controller on TCP 9389 (AD Web Services), plus Kerberos and LDAP.
- Outbound HTTPS (TCP 443) from the host to https://dex365.ai, and the tenant's enrollment token from the Dex console.
Choose & prepare the connector host
~10 minInstall RSAT, picking the command for the host OS. The connector host must also reach a DC on TCP 9389 (AD Web Services).
Verify the module and ADWS connectivity
~2 minOn the connector host, confirm the ActiveDirectory module is available and AD Web Services is reachable.
Get-Module -ListAvailable ActiveDirectory # module is listed Get-ADDomain # confirms ADWS connectivity
Generate an enrollment token in Dex
~2 minThe connector enrolls with a tenant enrollment token, the same as any Dex Device Agent. Sign in to the Dex console, go to Settings → Devices, and under Enrollment tokens generate (or reveal) a token. You'll put this value in the connector config as enrollment_token.
Create the KDS root key (one-time per forest)
~5 mingMSAs require a Key Distribution Service (KDS) root key. Skip this if a usable key already exists — check first. A new key isn't usable until 10 hours after its effective time (to allow replication across DCs); -EffectiveImmediately does not bypass this wait.
Create the gMSA and authorize the host
~5 minRun on a Domain Controller (or any host with AD admin rights). -PrincipalsAllowedToRetrieveManagedPassword must be the computer account of the host that will run the connector — its machine name with a trailing $. This is not a literal placeholder; substitute your real host name.
# On the connector host, get its name: $env:COMPUTERNAME # Confirm the computer object exists in AD (use the name from above): Get-ADComputer <CONNECTOR_HOSTNAME> # Create the gMSA, authorizing that host (trailing $ is required): New-ADServiceAccount -Name dexgmsa ` -DNSHostName dexgmsa.<corp.example.com> ` -PrincipalsAllowedToRetrieveManagedPassword "<CONNECTOR_HOSTNAME>$"
Install and verify the gMSA on the host
~3 minOn the connector host (elevated PowerShell), install the gMSA and confirm it. Install-ADServiceAccount copies no password — it verifies the host is authorized and lets the LSA fetch the rotating password from AD on demand. Test-ADServiceAccount must return True before continuing.
Install-ADServiceAccount -Identity dexgmsa Test-ADServiceAccount -Identity dexgmsa # must return True Get-ADServiceAccount dexgmsa # confirms the account exists
Identify the OU(s) to manage
~3 minPick (or create) the OU(s) the connector will manage and note each Distinguished Name — these go into the connector config's allowed_ous later, and you delegate rights on exactly these OUs.
New-ADOrganizationalUnit -Name "Staff" -Path "DC=corp,DC=example,DC=com" # DN: OU=Staff,DC=corp,DC=example,DC=com
Delegate least-privilege rights with dsacls
~10 minRun in an elevated PowerShell on a DC (or host with AD admin rights). Do not add the gMSA to Domain Admins. Set $ou to your target OU's DN and $gmsa to your <DOMAIN>\dexgmsa$, then run the complete grant block — it covers every supported connector action. Repeat for each OU by changing $ou and re-running.
GR (generic read)ad_user_exists, ad_get_user, ad_find_users_in_ou, ad_get_group_members, ad_list_user_groups, ad_find_groups.CC;user + WP;;user + CA;Reset Passwordad_create_user (object + initial property writes + initial password).DC;userad_delete_user.WP;;user (userAccountControl)ad_enable_user, ad_disable_user.WP;;user (lockoutTime)ad_unlock_user.CA;Reset Passwordad_reset_password.WP;;userad_update_user (name, email, title, department, manager, …).WP;;user (accountExpires)ad_set_account_expiration.RPWP;member;groupad_add_group_member, ad_remove_group_member.CCDC;groupad_create_group, ad_delete_group.CCDC;organizationalUnitad_create_ou, ad_delete_ou.CC/DC on user/group (see note)ad_move_object — within the delegated subtree. A move to an OU outside your delegated OUs needs CC of that object class on the destination too; a move that also renames needs WP;name;user / WP;name;group.$ou = "OU=Staff,DC=corp,DC=example,DC=com"
$gmsa = "<DOMAIN>\dexgmsa$"
# READ — user_exists, get_user, find_users_in_ou,
# get_group_members, list_user_groups, find_groups
dsacls $ou /I:T /G "${gmsa}:GR"
# USER create + delete — create_user, delete_user
dsacls $ou /I:T /G "${gmsa}:CCDC;user"
# USER property writes — update_user, enable_user, disable_user,
# unlock_user, set_account_expiration, force-change-at-logon
# (covers userAccountControl, lockoutTime, accountExpires, pwdLastSet, etc.)
dsacls $ou /I:S /G "${gmsa}:WP;;user"
# Reset password — reset_password (+ initial password on create_user)
dsacls $ou /I:S /G "${gmsa}:CA;Reset Password;user"
# GROUP create + delete — create_group, delete_group
dsacls $ou /I:T /G "${gmsa}:CCDC;group"
# GROUP membership — add_group_member, remove_group_member
dsacls $ou /I:S /G "${gmsa}:RPWP;member;group"
# OU create + delete — create_ou, delete_ou
dsacls $ou /I:T /G "${gmsa}:CCDC;organizationalUnit"Write the connector config
~3 minCreate C:\ProgramData\DexDeviceAgent\config.yaml (the installer creates the directory). Both enabled: true and the ad-connector profile are required before the agent will accept AD commands. List your real OU DNs in allowed_ous, matching exactly what you delegated.
cloud_service:
base_url: "https://dex365.ai"
enrollment_token: "<TENANT_ENROLLMENT_TOKEN>"
connector:
profile: "ad-connector"
service_account: "<DOMAIN>\\dexgmsa$" # informational
ad:
enabled: true # master switch — required
allowed_ous: # empty = deny ALL writes (safe default)
- "OU=Staff,DC=corp,DC=example,DC=com"
allow_raw_powershell: false # leave OFF unless you truly need itInstall the agent with the AD profile
~5 minThe connector is the same MSI as the regular Dex agent — the AD profile is selected by an install-time property. Pre-flight the gMSA first, then install. With no PROFILE property the MSI installs the ordinary endpoint agent unchanged.
msiexec /i DexDeviceAgent.msi /qn ` PROFILE=ad-connector AD_SERVICE_ACCOUNT="<DOMAIN>\dexgmsa$"
Install-DexAgent.ps1 -Token <TENANT_ENROLLMENT_TOKEN> ` -Profile ad-connector -ServiceAccount "<DOMAIN>\dexgmsa$"
Service identity & upgrades
as neededRe-running the installer (e.g. to upgrade) re-registers the Windows service and resets its logon identity back to LocalSystem — silently undoing the gMSA assignment. LocalSystem has no rights in AD, so every AD operation then fails with ACCESS_DENIED even though your OU delegation is perfectly intact. This looks exactly like a permissions problem but is not. Make re-pointing the service a standard post-upgrade check. The PowerShell-native method handles the empty gMSA password correctly; the sc.exe alternative needs single quotes around the account and no password argument. If the custom action never ran (e.g. the MSI was interrupted), also re-grant "Log on as a service" via secpol.msc → Local Policies → User Rights Assignment (type the gMSA name in directly — the picker won't resolve it cleanly) and ensure the profile policy key exists.
Stop-Service DexDeviceAgent
$svc = Get-CimInstance Win32_Service -Filter "Name='DexDeviceAgent'"
$svc | Invoke-CimMethod -MethodName Change -Arguments @{
StartName = '<DOMAIN>\dexgmsa$'
StartPassword = $null
} # ReturnValue 0 = success
Start-Service DexDeviceAgentsc.exe config DexDeviceAgent obj= '<DOMAIN>\dexgmsa$' Restart-Service DexDeviceAgent sc.exe qc DexDeviceAgent # SERVICE_START_NAME must read <DOMAIN>\dexgmsa$
Get-ItemProperty "HKLM:\SOFTWARE\Policies\DexDeviceAgent" # If Profile is missing or not "ad-connector", the agent is idle and rejects AD commands.
Verify the connector
~3 minConfirm the service runs as the gMSA, then from the Dex console send AD_CAPABILITIES to the device — expect module_available: true, the correct deployment_mode, and adws_reachable: true. Logs are at C:\ProgramData\DexDeviceAgent\logs\DexDeviceAgent.log (passwords are redacted).
sc.exe qc DexDeviceAgent # SERVICE_START_NAME should be <DOMAIN>\dexgmsa$ Get-Service DexDeviceAgent # Status: Running
Approve the device and enable the Local Active Directory app
~3 minOnce AD_CAPABILITIES reports adws_reachable: true, approve the device as an AD operator in the Dex console, then enable the Local Active Directory app so Dex routes AD commands to it. Until the app is enabled, Dex has the connector but no tools, skills, or actions to act with.
Troubleshooting
referenceCommon symptoms, their cause, and the fix. Most "permissions" failures after an upgrade are actually the service reverting to LocalSystem — check the service identity first.
Local Active Directory is live
The connector runs as a least-privilege gMSA, the device is approved as an AD operator, and the Local Active Directory app is enabled — Dex can now create, disable, and manage users, groups, and OUs in your on-prem AD, routed automatically to this connector. For production, run it on a member server (not a DC), sign the agent build, and trim user-property delegation to the specific attributes in use.