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.
Lab Topology (concept)
┌────────────────────────────┐ Internet/NAT
│ Windows Server 2022 (DC1) │─── (Outbound only)
│ Roles: AD DS, DNS, DHCP │
│ NIC1: 10.10.2.x (NAT) │
│ NIC2: 192.168.2.10/24 │── Internal VLAN "CAC-Internal"
└────────────────────────────┘
▲ ▲
│ └────────────── Clients (Win 10/11) via DHCP (192.168.2.101–200)
│
└────────────── Management workstation (optional)
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
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.1 after AD/DNS install.
- On CAC-Internal NIC: set static IP
192.168.2.10, mask 255.255.255.0, DNS 127.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.
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)
Install AD DS role and create new forest
# 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).
Quick DNS verification (PowerShell)
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, mask 255.255.255.0.
- Options: Router (gateway), DNS server (DC IP), DNS domain
cac.local.
Create DHCP scope (PowerShell)
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.
Domain join via PowerShell (client)
$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)
Create OUs and a sample group (PowerShell)
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
Bulk user creation from CSV (PowerShell)
# 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.
Create and link a GPO (PowerShell)
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)
Wrap common checks (PowerShell)
# 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.
Fix client DNS and verify SRV
# 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.
Find risky delegations & privileged group members (PowerShell)
# 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)
Spot MFA failures, conditional access blocks, legacy auth
# 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.
Disable account and force sign-out (on-prem + cloud)
# 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.
FSMO quick view (PowerShell)
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
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.
Google Discover / Edge News Summary (120 chars):
Fast, reliable Active Directory setup with blue-chip PowerShell and Graph API troubleshooting for modern Windows admins.
© Your Brand • Published for cloudknowledge.in readers.