WSL2 REST API Error due to WSL2 clock out of sync with Windows clock

clock, windows-subsystem-for-linux, windows-task-scheduler, wsl-2

Solution

UPDATE: as mentioned by drkvogel, the Clock Sync fix was released in WSL2 kernel version 5.10.16.3, however, you should install the Windows Store version of WSL:

# powershell install by id
winget install 9P9TQF7MRM4R

# powershell install by name
winget install 'Windows Subsystem for Linux'

At time of writing, this GitHub Issue was open for the bug.

The workaround I chose for my situation (single distro in WSL2) is to use Windows Task Scheduler to run `hwclock` in `WSL` whenever Windows resyncs hardware clock.

Windows: Open PowerShell as Administrator

schtasks /create /tn WSLClockSync /tr "wsl.exe sudo hwclock -s" /sc onevent /ec system /mo "*[System[Provider[@Name='Microsoft-Windows-Kernel-General'] and (EventID=1)]]"
Set-ScheduledTask WSLClockSync -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries)

WSL2: Run `sudo visudo` and add `hwclock` to sudoers to skip password prompt

# bottom of my file looks like this
...
...
#includedir /etc/sudoers.d
<username> ALL=(ALL) NOPASSWD:/usr/sbin/hwclock, /usr/bin/apt update, /usr/bin/apt upgrade

Results

See image for how to get Event XPath from Windows Event filtering. Use as provided to let task scheduler auto-display scheduled triggers.

Here is a batch script that does this process automatically, for each registered distro:

@echo off
rem this is a programmatic reminder of how to set up wsl clock sync
rem to prevent clock drift after sleep etc
rem see https://stackoverflow.com/a/65086857/120398 and https://github.com/microsoft/WSL/issues/5324

set WSL_UTF8=1
setlocal EnableDelayedExpansion
for /F "tokens=* delims=" %%D in ('wsl --list --quiet') DO (
    set hwclock_count=0
    for /f "tokens=* delims=" %%C in ('wsl -d %%D bash -c "grep -c hwclock /etc/sudoers.d/hwclock 2>/dev/null"') DO set hwclock_count=%%C
    if !hwclock_count! neq 1 (
        echo Setting up sudo permissions for hwclock on distro %%D - will prompt for password...
        wsl -d %%D sudo bash -c "echo -e '\x25adm ALL=(ALL)  NOPASSWD:/usr/sbin/hwclock -s' > /etc/sudoers.d/hwclock"
    ) else echo hwclock permissions already set up with !hwclock_count! - not changing...
    echo Testing resetting the clock - shouldn't prompt for password...
    wsl -d %%D sudo /usr/sbin/hwclock -s
    set syncname="WSLClockSync%%D"
    echo Creating scheduled task %syncname%...
    schtasks /create /f /tn "%syncname%" /tr "wsl.exe sudo hwclock -s" /sc onevent /ec system /mo "*[System[Provider[@Name='Microsoft-Windows-Kernel-General'] and (EventID=1)]]"
    echo Scheduling %syncname% to run even when on batteries...
    powershell -command "& {Set-ScheduledTask %syncname% -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries)}"
    echo Done!
)

Problem

WSL2 clock goes out of sync after resuming from sleep/hibernate. A workaround was shared on GitHub `sudo hwclock -s` to resync clock in WSL, but you have to do this every time you resume from sleep/hibernate.

Original source