How To

Configure NTP Server on Windows Server 2025 / 2022 (w32tm Guide)

A fresh Windows Server answers nobody on UDP 123, even though w32time is running and the clock looks fine. Most guides that show how to configure NTP server Windows Server roles stop at two registry values, and then you find out from a Linux box or a stray 0x800705B4 that the firewall, the domain hierarchy or the client itself had other plans.

Original content from computingforgeeks.com - post 39655

We built the whole chain in the homelab: a Windows Server 2025 box serving NTP to the LAN, the same box promoted to the PDC emulator of a homelab.lan domain and pointed at pool.ntp.org, a Windows Server 2022 member following it over NT5DS, and a Debian 13 box running chrony as the Linux client. You get the w32tm /config /manualpeerlist commands, AnnounceFlags, the firewall rule, a Group Policy method, and real w32tm /query /status and /stripchart output from both server versions. I ran through all of it on Windows Server 2025 and 2022 in November 2026, and it works end to end; I rechecked the steps and the links below before adding the client guide to this chain.

Which Windows Time role do you need?

Windows Time (the w32time service) does two different jobs depending on where the server sits. A workgroup or standalone server is a plain NTP client of time.windows.com until you tell it otherwise, and it only serves time once you enable the NtpServer provider. In an Active Directory domain the hierarchy is fixed: members sync from a domain controller, domain controllers sync from the PDC emulator, and the PDC emulator of the forest root is the only machine that should talk to an outside source.

That gives you two setups, and this guide covers both:

  • Standalone NTP server for LAN devices: steps 1 to 4
  • Domain time source on the PDC emulator: steps 5 to 7
  • Checks for either one: step 8 and the errors section

The sketch below is the lab as it ended up. DC01 is the only box with an arrow leaving the LAN, and the Debian client and the 2022 member both lean on it over UDP 123. The note on the right is the snag that cost us the most head scratching, and it gets its own fix further down.

Windows Server NTP time hierarchy diagram: PDC emulator DC01 syncs from pool.ntp.org, member server and chrony client sync from DC01 over UDP 123

The defaults are not the same in each role, and that is where most “it does not sync” threads start. We read these values from w32tm /query /configuration on each box in the lab:

SettingStandalone (2025 and 2022)PDC emulator (2025)Domain member (2022)
TypeNTPNT5DSNT5DS
NtpServer provider Enabled010
AnnounceFlags101010
Default peertime.windows.com,0x8none (Local CMOS Clock)domain hierarchy
MaxPos/NegPhaseCorrection54000 s (2025)172800 s4294967295
UtilizeSslTimeDatanot read01

The last row is the version difference Microsoft documents for Windows Time. We read it on the 2025 DC and the 2022 member: Secure Time Seeding (UtilizeSslTimeData) is off on Server 2025 and on for Server 2022, which matches the Windows Time settings reference from Microsoft. Every w32tm command in this guide ran unchanged on both, so the 2022 steps are the same as the 2025 ones.

1. Check the Windows Time defaults first

Before you change anything, look at what your box is doing now, because a GPO or an old script you forgot about may already own these values. Open PowerShell as Administrator and filter the configuration down to the lines that matter:

w32tm /query /configuration | Select-String 'AnnounceFlags|PollInterval|Type:|NtpServer|Enabled'

On our untouched Server 2025 box the NtpServer provider shows Enabled: 0, so the machine is a client only. Every value ends in (Local), which means it comes from the registry and not from Group Policy. If you see (Policy) here instead, the local commands below will not stick until you change the GPO. We also checked the firewall for any built-in NTP rule:

w32tm query configuration defaults on Windows Server 2025 showing AnnounceFlags 10 and NtpServer Enabled 0

The only matches are the two ICMPv6 “Time Exceeded” rules, which have nothing to do with NTP. There is no inbound UDP 123 rule on a default install, so step 3 is not optional. The Server 2022 clone printed exactly the same values.

2. Configure NTP Server on Windows Server 2025

You need three changes to turn the client into a server, and the order matters:

  1. Give it upstream peers with w32tm /config
  2. Enable the NtpServer provider in the registry
  3. Set AnnounceFlags so it advertises itself as reliable

The peers come first, because a server with no good upstream will happily hand your clients its own drifting clock. We used the public NTP pool with the 0x8 flag, which tells w32time to talk to each peer in client mode:

w32tm /config /manualpeerlist:"0.pool.ntp.org,0x8 1.pool.ntp.org,0x8 2.pool.ntp.org,0x8" /syncfromflags:manual /update

The peer list is space separated inside one pair of quotes. The flags after each comma are a bitmask: 0x1 polls at the fixed SpecialPollInterval, 0x2 marks a fallback peer, 0x4 is symmetric active mode and 0x8 is client mode. Without 0x1, the poll interval floats between MinPollInterval and MaxPollInterval, which on this box was 6 and 10 (64 to 1,024 seconds).

Next, enable the NtpServer provider and set AnnounceFlags to 5. The value 5 is 0x1 (always a time server) plus 0x4 (always a reliable time server), so the box advertises itself without waiting to decide whether it qualifies:

Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer' -Name Enabled -Value 1
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\Config' -Name AnnounceFlags -Value 5

The simplest way to apply registry edits to w32time is a service restart. Restart it, then force a fresh lookup of the peers so you do not have to wait for the next poll.

Restart-Service w32time
w32tm /resync /rediscover

Now ask the service what it is actually synced to. If the setup worked, you see one of your pool peers as the source and a stratum one higher than that peer.

w32tm /query /status

Our server came up at stratum 3 from 0.pool.ntp.org on the first resync. Note the 7.77 second root dispersion in that output. It is normal for w32time right after a sync, it shrinks over the next few minutes, and it matters a lot to Linux clients (step 4 shows why):

Configure NTP server on Windows Server 2025 with w32tm config, AnnounceFlags 5 and w32tm query status output

Two more checks tell you whether the server side is alive. w32tm /query /peers lists every configured peer and its state, and Get-NetUDPEndpoint proves something is listening on port 123:

w32tm /query /peers
Get-NetUDPEndpoint -LocalPort 123 | select LocalAddress,LocalPort,OwningProcess

Only 0.pool.ntp.org went Active. The other two sat in Pending with about 895 seconds remaining, and the System log explained it with event 135: “unable to set a manual peer … because of duplicate error”, error 0x800706E0. The pool names resolved to time sources w32time already had, so it parks them and retries in 15 minutes. One active peer is enough to serve time. It simply means you have less redundancy than the peer list suggests. The UDP endpoint shows w32time bound on 0.0.0.0:123 and :::123:

w32tm query peers output with one active pool.ntp.org peer and w32time listening on UDP 123

Listening is not the same as reachable, though. At this point a client on the LAN still got nothing back from the server, which is what the next step fixes.

3. Open UDP 123 in Windows Defender Firewall

Windows Defender Firewall drops inbound NTP by default, and the failure is silent on the server side. We tested it in order. With the NtpServer provider off, a w32tm /stripchart from the Server 2022 box returned error: 0x800705B4 on every sample, and after enabling the provider it still returned the same timeout until the rule below went in. Create the inbound rule for all profiles.

New-NetFirewallRule -DisplayName "NTP Server (UDP 123)" -Direction Inbound -Protocol UDP -LocalPort 123 -Action Allow -Profile Any

Domain controllers are the exception, because after promotion DC01 also had an enabled rule named W32Time-NTP-UDP-In that the AD DS role adds, so a DC does not need this step. If your servers live on a domain network only, narrow -Profile Any to -Profile Domain, and add -RemoteAddress 10.0.1.0/24 if you want to keep the service off other subnets. Confirm the rule exists and is enabled.

Get-NetFirewallRule -DisplayName "NTP Server (UDP 123)" | ft DisplayName,Enabled,Direction,Action,Profile

Then test from a Windows client on the LAN. w32tm /stripchart sends real NTP packets from an ephemeral port, so it works even from a box that runs its own time service, and it prints the round trip delay (d:) and the offset (o:) for each sample:

w32tm /stripchart /computer:10.0.1.10 /samples:5

The 2022 client got answers with sub-millisecond delay and an offset of 31 to 34 milliseconds, which is how far its own clock (still synced to time.windows.com at that point) sat from DC01. Stripchart only measures, it does not correct anything. The asterisk in the middle of the bar means the offset is close to zero on the scale of the chart:

Windows Defender Firewall inbound UDP 123 rule and w32tm stripchart from a Windows Server 2022 client

To make a Windows workgroup machine actually use the new server, point its peer list at it and resync. We did this on the 2022 box:

w32tm /config /manualpeerlist:"10.0.1.10,0x8" /syncfromflags:manual /update
Restart-Service w32time
w32tm /resync /rediscover
w32tm /query /status

We got stratum 4 back with Source: 10.0.1.10,0x8, one level below DC01. That client also reported 11.56 seconds of root dispersion, which Windows accepts without complaint, unlike chrony in the next step. Domain members skip this entirely, as step 6 shows. If you manage these servers from Linux or a jump box, the same checks run fine over PowerShell remoting over SSH, which saves an RDP session per server.

4. Sync a Linux chrony client from the Windows NTP server

A Windows client is forgiving. chrony is not, and it is the client most Linux distributions ship, so it is the better test of whether your Windows server is usable. On the Debian 13 box we added the Windows server as a source and commented out the Debian pool line, so chrony had nothing else to fall back on:

echo "server 10.0.1.10 iburst" | sudo tee /etc/chrony/sources.d/windows-ntp.sources
sudo sed -i 's/^pool 2.debian.pool.ntp.org iburst/#pool 2.debian.pool.ntp.org iburst/' /etc/chrony/chrony.conf
sudo systemctl restart chrony

On Rocky Linux or AlmaLinux the chrony config lives in /etc/chrony.conf, so add the same server line there. Give chrony 20 seconds, then list the sources:

chronyc sources
chronyc tracking

This is where we got stuck the first time. chrony reached the server (reach register 17, offset +68 microseconds), yet it flagged it ^?, unusable, with an error bound of plus or minus 7,802 ms, and chronyc tracking said “Not synchronised”. The reason is that root dispersion. chrony refuses a source whose root distance is above its maxdistance of 3 seconds, and w32time was advertising 7.77 seconds of dispersion just after its own sync:

chrony on Debian 13 syncing from a Windows Server NTP server, unusable at first then selected

Doing nothing fixed it. About three minutes after the Windows server synced, the dispersion it advertised had dropped enough for chrony to accept it (the root dispersion chrony itself reported was 1.76 seconds), chrony switched the mark to ^* and settled at stratum 4 with a last offset of 0.26 ms. So if a Linux client refuses your new Windows NTP server, wait out the first few minutes before you change anything on either side. If the server sits behind a long or busy link and the dispersion never drops below 3 seconds, maxdistance 16 in the chrony config makes chrony accept it, at the cost of trusting a less certain source.

5. Configure the PDC emulator time source

In a domain you do not pick the NTP server, the domain does. The PDC emulator of the forest root is the top of the tree, so it is the one machine you point at external peers, and every other DC and member follows it. We reset w32time on DC01 to its defaults, promoted it as the first DC of homelab.lan (the AD DS installation guide walks through that part), and confirmed it holds the PDC role:

netdom query fsmo

Then we looked at the time configuration the promotion left behind. This answers a question other guides argue about. Promotion does turn the NtpServer provider on by itself (Enabled: 1), and it switches Type to NT5DS. What it does not do is give the PDC anything to sync from:

New PDC emulator on Windows Server 2025 serving Local CMOS Clock as stratum 1 with NtpServer enabled

Read that status carefully, because it looks healthy to you at a glance. Stratum 1, “primary reference”, reference ID LOCL and source “Local CMOS Clock” mean the PDC is serving its own hardware clock as if it were an atomic reference. Event 12 in the System log says the same thing in words. Our Debian client, still pointed at DC01, kept it selected and measured it 1.6 seconds away from its own clock a minute later, because nothing in the packet told it the time was bad. Point the PDC at real peers and mark it reliable.

w32tm /config /manualpeerlist:"0.pool.ntp.org,0x8 1.pool.ntp.org,0x8 2.pool.ntp.org,0x8" /syncfromflags:manual /reliable:yes /update

The /reliable:yes switch is only meaningful on a domain controller, and it is what set AnnounceFlags to 5 here, so there is no registry edit on the PDC. The Microsoft authoritative time server article suggests AnnounceFlags 0xA (10) instead of 5 if the link from the PDC to its upstream is unreliable, because clients can fail to resync with a 0x5 server after an upstream outage. Restart the service and resync.

net stop w32time
net start w32time
w32tm /resync /rediscover
w32tm /query /status

The PDC dropped from fake stratum 1 to a real stratum 3 from the pool, and /query /configuration now shows Type NTP, AnnounceFlags 5 and the three peers. If your network blocks outbound NTP to the internet, use an internal stratum 1 or 2 appliance in the peer list instead; time.windows.com,0x8 also works if outbound UDP 123 to Microsoft is allowed:

Configure PDC emulator time source with w32tm manualpeerlist and reliable yes, synced to pool.ntp.org

Remember that this config follows the server, not the role. If you move the PDC emulator role to another DC, run the same command on the new PDC, then put the old one back on the domain hierarchy and drop its reliable flag. Without /reliable:no the old PDC keeps AnnounceFlags 5, and you end up with two DCs that both advertise themselves as the authority:

w32tm /config /syncfromflags:domhier /reliable:no /update
net stop w32time
net start w32time

We ran that on DC01 and AnnounceFlags went back to 10, then restored the pool peers with the earlier command and it returned to 5.

6. Let member servers follow NT5DS

Your members need no configuration at all. Joining the domain switched our Server 2022 box from NTP to NT5DS and pointed it at DC01 without a single w32tm command. We reset its time service to defaults first, so this is the behaviour of a clean join:

w32tm /query /source
w32tm /query /configuration | Select-String 'AnnounceFlags|PollInterval|Type:|NtpServer|Enabled'

The source reads DC01.homelab.lan, Type is NT5DS and the NtpServer provider on the member stays off. The stripchart against the DC by name showed the two about 0.62 seconds apart, because the PDC itself had only just been corrected and both clocks were still slewing:

Windows Server 2022 domain member using NT5DS with DC01 as its time source

If someone has hard coded a member to an outside server (old guides told people to run /manualpeerlist on every box), this puts it back on the domain hierarchy. If the box you are fixing is a standalone server that should pull time from this one instead, the follow-up guide shows how to configure Windows Server as an NTP client with the same w32tm commands. We tested the reset on the 2022 member after pointing it at time.windows.com:

w32tm /config /syncfromflags:domhier /update
net stop w32time
net start w32time
w32tm /resync /rediscover

After the restart w32tm /query /source returned DC01.homelab.lan again and Type was back to NT5DS. Kerberos allows five minutes of skew by default, so a member that drifts on its own clock fails your logons long before anyone notices the time on the taskbar.

7. Configure NTP through Group Policy

A GPO is the cleaner way to set the peers on the PDC, because the setting lives in Active Directory and survives a rebuild of the server. It only follows the PDC role if you scope it that way, which we come back to at the end of this step. The policies live under Computer Configuration, Administrative Templates, System, Windows Time Service, Time Providers. Three of them do the work:

  • Configure Windows NTP Client: NtpServer and Type
  • Enable Windows NTP Client: turns the client on
  • Enable Windows NTP Server: turns the server on

You can set them by hand in the Group Policy Management Editor (our Group Policy setup guide for Windows Server 2025 covers creating and linking GPOs in the console). We built the same GPO from PowerShell on DC01, writing the values those three policies store under HKLM\Software\Policies\Microsoft\W32Time:

New-GPO -Name "PDC Time Source" -Comment "PDC emulator syncs from pool.ntp.org"
$p = 'HKLM\Software\Policies\Microsoft\W32Time'
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\Parameters" -ValueName NtpServer -Type String -Value "0.pool.ntp.org,0x8 1.pool.ntp.org,0x8"
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\Parameters" -ValueName Type -Type String -Value "NTP"
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName CrossSiteSyncFlags -Type DWord -Value 2
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName ResolvePeerBackoffMinutes -Type DWord -Value 15
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName ResolvePeerBackoffMaxTimes -Type DWord -Value 7
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName SpecialPollInterval -Type DWord -Value 3600
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName EventLogFlags -Type DWord -Value 0
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpClient" -ValueName Enabled -Type DWord -Value 1
Set-GPRegistryValue -Name "PDC Time Source" -Key "$p\TimeProviders\NtpServer" -ValueName Enabled -Type DWord -Value 1

Link it to the Domain Controllers OU, then read the GPO report back to confirm GPMC sees these values as the named policies:

New-GPLink -Name "PDC Time Source" -Target "OU=Domain Controllers,DC=homelab,DC=lan"
[xml]$r = Get-GPOReport -Name "PDC Time Source" -ReportType Xml
$r.GPO.Computer.ExtensionData.Extension.Policy | select Name,State | ft -auto

All three show up as named policies in the Enabled state. After gpupdate /target:computer /force, the NtpServer and Type lines in w32tm /query /configuration carry (Policy) instead of (Local), and the PDC kept syncing from 0.pool.ntp.org:

Group Policy PDC Time Source GPO with Configure Windows NTP Client enabled and w32tm showing Policy values

One thing that looks wrong but is not: the policy key on disk held SpecialPollInterval 3600, yet w32tm kept reporting 1024 (Policy) after a service restart. Microsoft documents that SpecialPollInterval is held inside MinPollInterval and MaxPollInterval, and MaxPollInterval 10 is 1,024 seconds, so the 3600 gets clamped. With 0x8 peers the value is not used anyway, since only 0x1 peers poll on the special interval. If you need an hourly fixed poll, raise MaxPollInterval as well.

Our lab had a single DC, so linking to the Domain Controllers OU was enough. With several DCs, every one of them would pick up external peers from this GPO, because GPO values overwrite the local W32Time settings on every machine the GPO applies to. The usual answer is a WMI filter on the GPO, SELECT * FROM Win32_ComputerSystem WHERE DomainRole = 5, so only the current PDC emulator applies it and the setting moves with the role. Our PDC did return DomainRole 5, but we did not build that filter in this lab, so test it on your own domain before you rely on it. Note that this GPO does not set AnnounceFlags, and when a former PDC stops matching the filter, Windows removes the policy values and w32time falls back to the local registry. If that server ever had the manual /reliable:yes config from step 5, it still needs the /reliable:no reset. While you are in GPMC, the Windows Server 2025 security baseline is worth a look too, because it touches other policies on the same OU.

8. Verify with w32tm /monitor and /stripchart

Once the hierarchy is in place, two commands on the PDC tell you whether the whole domain is sane. w32tm /monitor walks every DC in your domain and reports its offset and upstream reference. A stripchart against your upstream shows you how far the PDC itself is from the outside world.

w32tm /monitor /domain:homelab.lan
w32tm /stripchart /computer:0.pool.ntp.org /samples:4 /dataonly

The monitor marked DC01 as *** PDC *** at stratum 3 with a reference from the pool. The stripchart is the more interesting part, because the PDC was still 0.78 seconds away from the pool and closing the gap by about 15 ms every two seconds. That is w32time slewing the clock gently instead of stepping it, because the offset was under MaxAllowedPhaseOffset (300 seconds on this DC). In other words, a fresh sync is not an instant correction, and readings over the first few minutes will look worse than the steady state:

w32tm monitor domain output for the PDC and w32tm stripchart offset against pool.ntp.org

If you also run DHCP or other domain services on these DCs, time drift shows up there as well, for example as failed lease updates between DHCP failover partners, so a healthy /monitor is worth checking after any DC change.

What broke in the lab

Every error below came up while we built this lab, with the exact text Windows printed. Each one has a different cause, so match the message you see before you start changing settings.

w32tm /stripchart returns “error: 0x800705B4”

0x800705B4 is a timeout: the client sent an NTP request and got nothing back. We reproduced it twice, once with the NtpServer provider disabled on the target and once with the provider enabled but no inbound UDP 123 rule. Check Enabled: 1 under the NtpServer provider in /query /configuration, then the firewall rule from step 3, then any network firewall between the two hosts.

Both errors from our runs are in this capture, the timeout first and the empty resync below it:

w32tm error 0x800705B4 and The computer did not resync because no time data was available

The second half of that capture is the next error on this list.

“The computer did not resync because no time data was available”

This one means your w32time has no usable peer at all. We triggered it on the 2022 box with a peer name that does not resolve: w32tm /resync printed the message, /query /status fell back to “Local CMOS Clock” with leap indicator 3 (not synchronized), and the System log recorded event 134 with “No such host is known. (0x80072AF9)”. Note that w32tm still exits with code 0 here, so a script that only checks the exit code will think the resync worked. Fix the peer name or DNS, then restart the service and run w32tm /resync /rediscover.

Event 135: “duplicate error” with 0x800706E0

Seen on DC01 every time we listed three pool names. w32time resolved them, found time sources it was already using, and parked the extra peers in Pending for 15 minutes, doubling the retry each time. It is a warning, not a failure, as long as one peer stays Active. The Microsoft registry guidance says each peer name must be unique, and the event shows that unique names are not enough when they resolve to the same servers. If you want real redundancy, list peers run by different operators rather than three names from the same pool.

chrony shows the Windows server as ^? (unusable)

This is the root dispersion problem from step 4. A Windows server that has just synced advertises several seconds of dispersion, and chrony rejects any source whose root distance passes 3 seconds. In our lab it cleared on its own about three minutes after the Windows server synced. Check the advertised value with sudo chronyc ntpdata 10.0.1.10 before you reach for maxdistance.

Windows time service not syncing in a new domain

If your whole domain is off by the same amount, look at the PDC first. A freshly promoted forest root PDC with no peers reports stratum 1 from “Local CMOS Clock” and logs event 12, and every DC, member and Linux client below it inherits that clock. Step 5 is the fix. Do you run a Samba domain instead? The same rule applies: the DC holding the PDC role is the one that needs an outside source, as in our Samba AD domain controller guide.

Keep reading

Create a Bootable Windows 11 USB and Install Windows 11 Windows Create a Bootable Windows 11 USB and Install Windows 11 Set Up a Samba Share on Windows 11 and Access It from Linux Networking Set Up a Samba Share on Windows 11 and Access It from Linux Windows 11 Installation on KVM with Virt-Manager KVM Windows 11 Installation on KVM with Virt-Manager Windows 11 Keyboard Shortcuts Cheat Sheet (Printable PDF) Cheat Sheets Windows 11 Keyboard Shortcuts Cheat Sheet (Printable PDF) Configure Windows Server 2025 / 2022 as an NTP Client Windows Configure Windows Server 2025 / 2022 as an NTP Client Create Disk Partitions in Windows Using diskpart Windows Create Disk Partitions in Windows Using diskpart

3 thoughts on “Configure NTP Server on Windows Server 2025 / 2022 (w32tm Guide)”

  1. I see a blaring securit hole in the firewall. Instead of leaving just an open UDP port for anything to connect to it, lock it down to just the svchost.exe and the W32Time Service!

    replace -Program Any with -Program “%systemroot%\system32\svchost.exe” -Service W32Time

    Reply
  2. Great article Kibet, I have a question concerning the Announceflag setting:

    Set-ItemProperty -Path “HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Config” -Name “AnnounceFlags” -Value 5

    Why 5? It’s not listed as an available AnnounceFlags value.

    Reply

Leave a Comment

Press ESC to close