Step-by-Step Guide to Installing and Configuring Active Directory on Windows Server (with PowerShell & Graph API Troubleshooting)
A complete, production-style walkthrough for modern Windows Server admins: planning, installing, hardening, and troubleshooting Active Directory (AD) with deep-dive PowerShell and Microsoft Graph API examples.
Why this guide matters
Active Directory remains the backbone for identity, access, and policy at thousands of organizations. Even as Microsoft Entra ID (formerly Azure AD) powers cloud identity, on-premises AD DS continues to authenticate users and machines, govern Group Policy, and broker secure access to file shares, print, and line-of-business apps. This guide blends hands-on steps, best practices, and an operational playbook so you can deploy confidently and fix issues fast.
We’ll use the sample domain cac.local, DC IP 192.168.2.10, static server range 192.168.2.1–100, DHCP pool 192.168.2.101–200. Adjust to your environment.
Prerequisites & planning checklist
Platform
- Windows Server 2019/2022 ISO installed on a VM/host.
- 2 vCPU, 8 GB RAM (lab), 60+ GB disk (more for SYSVOL/DFS-R growth).
- Two NICs recommended: NAT and Internal.
Names & IPs
- Domain:
cac.local - DC IP:
192.168.2.10, Subnet:255.255.255.0 - Clients via DHCP:
192.168.2.101–200
Security
- Separate admin accounts (Tiered Admin model).
- Hardened DNS, NTP, and GPO baselines.
- Backups (System State, AD DB, SYSVOL).
Network configuration (server & clients)
Server NICs
- Rename NICs (clarity): Internet (NAT) and CAC-Internal (LAN).
- On Internet NIC: obtain IP automatically; set DNS to
127.0.0.1after AD/DNS install. - On CAC-Internal NIC: set static IP
192.168.2.10, mask255.255.255.0, DNS127.0.0.1.
IP plan (quick reference)
| Range | Use | Notes |
|---|---|---|
| 192.168.2.1–100 | Static: servers, infra | DCs, printers, load balancers |
| 192.168.2.101–200 | DHCP pool | Windows clients, temp devices |
| 192.168.2.201–254 | Reserve | Growth/headroom |
Keep a living IPAM spreadsheet or CMDB for allocations; it pays off during audits and incident response.
Install Active Directory Domain Services (AD DS)
GUI path (quick)
- Open Server Manager → Add roles and features.
- Role-based installation → select this server → choose Active Directory Domain Services.
- Complete the wizard; then click the yellow flag → Promote this server to a domain controller.
- Create a new forest:
cac.local; set DSRM password; proceed with defaults (DNS, GC). - Reboot when prompted.
PowerShell path (fast, repeatable)
# Run in elevated PowerShell on the future DC Install-WindowsFeature AD-Domain-Services -IncludeManagementTools Import-Module ADDSDeployment Install-ADDSForest ` -DomainName "cac.local" ` -DomainNetbiosName "CAC" ` -SafeModeAdministratorPassword (Read-Host -AsSecureString "DSRM Password") ` -InstallDns:$true ` -NoRebootOnCompletion:$false
After promotion, confirm DNS zones (cac.local, _msdcs.cac.local) and that the server’s preferred DNS is itself (127.0.0.1).
DNS & DHCP essentials (foundation for smooth logons)
DNS sanity checks
- A/AAAA records for DC(s) and key servers are present and accurate.
- SRV records (
_ldap._tcp.dc._msdcs) exist for the DC. - Clients use only your AD DNS (not an external resolver).
Resolve-DnsName -Type SRV _ldap._tcp.dc._msdcs.cac.local Resolve-DnsName -Name dc1.cac.local
DHCP scope (optional but common)
- Install DHCP: Add-WindowsFeature DHCP or via Server Manager.
- Create scope:
192.168.2.101–200, mask255.255.255.0. - Options: Router (gateway), DNS server (DC IP), DNS domain
cac.local.
Add-WindowsFeature DHCP -IncludeManagementTools Add-DhcpServerv4Scope -Name "LAN-192.168.2.0" -StartRange 192.168.2.101 -EndRange 192.168.2.200 -SubnetMask 255.255.255.0 Set-DhcpServerv4OptionValue -DnsDomain "cac.local" -DnsServer 192.168.2.10
Join Windows clients to the domain
- Ensure client gets IP via DHCP and can resolve
dc1.cac.local. - Set the client’s primary DNS to the DC address (
192.168.2.10). - System → About → Rename this PC (advanced) → Change → Domain:
cac.local.
$cred = Get-Credential # domain join rights (e.g., CAC\Joiner) Add-Computer -DomainName "cac.local" -Credential $cred -Restart
Core administration: users, groups, OUs, and Group Policy
Create a secure OU structure
- _Core (Service Accounts, Admins)
- _Users (By department)
- _Computers (Workstations, Laptops)
- _Servers (By role: File, Print, SQL)
Import-Module ActiveDirectory New-ADOrganizationalUnit -Name "_Core" -Path "DC=cac,DC=local" New-ADOrganizationalUnit -Name "_Users" -Path "DC=cac,DC=local" New-ADOrganizationalUnit -Name "_Computers" -Path "DC=cac,DC=local" New-ADOrganizationalUnit -Name "_Servers" -Path "DC=cac,DC=local" New-ADGroup -Name "GG-IT-Admins" -GroupScope Global -GroupCategory Security -Path "OU=_Core,DC=cac,DC=local"
Create users with enforced standards
# CSV columns: GivenName,Surname,SamAccountName,UserPrincipalName,Department,OU
# Example OU: OU=_Users,DC=cac,DC=local
$users = Import-Csv .\new_users.csv
foreach($u in $users){
$ou = $u.OU
$upn = $u.UserPrincipalName
$pwd = (New-Guid).Guid + "!" # temporary; rotate on first logon
New-ADUser -Name "$($u.GivenName) $($u.Surname)" `
-GivenName $u.GivenName -Surname $u.Surname `
-SamAccountName $u.SamAccountName -UserPrincipalName $upn `
-Department $u.Department -Path $ou `
-AccountPassword (ConvertTo-SecureString $pwd -AsPlainText -Force) `
-Enabled $true -ChangePasswordAtLogon $true
}
Group Policy (GPO) essentials
- Baseline hardening with Microsoft Security Baselines.
- Separate user vs. computer GPOs; link at appropriate OUs.
- Use WMI filters sparingly, document every exception.
New-GPO -Name "CIS-Workstation-Baseline" | New-GPLink -Target "OU=_Computers,DC=cac,DC=local" -LinkEnabled Yes gpupdate /force
Daily health checks (quick wins)
Domain Controller
- dcdiag /v clean
- repadmin /replsummary success
- Event Viewer: Directory Service, DNS Server, DFSR
DNS
- SRV records present
- Clients resolve
_ldap._tcp.cac.local
Time
- PDC Emulator syncs with reliable NTP
- Skew < 5 minutes (Kerberos)
# Run as domain admin
$errors = @()
Write-Host "== DCDIAG ==" -ForegroundColor Cyan
dcdiag /q; if($LASTEXITCODE -ne 0){ $errors += "dcdiag issues" }
Write-Host "== REPLICATION ==" -ForegroundColor Cyan
repadmin /replsummary; if($LASTEXITCODE -ne 0){ $errors += "replication issues" }
Write-Host "== DNS SRV Check ==" -ForegroundColor Cyan
try {
Resolve-DnsName -Type SRV _ldap._tcp.dc._msdcs.cac.local -ErrorAction Stop | Out-Null
} catch { $errors += "SRV records missing" }
Write-Host "== PDC Time Source ==" -ForegroundColor Cyan
w32tm /query /source
if($errors.Count){
Write-Warning "Health check completed with issues: $($errors -join ', ')"
}else{
Write-Host "All baseline checks passed." -ForegroundColor Green
}
Troubleshooting: the fast path
1) Logons are slow or fail
Likely causes: client using public DNS, SRV records missing, network latency, GPO scripts stalling.
# On a problematic client: ipconfig /all | more # DNS must point only to 192.168.2.10 # From DC: Resolve-DnsName -Type SRV _ldap._tcp.dc._msdcs.cac.local
2) “The trust relationship between this workstation and the primary domain failed”
Likely cause: machine account password out of sync.
# On the affected machine (domain creds with rights) $creds = Get-Credential Reset-ComputerMachinePassword -Server "dc1.cac.local" -Credential $creds
3) Replication errors (SYSVOL/DFSR, lingering objects)
Use repadmin, check DFSR state, ensure DCs see each other’s SRV records and time source.
repadmin /replsummary repadmin /showrepl * Get-WinEvent -LogName "DFS Replication" -MaxEvents 50 | Format-Table TimeCreated,Id,LevelDisplayName,Message -Auto
4) Kerberos / time skew
Ensure the PDC Emulator syncs with an authoritative NTP server; downstream DCs/clients sync from the domain hierarchy.
# On PDC Emulator w32tm /config /manualpeerlist:"time.windows.com,0x8" /syncfromflags:manual /reliable:yes /update w32tm /resync w32tm /query /status
5) DNS “name does not exist” for domain join
Confirm forward/reverse lookups and ensure no stale A records.
Get-DnsServerZone -ComputerName dc1
Get-DnsServerResourceRecord -ZoneName "cac.local" | Where-Object {$_.RecordType -eq "A"}
Security hardening (must-do list)
- Use a tiered administration model; never browse or read email as Domain Admin.
- Protect DCs with LAPS/Windows LAPS for local admin passwords.
- Enable LDAP signing and channel binding; disable NTLM where feasible.
- Audit privileged groups (Enterprise/Domain Admins), and enforce PIM/JIT concepts where possible.
- Regularly back up System State and test authoritative/non-authoritative restore.
# Members of high-privilege groups
"Enterprise Admins","Domain Admins","Schema Admins","Administrators" | ForEach-Object {
Write-Host "`n== $_ =="
Get-ADGroupMember $_ -Recursive | Select-Object Name,SamAccountName,ObjectClass
}
# Accounts with "Password never expires" (investigate)
Search-ADAccount -PasswordNeverExpires | Select-Object Name,SamAccountName,Enabled
Hybrid identity & Microsoft Graph: visibility beyond on-prem
Many organizations run hybrid identity with Microsoft Entra Connect, syncing on-prem identities to the cloud. For incident response and sign-in analytics, the Microsoft Graph API provides powerful telemetry from Entra ID (sign-ins, conditional access, risky users) that complements on-prem AD DS logs.
Setup (one-time): Microsoft Graph PowerShell
Install-Module Microsoft.Graph -Scope AllUsers -Force # Use least privilege in production; for demos we request broad scopes Connect-MgGraph -Scopes "AuditLog.Read.All","Directory.Read.All","Policy.Read.All","Reports.Read.All","User.Read.All" Select-MgProfile -Name "v1.0"
Query sign-in failures (Graph)
# Last 24h failed sign-ins (summarized)
$since = (Get-Date).AddDays(-1).ToString("o")
$fail = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/auditLogs/signIns?$filter=createdDateTime ge $since and status/errorCode ne 0&$top=50"
($fail.value | Select-Object createdDateTime,userDisplayName,userPrincipalName,appDisplayName,ipAddress,clientAppUsed,conditionalAccessStatus,correlationId,status).Count
# Top failure reasons
$fail.value | Group-Object {$_.status.errorCode} | Sort-Object Count -Desc | Select-Object Name,Count
# Legacy (basic) auth sign-ins (clientAppUsed) - investigate and block
$legacy = $fail.value | Where-Object {$_.clientAppUsed -match "Legacy"}
$legacy | Select-Object createdDateTime,userPrincipalName,ipAddress,clientAppUsed | Format-Table -Auto
Risky users & risk detections (Graph)
# Risky users $risky = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identityProtection/riskyUsers" $risky.value | Select-Object userDisplayName,userPrincipalName,riskDetail,riskLevel | Format-Table -Auto # Risk detections (leaked creds, anonymous IP, impossible travel) $det = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identityProtection/riskDetections?$top=50" $det.value | Select-Object detectionTimingType,ipAddress,activityType,riskLevel,riskDetail,source
Conditional Access policies (inventory via Graph)
$cap = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies?$top=50" $cap.value | Select-Object displayName,state,conditions,grantControls
Cross-correlate on-prem events with cloud telemetry
Use correlation IDs from app sign-ins, match timestamps, and pivot on userPrincipalName to tell a full story (e.g., GPO change → client reboot → suspicious MFA denial).
Incident triage playbook (copy/paste)
- Scope: Which users/systems? Domain-wide or site-specific?
- Contain: Disable risky accounts; remove from privileged groups; enforce password reset/MFA.
- Evidence: AD DS logs (Security, Directory Service, DFSR), Graph sign-ins, Defender alerts.
- Root cause: DNS, time, replication, patching, GPO drift.
- Correct: Fix underlying misconfig, add monitoring, document lessons.
# On-prem AD Disable-ADAccount -Identity "samAccountName" # Microsoft Graph: revoke refresh tokens (cloud sessions) $userId = (Get-MgUser -UserId "user@cac.local").Id Invoke-MgInvalidateUserRefreshToken -UserId $userId
Maintenance windows & backups
- Monthly patching for DCs; stagger reboots per site.
- System State backups of DCs; quarterly restore tests.
- Document FSMO roles; ensure PDC Emulator resides on reliable hardware/site.
Get-ADForest | Select-Object SchemaMaster,DomainNamingMaster Get-ADDomain | Select-Object PDCEmulator,RIDMaster,InfrastructureMaster
Advanced diagnostics (when things get weird)
DFSR & SYSVOL integrity
# DFSR backlog between two DCs $src = "dc1"; $dst = "dc2"; $rg = "Domain System Volume"; $folder = "SYSVOL Share" dfsrdiag backlog /sendingmember:$src /receivingmember:$dst /rgname:"$rg" /rfname:"$folder" # Check DFSR service health events Get-WinEvent -LogName "DFS Replication" -MaxEvents 100 | Group-Object Id | Sort-Object Count -Desc | Select-Object Name,Count
Lingering objects & USN rollback suspicion
repadmin /showrepl * /csv | ConvertFrom-Csv | Where-Object {$_.result -notmatch "0x0"} | Format-Table -Auto
repadmin /replsummary
Kerberos tickets & SPNs
# Show Kerberos tickets on a client klist # Find duplicate SPNs (classic cause of 401/Logon failures) setspn -x
Roadmap: from on-prem AD to modern identity
- Deploy Entra Connect with staging server and Seamless SSO.
- Turn on Conditional Access (baseline, MFA for admins, block legacy auth).
- Move apps to modern auth (OIDC/SAML) and reduce NTLM.
- Adopt Privileged Identity Management and Access Reviews.
FAQ: quick answers
Should the DC point DNS to itself?
Yes—use 127.0.0.1 or its static IP. For multi-DC environments, you can point preferred DNS to a partner DC and alternate to self—just be consistent.
Do I need reverse lookup zones?
They improve diagnostics and some tooling, so create them for key subnets (e.g., 192.168.2.x → 2.168.192.in-addr.arpa).
Can I block legacy authentication?
On-prem, reduce NTLM where feasible and enforce Kerberos. In cloud, use Conditional Access to block legacy clients, then remediate service dependencies.
Wrap-up
With a clean network plan, a reliable DNS/NTP foundation, and a scripted install, Active Directory is straightforward to deploy and run. The real edge comes from operational excellence: daily health checks, auditable change control, and telemetry from both on-prem and the cloud via Microsoft Graph. Keep this guide nearby for build-outs and incidents—you’ll move faster and break less.
Fast, reliable Active Directory setup with blue-chip PowerShell and Graph API troubleshooting for modern Windows admins.
© Your Brand • Published for cloudknowledge.in readers.











Leave a Reply