TL;DR: Point the server at the DC for DNS, make sure the clock isn't more than 5 minutes off, then run one command:

Add-Computer -DomainName corp.local -Credential corp\domainadmin -OUPath "OU=Servers,DC=corp,DC=local" -Restart

That's the whole post if you already know what you're doing. Below is the stuff that actually goes wrong.

Prereqs (the part everyone skips)

Domain-join fails for three reasons, in this order: DNS, time, and network. Fix those first or you'll waste an hour reading event logs.

DNS

The server must use the domain controller as its primary DNS server. Not Google DNS. Not Cloudflare. The DC. If you can't resolve corp.local or the DC's FQDN from the server, you can't join.

Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 10.0.0.10
Resolve-DnsName corp.local
nslookup -type=SRV _ldap._tcp.corp.local

If _ldap._tcp.corp.local doesn't return SRV records pointing at your DC, nothing else matters. Fix DNS first.

Time

Kerberos refuses tickets if the clock skew is over 5 minutes. Fresh VMs often boot with garbage time.

w32tm /query /status
w32tm /resync

If the server is a VM, double-check that hypervisor time sync is actually working. I've been bitten by VMs reporting the host time as UTC when the host was in local time.

Network

The server needs to reach the DC on a handful of ports: 53 (DNS), 88 (Kerberos), 389 (LDAP), 445 (SMB), 464 (kpasswd), plus the high RPC range. Quick test:

Test-NetConnection dc01.corp.local -Port 389
Test-NetConnection dc01.corp.local -Port 445

The join command

With prereqs green, the join is one line. Use -Credential so you get prompted for the password instead of putting it on disk:

Add-Computer -DomainName corp.local -Credential corp\domainadmin -OUPath "OU=Servers,DC=corp,DC=local" -NewName "web05" -Restart

Flags that matter:

  • -DomainName — the domain name, not the DC hostname
  • -Credential — a user with the "Add workstations to domain" right, or Domain Admin
  • -OUPath — full distinguished name. Skip this and the computer object lands in CN=Computers, which nobody wants
  • -NewName — rename during join, saves a reboot
  • -Restart — required to activate the join, and you can't use the box until you reboot anyway

If the command returns without an error, you're joined. The reboot finishes the work.

Verify it worked

After the reboot, log in with a domain account and run:

systeminfo | findstr /B "Domain"
(Get-WmiObject Win32_ComputerSystem).PartOfDomain
gpresult /r /scope:computer
klist

systeminfo should print your domain, not WORKGROUP. gpresult shows applied GPOs — if it prints nothing, either the OU has no GPOs linked or AD replication hasn't caught up. klist lists Kerberos tickets and proves the machine account is authenticating properly.

Leave the domain

Same flow in reverse. Don't just delete the computer object in AD and wonder why things break.

Remove-Computer -UnjoinDomainCredential corp\domainadmin -PassThru -Verbose -Restart

This cleans both sides: the local secure channel and the AD computer object. If the server can't reach AD anymore (typical decommissioning scenario), add -Force for a local-only unjoin, then remove the stale AD object by hand.

Gotchas I've actually hit

Duplicate computer object

Joining a server with the same name as a pre-existing AD object fails with a cryptic access-denied error. Delete the old object, or pick a different -NewName.

Broken secure channel

If a server sits off the network for months, its machine password desyncs. Symptom: domain users can't log in even though the server is still "joined". Fix:

Test-ComputerSecureChannel -Verbose
Test-ComputerSecureChannel -Repair -Credential corp\domainadmin

Wrong OU after join

Forgot -OUPath? The object is sitting in CN=Computers. Move it in ADUC or via PowerShell:

Get-ADComputer web05 | Move-ADObject -TargetPath "OU=Servers,DC=corp,DC=local"

Then gpupdate /force on the server to pull GPOs from the new OU.

DNS registration didn't happen

Forward record works, reverse doesn't, or vice versa. Force it:

ipconfig /registerdns

If the DNS zone doesn't allow dynamic updates you'll need to create the record by hand on the DNS server.

Name longer than 15 characters

NetBIOS still matters. Names over 15 characters get truncated and cause duplicate-name conflicts. Just pick shorter names — your future self will thank you.

Next steps

Once the server is on the domain, the rest of the setup is standard. If you haven't done baseline hardening yet, do that first: Windows Server initial setup checklist. And if you want RDP from a domain account instead of local admin, see Enable RDP on Windows Server.

Domain-join is the kind of task that's one command when everything's right and a half-day debugging session when something's wrong. Fix DNS, fix time, then run the command.


Related posts