Fix fresh domain controller bootstrap

This commit is contained in:
2026-09-03 17:26:05 -06:00
parent 1d7c312a67
commit 57572c5567
5 changed files with 278 additions and 40 deletions
+57 -10
View File
@@ -8,18 +8,65 @@ param(
)
$ErrorActionPreference = 'Stop'
$existing = Get-DnsServerResourceRecord -ZoneName $ZoneName -Name $RecordName -RRType A -ErrorAction SilentlyContinue
if ($existing) {
$current = @($existing.RecordData.IPv4Address.IPAddressToString)
if ($current.Count -ne 1 -or $current[0] -ne $IPv4Address.IPAddressToString) {
# The fixed lab address is an explicit bootstrap input and may change
# when the server is rebuilt. Replace only this exact A record set.
$existing | Remove-DnsServerResourceRecord -ZoneName $ZoneName -Force
Add-DnsServerResourceRecordA -ZoneName $ZoneName -Name $RecordName -IPv4Address $IPv4Address
$dnsReady = $false
for ($attempt = 1; $attempt -le 30; $attempt++) {
try {
$soa = @(Resolve-DnsName $ZoneName -Type SOA -DnsOnly -Server localhost `
-ErrorAction Stop | Where-Object Type -eq SOA)
if ($soa.Count -gt 0) {
$dnsReady = $true
break
}
}
catch {
# An AD-integrated zone can take a few seconds to load after DNS starts.
}
Start-Sleep -Seconds 2
}
else {
Add-DnsServerResourceRecordA -ZoneName $ZoneName -Name $RecordName -IPv4Address $IPv4Address
if (-not $dnsReady) {
throw "DNS did not load the $ZoneName zone before the readiness timeout."
}
$recordReady = $false
for ($attempt = 1; $attempt -le 5; $attempt++) {
$existing = @(Get-DnsServerResourceRecord -ZoneName $ZoneName -Name $RecordName `
-RRType A -ErrorAction SilentlyContinue)
$unwanted = @($existing | Where-Object {
$_.RecordData.IPv4Address.IPAddressToString -ne $IPv4Address.IPAddressToString
})
foreach ($record in $unwanted) {
Remove-DnsServerResourceRecord -ZoneName $ZoneName -InputObject $record -Force
}
$desired = @($existing | Where-Object {
$_.RecordData.IPv4Address.IPAddressToString -eq $IPv4Address.IPAddressToString
})
if ($desired.Count -eq 0) {
try {
Add-DnsServerResourceRecordA -ZoneName $ZoneName -Name $RecordName `
-IPv4Address $IPv4Address -ErrorAction Stop
}
catch {
# A record that becomes visible while an AD-integrated zone is
# finishing its load is harmless; the verified read below decides.
}
}
Start-Sleep -Milliseconds 250
$final = @(Get-DnsServerResourceRecord -ZoneName $ZoneName -Name $RecordName `
-RRType A -ErrorAction SilentlyContinue)
$finalAddresses = @($final | ForEach-Object {
$_.RecordData.IPv4Address.IPAddressToString
})
if ($finalAddresses.Count -eq 1 -and
$finalAddresses[0] -eq $IPv4Address.IPAddressToString) {
$recordReady = $true
break
}
Start-Sleep -Seconds 1
}
if (-not $recordReady) {
throw "The $RecordName.$ZoneName A record could not be set exclusively to $IPv4Address."
}
if ($ExternalForwarders.Count -gt 0) {