How to Set Up Multi-Site Active Directory on Windows Server 2012 R2
A multi-site Active Directory deployment distributes Domain Controllers across geographically separated locations, providing local authentication, policy application, and directory services to users at each site without relying on WAN connectivity for every AD operation. Properly designed AD sites and services configuration is essential for controlling replication topology, directing client authentication to local DCs, and managing Group Policy application in distributed environments. This guide covers designing and implementing a complete multi-site AD infrastructure on Windows Server 2012 R2.
Prerequisites
– Windows Server 2012 R2 Domain Controllers at each site
– IP subnets for each site clearly defined
– Network connectivity between sites (WAN, MPLS, VPN, or ExpressRoute)
– DNS properly configured at all sites
– Active Directory Sites and Services snap-in access
– Enterprise Admin or Domain Admin privileges
– Defined replication schedule and bandwidth constraints per site link
Step 1: Create AD Sites
Import-Module ActiveDirectory
# Create sites for each physical location
$sites = @(
@{Name="HQ-Chicago"; Description="Headquarters - Chicago, IL"},
@{Name="Branch-NYC"; Description="New York City Branch Office"},
@{Name="Branch-LA"; Description="Los Angeles Branch Office"},
@{Name="Branch-London"; Description="London UK Branch Office"},
@{Name="DC-Dallas"; Description="Dallas Data Center - Colocation"}
)
foreach ($s in $sites) {
try {
New-ADReplicationSite -Name $s.Name -Description $s.Description
Write-Host "Created site: $($s.Name)" -ForegroundColor Green
} catch {
Write-Warning "Site may already exist: $($s.Name)"
}
}
# Verify sites
Get-ADReplicationSite -Filter * | Select-Object Name, Description | Format-Table -AutoSize
Step 2: Create Subnets and Associate with Sites
Active Directory uses subnet-to-site mappings to determine which site a client belongs to. This is what controls which DC a client authenticates against:
Import-Module ActiveDirectory
$subnets = @(
@{Name="10.10.0.0/16"; Site="HQ-Chicago"; Description="Chicago corporate network"},
@{Name="10.10.100.0/24";Site="HQ-Chicago"; Description="Chicago DMZ"},
@{Name="10.20.0.0/24"; Site="Branch-NYC"; Description="NYC office network"},
@{Name="10.30.0.0/24"; Site="Branch-LA"; Description="LA office network"},
@{Name="172.16.10.0/24";Site="Branch-London";Description="London office network"},
@{Name="192.168.50.0/24";Site="DC-Dallas"; Description="Dallas colo network"},
@{Name="192.168.51.0/24";Site="DC-Dallas"; Description="Dallas management network"}
)
foreach ($subnet in $subnets) {
try {
New-ADReplicationSubnet -Name $subnet.Name `
-Site $subnet.Site `
-Description $subnet.Description
Write-Host "Created subnet $($subnet.Name) -> $($subnet.Site)" -ForegroundColor Green
} catch {
Write-Warning "Subnet error: $($subnet.Name) - $($_.Exception.Message)"
}
}
# Verify subnet assignments
Get-ADReplicationSubnet -Filter * |
Select-Object Name, Site, Description |
Format-Table -AutoSize
Step 3: Create Site Links
Site links define the replication paths between sites. Their cost, replication frequency, and schedule determine when and how often replication occurs across each path:
Import-Module ActiveDirectory
# Remove the default DEFAULTIPSITELINK if not needed
# Get-ADReplicationSiteLink -Filter * | Remove-ADReplicationSiteLink
# Create site links representing actual WAN connections
$siteLinks = @(
@{
Name="HQ-NYC-Link"
SitesIncluded=@("HQ-Chicago","Branch-NYC")
Cost=100
ReplicationFrequency=15 # minutes
Description="MPLS Chicago-NYC 100Mbps"
},
@{
Name="HQ-LA-Link"
SitesIncluded=@("HQ-Chicago","Branch-LA")
Cost=150
ReplicationFrequency=30
Description="MPLS Chicago-LA 50Mbps"
},
@{
Name="HQ-London-Link"
SitesIncluded=@("HQ-Chicago","Branch-London")
Cost=300
ReplicationFrequency=60
Description="MPLS Chicago-London 10Mbps transatlantic"
},
@{
Name="HQ-Dallas-Link"
SitesIncluded=@("HQ-Chicago","DC-Dallas")
Cost=50
ReplicationFrequency=15
Description="Private fiber Chicago-Dallas datacenter"
}
)
foreach ($link in $siteLinks) {
New-ADReplicationSiteLink -Name $link.Name `
-SitesIncluded $link.SitesIncluded `
-Cost $link.Cost `
-ReplicationFrequencyInMinutes $link.ReplicationFrequency `
-Description $link.Description `
-InterSiteTransportProtocol IP
Write-Host "Created site link: $($link.Name)" -ForegroundColor Green
}
# Enable site link bridging if needed for indirect routes
# Set-ADReplicationSiteLinkBridge (typically not required if all sites are fully connected)
# Configure replication schedule for the London link (replicate only during off-hours)
$londonLink = Get-ADReplicationSiteLink -Identity "HQ-London-Link"
# Schedule: Mon-Fri 6PM-6AM UTC, all day Saturday and Sunday
# Schedule is configured as a 168-byte array; use ADAC GUI for complex schedules
Set-ADReplicationSiteLink -Identity "HQ-London-Link" `
-ReplicationFrequencyInMinutes 180 # 3-hour intervals for bandwidth conservation
# Verify site links
Get-ADReplicationSiteLink -Filter * |
Select-Object Name, Cost, ReplicationFrequencyInMinutes |
Format-Table -AutoSize
Step 4: Place Domain Controllers in Sites
Import-Module ActiveDirectory
# Move DCs to their correct sites
# The DC's IP address determines its site automatically IF the subnet is configured
# But you can also manually place DCs
$dcSiteMapping = @(
@{DC="HQ-DC01"; Site="HQ-Chicago"},
@{DC="HQ-DC02"; Site="HQ-Chicago"},
@{DC="NYC-DC01"; Site="Branch-NYC"},
@{DC="LA-DC01"; Site="Branch-LA"},
@{DC="LON-DC01"; Site="Branch-London"},
@{DC="DAL-DC01"; Site="DC-Dallas"},
@{DC="DAL-DC02"; Site="DC-Dallas"}
)
foreach ($mapping in $dcSiteMapping) {
$dcObject = Get-ADDomainController -Identity $mapping.DC -ErrorAction SilentlyContinue
if ($dcObject) {
$ntdsPath = "CN=NTDS Settings,CN=$($mapping.DC),CN=Servers,CN=$($mapping.Site),CN=Sites,CN=Configuration,$((Get-ADDomain).DistinguishedName)"
# Move the server object to the correct site
$serverPath = "CN=$($mapping.DC),CN=Servers,CN=$($mapping.Site),CN=Sites,CN=Configuration,$((Get-ADDomain).DistinguishedName)"
Write-Host "DC $($mapping.DC) -> Site: $($dcObject.Site)"
}
}
# Verify DC placement
Get-ADDomainController -Filter * |
Select-Object Hostname, Site, IsGlobalCatalog, OperationMasterRoles |
Format-Table -AutoSize
Step 5: Configure Global Catalog Servers
Import-Module ActiveDirectory
# Make DCs in large sites Global Catalog servers
# GC servers are required for Universal Group membership lookups
$gcCandidates = @("HQ-DC01","HQ-DC02","DAL-DC01","NYC-DC01")
foreach ($dc in $gcCandidates) {
Set-ADDomainController -Identity $dc -IsGlobalCatalog $true
Write-Host "Enabled Global Catalog on: $dc" -ForegroundColor Green
}
# For bandwidth-constrained sites (London), avoid GC unless justified
# Universal Group Membership Caching is an alternative for small branch offices
# This must be enabled in AD Sites and Services for each site
$londonSite = Get-ADReplicationSite -Identity "Branch-London"
# Configure Universal Group Membership Caching via ADAC or repadmin
# Verify GC distribution
Get-ADDomainController -Filter {IsGlobalCatalog -eq $true} |
Select-Object Hostname, Site | Format-Table -AutoSize
Step 6: Configure Operations Master Roles
Import-Module ActiveDirectory
# Check current FSMO role placement
$forest = Get-ADForest
$domain = Get-ADDomain
Write-Host "=== FSMO Role Placement ===" -ForegroundColor Cyan
Write-Host "Schema Master: $($forest.SchemaMaster)"
Write-Host "Domain Naming Master: $($forest.DomainNamingMaster)"
Write-Host "PDC Emulator: $($domain.PDCEmulator)"
Write-Host "RID Master: $($domain.RIDMaster)"
Write-Host "Infrastructure Master:$($domain.InfrastructureMaster)"
# Best practice: PDC Emulator should be in the largest/most connected site (HQ)
# RID Master with PDC Emulator
# Infrastructure Master should NOT be on a GC server (unless all DCs are GC)
# Move PDC Emulator to HQ if not already there
if ($domain.PDCEmulator -notlike "*HQ*") {
Move-ADDirectoryServerOperationMasterRole `
-Identity "HQ-DC01" `
-OperationMasterRole PDCEmulator -Force
Write-Host "Moved PDC Emulator to HQ-DC01" -ForegroundColor Green
}
# Set site coverage for sites without DCs
# This is automatic based on site link costs, but can be forced
# Clients in sites with no DC use the DC from the closest connected site
Step 7: Monitor Replication Health Across Sites
# Comprehensive multi-site replication monitoring
function Get-MultiSiteReplicationHealth {
$dcs = Get-ADDomainController -Filter *
$report = [System.Collections.Generic.List[PSCustomObject]]::new()
foreach ($dc in $dcs) {
try {
$partners = Get-ADReplicationPartnerMetadata -Target $dc.Hostname -ErrorAction Stop
foreach ($partner in $partners) {
$report.Add([PSCustomObject]@{
SourceDC = $dc.Hostname
SourceSite = $dc.Site
PartnerDC = $partner.Partner -replace 'CN=NTDS.*?CN=',''-replace ',.*',''
LastSuccess = $partner.LastReplicationSuccess
Errors = $partner.ConsecutiveReplicationFailures
HealthStatus = if ($partner.ConsecutiveReplicationFailures -eq 0) {"OK"} else {"FAILED"}
})
}
} catch {
$report.Add([PSCustomObject]@{
SourceDC = $dc.Hostname
SourceSite = $dc.Site
HealthStatus = "QueryFailed: $($_.Exception.Message)"
})
}
}
$failed = $report | Where-Object { $_.HealthStatus -ne "OK" }
if ($failed) {
Write-Warning "Replication issues detected:"
$failed | Format-Table -AutoSize
} else {
Write-Host "All replication links healthy" -ForegroundColor Green
}
$report | Group-Object SourceSite | ForEach-Object {
Write-Host "Site: $($_.Name) - $($_.Count) connections"
}
$report | Export-Csv "C:ReportsMultiSiteReplHealth.csv" -NoTypeInformation
}
Get-MultiSiteReplicationHealth
# Force replication between specific DCs
repadmin /replicate nyc-dc01 hq-dc01 "DC=corp,DC=local"
# Run dcdiag across all sites
dcdiag /test:replications /v /e
Verification
# Full multi-site AD verification
Write-Host "=== Multi-Site AD Health ===" -ForegroundColor Cyan
# Sites
Write-Host "Sites configured: $(( Get-ADReplicationSite -Filter *).Count)"
Get-ADReplicationSite -Filter * | Select-Object Name | Sort-Object Name | Format-Table
# Subnets
Write-Host "Subnets configured: $((Get-ADReplicationSubnet -Filter *).Count)"
# Site links
Write-Host "Site Links:"
Get-ADReplicationSiteLink -Filter * |
Select-Object Name, Cost, ReplicationFrequencyInMinutes | Format-Table
# DC distribution
Write-Host "DC Site Distribution:"
Get-ADDomainController -Filter * | Group-Object Site |
Select-Object Name, Count | Format-Table
# Replication topology (connection objects)
repadmin /showrepl * /errorsonly
Summary
A properly designed multi-site Active Directory on Windows Server 2012 R2 ensures that users at each location authenticate against local Domain Controllers, Group Policy is applied efficiently, and directory replication is managed according to available WAN bandwidth. The key components are Sites (representing physical locations), Subnets (mapping IP ranges to sites), Site Links (defining replication paths with costs and schedules), and Domain Controllers placed at each site serving as local authentication points. With Global Catalog servers at major sites, FSMO roles in the most connected location, and regular replication health monitoring, your multi-site AD will provide consistent, reliable identity services across your entire organization.