Time Sync and Virtual Domain Controllers

UPDATE [2019/04/30]:  It appears that these recommendations have changed.  See this new post.

This is a brief guide on how to set up the time services on a Windows Server running under Hyper-V, specifically Active Directory servers.

Before I get into the details, I will lay out all the commands first, then go into an explanation below.

This will get your time service back to default if you monkey around with it:

Stop-Service W32Time
w32tm /unregister
w32tm /register
Start-Service W32Time

This is the set of commands for Non-PDC Emulator virtual DCs:

Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider -Name "Enabled" -Value 0
w32tm /config /syncfromflags:DOMHIER /update
Restart-Service W32Time
w32tm /resync /force

This is the set of commands for a PDC Emulator virtual DC:

Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider -Name "Enabled" -Value 0 
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\w32time\Parameters -Name Type -Value "NTP"
w32tm /config /manualpeerlist:"primary.example.org,0x9 backup.example.org,0xa" /syncfromflags:manual /reliable:yes /update
Restart-Service W32Time
w32tm /resync /force
w32tm /query /source

Now that you’ve probably copied and pasted that, here’s what the commands actually do.

The /unregister and /reregister flags for w32tm will cause it to remove itself as a service and re-add itself with defaults, like it was out of the box.

Setting the VMICTimeProvider to disabled prevents the Hyper-V Time Synchronization from monkeying with the local clock, and uses it solely for resume and boot time setting.

The non PDCE domain controllers should sync from the domain hierarchy instead of the local hypervisor.

The PDCE domain controller needs to sync from an external source.  Segal’s Law states that:

“A man with a watch knows what time it is. A man with two watches is never sure.”

As such we want to make sure the PDC has a primary clock source and a backup, not two sources that it swaps between.  the 0x9 flag specifies that we are a client and want to use the special sync interval.  The 0xA flag specifies that we are a client, want to use the special sync interval, and only use this source when no other is available.  We’re also specifying to sync from manually defined peers, and that we’re using a reliable time source.

Once we’ve made these settings we need to restart the W32Time service so it can pull in the new settings from the registry.

To speed up the time it takes to complete the first poll, we use the /resync /force flags.

As a sanity check, we use the /query /source to verify that all our changes have applied successfully.  We can also use w32tm /stripchart /computer:primary.example.org to verify that we’re syncing well with our clock source.

Note: These commands were tested with Windows Server 2016, but should also work with 2012R2.