Cuando el tiempo en WSL2 deriva, nada falla amablemente. Los git fetch fallan con errores TLS. Los gestores de paquetes dicen que la metadata del repositorio es “del futuro”. Los registros se convierten en ficción. Y tu línea temporal de incidentes—ya frágil—se transforma en danza interpretativa.
Lo peor: parece aleatorio. Cierras el portátil, vas a una reunión, vuelves y de repente tu entorno Linux cree que es el martes pasado. Arreglémoslo como adultos: mide primero, sincroniza el reloj correcto y deja de parchear la deriva con hacks que hacen gritar a las herramientas de seguridad.
Cómo se ve la deriva de tiempo en WSL2 (y por qué te debe importar)
El desfase del reloj es uno de esos problemas de “solo unos minutos” que pueden parar una canalización entera. En operaciones de producción, el tiempo es un contrato de API: validez de certificados TLS, tickets Kerberos, caducidad de tokens OAuth, correlación de logs, spans de trazado distribuido, invalidación de cache, reproducibilidad de builds. Rompe el tiempo y rompes la confianza.
WSL2 añade un giro: es una VM Linux que corre bajo la arquitectura de virtualización de Hyper-V, con su propio kernel. Eso significa que el tiempo puede derivar a nivel de guest aun cuando Windows parece correcto. Las transiciones de suspensión/hibernación y la carga del host pueden agravar el problema. Algunos usuarios obtienen una instancia WSL2 que reanuda con un reloj obsoleto; otros ven deriva periódica bajo presión sostenida de CPU o cuando el guest no recibe planificación con frecuencia.
Dos realidades rápidas:
- Que el reloj de Windows esté correcto no garantiza que el reloj de WSL2 lo esté.
- Arreglar la hora “simplemente poniendo la fecha” dentro del guest es un parche temporal. Incluso puede crear problemas de seguridad al enmascarar la falta de una fuente de tiempo fiable.
Broma #1: La deriva del tiempo es como la deuda técnica: la ignoras hasta que te cobra intereses durante un incidente.
Datos interesantes y contexto histórico (serás más listo al final)
- NTP es anterior a muchos sistemas modernos. El Network Time Protocol existe desde principios de los años 80 y sigue siendo la columna vertebral de la sincronización horaria en internet.
- Sincronizar el reloj no es solo “poner la hora”. Las implementaciones modernas disciplinan el reloj gradualmente para evitar romper aplicaciones sensibles al tiempo.
- El tiempo en virtualización siempre ha sido extraño. Las primeras plataformas de VM luchaban con interrupciones del temporizador y planificación, llevando a guests que corrían “rápido” o “lento” bajo carga.
- Monótono vs reloj de pared importa. Linux ofrece un reloj monotónico para medir duraciones; el reloj de pared puede saltar debido a ajustes NTP o cambios manuales.
- Kerberos es notoriamente intolerante al desfase. Las tolerancias típicas son de minutos, no horas. Más allá de eso, la autenticación falla de maneras que parecen “credenciales rotas”.
- TLS depende del tiempo para seguridad básica. Las ventanas de validez de certificados son una comprobación simple que evita replays y usos indebidos. Un tiempo incorrecto hace que sistemas seguros parezcan rotos.
- Los segundos intercalares son reales. Son raros, pero han causado incidentes en producción cuando los sistemas discrepan en cómo manejarlos.
- Windows y Linux difieren en supuestos sobre el tiempo. Históricamente, los sistemas de arranque dual discutían si el reloj de hardware está en hora local o en UTC; esa pelea enseñó a una generación a respetar la cronometraje.
Cómo WSL2 mantiene el tiempo: las piezas móviles
WSL2 es una VM ligera con un kernel Linux real. Comparte mucho con invitados Hyper-V: temporizadores virtuales, un bus de virtualización y mecanismos de integración que permiten que el guest coopere con el host. Pero “ligero” no significa “inmune a problemas de tiempo en VM”. Solo significa que los modos de fallo son más sigilosos.
Tres relojes que debes mantener distintos
- Reloj de pared del host Windows: lo que muestra tu bandeja del sistema; generalmente disciplinado por el servicio Windows Time (w32time) o por la hora de dominio.
- Reloj de pared del guest WSL2: lo que imprime
dateen Linux; puede derivar o reanudar obsoleto tras suspensión. - Relojes monotónicos: usados para medir intervalos; raramente son tu problema en “TLS no válido aún”, pero relevantes si ves timeouts extraños o comportamiento de planificación.
Por qué la suspensión/hibernación suele ser la culpable
Cuando un portátil entra en suspensión, la ejecución de CPU se detiene. Al despertarse, el host actualiza su hora, pero la VM guest puede no recibir inmediatamente un evento de sincronización limpio. Si la VM está pausada o su contabilización del tiempo depende de una fuente de reloj virtual que no se corrige rápidamente, puedes reanudar con un reloj atrasado. Cuanto más suspendes, más derivación. No es místico; es reanudación de estado.
Por qué “simplemente ejecutar ntpdate” no es el instinto correcto
Saltos puntuales de tiempo pueden romper procesos en ejecución. Bases de datos, herramientas de construcción y cualquier cosa que dependa de marcas temporales pueden comportarse mal. El enfoque correcto es habilitar un servicio de tiempo que discipline el reloj (correcciones graduales) y arreglar la causa raíz (resincronizar al reanudar, asegurar integración WSL2, garantizar la estabilidad del tiempo en el host).
Idea parafraseada (no literal) de Richard Cook, investigador de fiabilidad: Los fallos raramente son de un solo punto; son el resultado de supuestos normales que se alinean mal.
Guía rápida de diagnóstico
Este es el flujo de “estás de guardia, las cosas están fallando y necesitas saber qué ocurre en cinco minutos”. No lo sobrepienses.
Primero: confirma el desfase y su dirección
- Comprueba la hora de Windows frente a una referencia externa (o al menos confirma que Windows no está muy desfasado).
- Comprueba la hora de WSL2 dentro de la distribución.
- Calcula el delta. ¿Segundos? ¿Minutos? ¿Horas? Esa escala cambia la causa más probable.
Segundo: decide si el guest puede alcanzar una fuente de tiempo
- Verifica la resolución DNS y la accesibilidad saliente UDP/123 (o al menos acceso HTTPS a proxies de tiempo corporativos si ese es tu entorno).
- Comprueba si existe un demonio de tiempo y si está en ejecución (systemd-timesyncd, chrony).
Tercero: aisla host vs guest vs política de red
- Si Windows está mal: arregla la hora de Windows primero. El guest que monta sobre un host roto no es problema del guest.
- Si Windows está bien pero WSL2 está mal: arregla el mecanismo de sincronización de WSL2 y el comportamiento tras reanudar.
- Si ambos están bien a veces y mal tras suspensión: implementa resincronización al despertar y verifica actualizaciones de WSL/kernel.
- Si solo la red corporativa lo rompe: probablemente tengas NTP bloqueado y necesitas una fuente de tiempo permitida o un enfoque diferente.
Tareas prácticas: comandos, salidas, decisiones (12+)
Estas son comprobaciones prácticas que puedes ejecutar ahora mismo. Cada tarea incluye: comando, qué significa la salida típica y qué decisión tomar.
Task 1: Check WSL2 wall clock immediately
cr0x@server:~$ date -Is
2026-02-05T14:22:09+00:00
Significado: Hora de pared en formato ISO-8601 dentro de WSL2. Compárala con Windows o con una referencia conocida.
Decisión: Si está desfasada más de ~2 minutos, trátalo como un problema real. Si está desfasada por horas, sospecha reanudación tras suspensión o cambios manuales.
Task 2: Check time zone and whether it’s a “timezone confusion” not drift
cr0x@server:~$ timedatectl
Local time: Thu 2026-02-05 14:22:12 UTC
Universal time: Thu 2026-02-05 14:22:12 UTC
RTC time: Thu 2026-02-05 14:22:12
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: no
NTP service: inactive
RTC in local TZ: no
Significado: Si “Local time” coincide con lo esperado pero la “Time zone” es incorrecta, podrías estar viendo una confusión de huso horario. Si “System clock synchronized” es no y NTP está inactivo, el guest no está siendo disciplinado.
Decisión: Si NTP está inactivo, necesitas habilitar un servicio de tiempo (systemd-timesyncd o chrony). Si el huso horario es incorrecto, arréglalo por separado—no persigas una “deriva” que en realidad es un desplazamiento horario.
Task 3: Confirm systemd is actually running (WSL2 varies by config)
cr0x@server:~$ ps -p 1 -o comm=
systemd
Significado: Si PID 1 es systemd, puedes usar servicios systemd normalmente. Si es otra cosa (como init o bash), necesitarás un enfoque distinto (o habilitar systemd en WSL).
Decisión: Si systemd no es PID 1, decide si vas a habilitar systemd (recomendado para una experiencia Linux “real”) o ejecutar chrony manualmente.
Task 4: If systemd exists, check timesync service status
cr0x@server:~$ systemctl status systemd-timesyncd --no-pager
● systemd-timesyncd.service - Network Time Synchronization
Loaded: loaded (/lib/systemd/system/systemd-timesyncd.service; enabled)
Active: active (running) since Thu 2026-02-05 14:10:03 UTC; 12min ago
Docs: man:systemd-timesyncd.service(8)
Main PID: 319 (systemd-timesyn)
Status: "Synchronized to time server 10.0.0.53:123 (ntp.corp)"
Significado: “Synchronized” es lo que quieres. Si dice “No network connectivity” o “Timed out”, la ruta de red hacia NTP está bloqueada o mal configurada.
Decisión: Si está activo y sincronizado, la deriva puede estar relacionada con reanudación (necesita resincronización al despertar) o con la fuente de reloj. Si no está sincronizado, arregla la conectividad o la configuración del servidor NTP.
Task 5: Inspect the last sync and current offset (timesyncd)
cr0x@server:~$ timedatectl timesync-status
Server: 10.0.0.53 (ntp.corp)
Poll interval: 32min 0s (min: 32s; max 34min 8s)
Leap: normal
Version: 4
Stratum: 3
Reference: 3B4E2A91
Precision: 1us (-24)
Root distance: 18.525ms
Offset: +1.842ms
Delay: 2.913ms
Jitter: 0
Packet count: 109
Frequency: -12.345ppm
Significado: El offset en milisegundos es saludable. Root distance y stratum te dan una idea de la calidad. Offsets gigantes (segundos+) significan que tu guest es inestable o no está sincronizado.
Decisión: Si el offset es pequeño pero aún ves errores TLS, tu problema puede ser huso horario, DNS cacheado o la cadena de certificados—no necesariamente deriva de tiempo.
Task 6: If you’re using chrony, confirm sources and tracking
cr0x@server:~$ chronyc tracking
Reference ID : 0A000035 (10.0.0.53)
Stratum : 4
Ref time (UTC) : Thu Feb 05 14:22:24 2026
System time : 0.000001234 seconds fast of NTP time
Last offset : -0.000000321 seconds
RMS offset : 0.000012345 seconds
Frequency : 15.123 ppm slow
Residual freq : -0.001 ppm
Skew : 0.020 ppm
Root delay : 0.002911 seconds
Root dispersion : 0.000812 seconds
Update interval : 64.0 seconds
Leap status : Normal
Significado: “System time … fast/slow of NTP time” te indica tu error. Saludable es cercano a cero, frecuencia estable, estado de leap normal.
Decisión: Si chrony no muestra referencia o muestra offsets grandes, no te estás sincronizando realmente. Arregla la red o la configuración del servidor antes de culpar a WSL.
Task 7: Verify name resolution and basic connectivity (because NTP can fail quietly)
cr0x@server:~$ getent hosts ntp.corp
10.0.0.53 ntp.corp
Significado: DNS resuelve el nombre NTP. Si no lo hace, timesync fallará incluso si la red está bien.
Decisión: Si DNS falla, arregla la generación de resolv.conf en WSL2 o el acceso al DNS corporativo antes de tocar servicios de tiempo.
Task 8: Check UDP/123 reachability indirectly (no fancy tools required)
cr0x@server:~$ sudo timeout 3 bash -c 'cat < /dev/null > /dev/udp/10.0.0.53/123' && echo ok || echo blocked
ok
Significado: Esta es una comprobación burda: no prueba respuestas NTP, pero “blocked” sugiere problemas de ruteo/firewall/política.
Decisión: Si está bloqueado, deja de probar servidores NTP aleatorios; necesitas una ruta de tiempo aprobada por la empresa (o usar la sincronización proporcionada por el host).
Task 9: Look for suspend/resume patterns in dmesg
cr0x@server:~$ dmesg | tail -n 20
[ 812.345678] systemd[1]: Started Network Time Synchronization.
[ 5432.123456] PM: suspend entry (s2idle)
[ 5432.234567] Freezing user space processes
[ 5432.345678] PM: suspend exit
[ 5432.456789] systemd-timesyncd[319]: Network configuration changed, trying to establish connection.
Significado: Si ves marcadores de suspensión/reanudación y luego reinicio de sincronización, probablemente estés lidiando con tiempo obsoleto post-reanudación.
Decisión: Implementa un hook de resincronización post-reanudación (en contexto WSL: reinicia WSL o desencadena el reinicio del servicio de tiempo) en lugar de ajustar la hora manualmente.
Task 10: Confirm the guest is actually WSL2 and see version info
cr0x@server:~$ uname -a
Linux cr0x-wsl 5.15.146.1-microsoft-standard-WSL2 #1 SMP Fri Jan 10 18:20:00 UTC 2026 x86_64 GNU/Linux
Significado: La cadena del kernel incluye la marca Microsoft WSL2. La antigüedad del kernel importa; mejoras de timekeeping llegan en kernels más nuevos.
Decisión: Si tu kernel es antiguo, actualiza WSL. No depures comportamientos de timekeeping de 2020 si puedes instalar correcciones de 2026.
Task 11: Detect “time went backwards” symptoms in logs (a classic red flag)
cr0x@server:~$ journalctl -b -p warning --no-pager | grep -i time | tail -n 5
Feb 05 14:05:01 cr0x-wsl systemd[1]: Time has been changed
Feb 05 14:05:01 cr0x-wsl systemd[1]: Detected clock change. Skipping time warp.
Significado: Ocurrieron saltos de tiempo. No necesariamente fatales, pero explican builds inestables y errores de “aún no válido”.
Decisión: Si el tiempo salta con frecuencia, céntrate en disciplina estable (chrony) y hooks de reanudación, no en correcciones manuales.
Task 12: Reproduce the failure in a controlled way (TLS validity check)
cr0x@server:~$ curl -Iv https://example.internal 2>&1 | sed -n '1,15p'
* Trying 10.0.1.25:443...
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL certificate problem: certificate is not yet valid
* Closing connection 0
curl: (60) SSL certificate problem: certificate is not yet valid
Significado: “Not yet valid” suele indicar que el reloj del cliente está atrasado respecto al timestamp NotBefore del certificado. También puede ser un proxy que hace intercepción TLS con certificados nuevos. Pero el tiempo es el primer sospechoso.
Decisión: Compara date con la hora de Windows y con la ventana de validez del certificado (siguiente tarea). Si el desfase es real, arregla la hora antes de perseguir stores de certificados.
Task 13: Inspect certificate validity dates to prove it’s time, not “mystery TLS”
cr0x@server:~$ echo | openssl s_client -connect example.internal:443 -servername example.internal 2>/dev/null | openssl x509 -noout -dates
notBefore=Feb 5 14:10:00 2026 GMT
notAfter=May 6 14:10:00 2026 GMT
Significado: Si tu hora en WSL2 es anterior a notBefore, TLS falla exactamente como se mostró.
Decisión: Deja de discutir con TLS. Arregla el reloj.
Task 14: Quick, low-risk “kick” — restart WSL from Windows side
cr0x@server:~$ powershell.exe -NoProfile -Command "wsl --shutdown"
Significado: Esto apaga todas las instancias WSL. En el siguiente inicio, la VM arranca de nuevo y a menudo toma la hora correcta del host.
Decisión: Si esto lo soluciona consistentemente, la causa raíz es el comportamiento post-reanudación. Aun así quieres una solución duradera, pero ahora tienes un workaround seguro.
Task 15: Validate whether your time daemon is stepping the clock (dangerous) or slewing (preferred)
cr0x@server:~$ chronyc -n sourcestats | head
Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
10.0.0.53 7 4 256 +0.012 0.034 +0.000 0.001
Significado: Frecuencia estable y offsets pequeños indican disciplina por slew. Si ves correcciones violentas, puede que estés haciendo stepping a menudo, lo que rompe apps.
Decisión: Configura chrony para hacer step solo al arrancar y luego slew, a menos que tengas un caso especial.
Soluciones que funcionan (y por qué)
Hay tres niveles de arreglos: actualizar/habilitar la infraestructura, ejecutar un demonio de sincronización real y manejar suspensión/reanudación. Hazlos en ese orden. Evita “poner la hora en un cron” a menos que tu objetivo sea crear nuevos y excitantes modos de falla.
1) Mantén WSL y Windows con la hora saludable
Si la hora de Windows está mal, todo lo que depende de ella quedará en escena. Arregla primero la sincronización de Windows (las máquinas unidas a dominio deberían estar disciplinadas). En máquinas no unidas, asegúrate de que el servicio Windows Time está en ejecución y no está bloqueado por la política del VPN. Luego actualiza WSL para no quedarte con un comportamiento de kernel antiguo.
2) Habilita systemd en WSL (si puedes)
WSL moderno soporta systemd cuando está configurado. Tener systemd convierte la sincronización de tiempo en un problema Linux normal, lo cual es una bendición. Puedes ejecutar systemd-timesyncd (simple) o chrony (mejor en condiciones raras).
Si no puedes o no quieres habilitar systemd, aún puedes ejecutar chrony de forma más manual, pero perderás los ganchos de ciclo de vida de servicio que hacen esto fiable.
3) Prefiere chrony cuando la deriva es crónica
systemd-timesyncd es suficiente para muchos portátiles de desarrollo. Pero los patrones de deriva de WSL2—especialmente post-suspensión y bajo contención de CPU—suelen beneficiarse de la robustez de chrony y su mejor comportamiento de tracking/steering.
chrony también se adapta mejor a conectividad intermitente y grandes intervalos entre oportunidades de sincronización. Esa es básicamente la descripción del trabajo de un portátil VM.
4) Maneja la reanudación explícitamente
Si la deriva aparece tras suspensión/hibernación, quieres un disparador explícito de resincronización. Un enfoque limpio es reiniciar el demonio de tiempo (o incluso WSL) al reanudar. El hook “correcto” depende de si lo gestionas desde Windows (Programador de Tareas) o dentro de Linux (unidades y timers systemd). En una flota corporativa, la remediación desde Windows suele ser más fácil de distribuir.
Broma #2: Un portátil que despierta de la suspensión es básicamente un pequeño ejercicio de recuperación ante desastres—solo que con menos postmortems y más café.
Patrón de configuración de chrony que se comporta en el mundo real
En una red corporativa, a menudo tienes un servidor NTP interno. Úsalo. NTP público aleatorio desde dentro de un VPN restringido es cómo pasas un jueves explicando egress UDP a seguridad.
Ejemplo: instala y configura chrony (comandos difieren por distribución). Aquí hay una configuración con sabor Debian/Ubuntu:
cr0x@server:~$ sudo apt-get update
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Reading package lists... Done
Significado: Si esto falla con “Release file is not valid yet”, tu reloj está atrasado. Arregla la hora antes de continuar.
Decisión: Si update tuvo éxito, procede a instalar chrony.
cr0x@server:~$ sudo apt-get install -y chrony
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
chrony
Setting up chrony (4.4-1ubuntu0.1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/chrony.service → /lib/systemd/system/chrony.service.
Significado: chrony está instalado y habilitado como servicio.
Decisión: Configúralo para apuntar a servidores permitidos y para hacer step solo en el arranque.
cr0x@server:~$ sudo bash -c 'cat >/etc/chrony/chrony.conf <<EOF
pool ntp.corp iburst
driftfile /var/lib/chrony/chrony.drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF'
Significado: makestep 1.0 3 permite hacer step si el offset >1s durante las primeras 3 actualizaciones. Después de eso, hace slew. Es un equilibrio sensato para las rarezas de reanudación en portátiles sin romper cargas en ejecución repetidamente.
Decisión: Reinicia y verifica el tracking.
cr0x@server:~$ sudo systemctl restart chrony
cr0x@server:~$ chronyc sources -v
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current best, '+' = combined, '-' = not combined.
| / Reachability register (octal) - '>377' means good.
||
^* 10.0.0.53 3 6 377 12 +0us[ +5us] +/- 20ms
Significado: El * indica la fuente seleccionada. Reachability 377 es excelente. El offset es pequeño.
Decisión: Si no obtienes una fuente y reach se queda bajo (como 0 o 1), es política de red o DNS. Arregla eso upstream.
Remediación tras reanudación: el enfoque pragmático
En portátiles afectados, la acción más consistente de “arreglarlo ahora” es reiniciar WSL. Es brutal, pero efectivo. Para una estación de desarrollo, esto suele ser aceptable. Para procesos de larga duración en WSL, menos.
Si no puedes permitir un apagado total de WSL, reinicia el servicio de tiempo dentro de la distro después de reanudar. Si systemd está habilitado, eso es sencillo.
cr0x@server:~$ sudo systemctl restart systemd-timesyncd
Significado: Fuerza a timesyncd a reevaluar la red y resincronizar.
Decisión: Si timesyncd no se sincroniza realmente post-reanudación, cambia a chrony o aborda la alcanzabilidad NTP.
Errores comunes: síntomas → causa raíz → solución
Estos son los reincidentes. Si reconoces uno, puedes evitar horas de “quizá sea DNS” agitación.
1) Síntoma: “SSL certificate is not yet valid” solo dentro de WSL2
- Causa raíz: El tiempo del guest WSL2 está atrasado tras suspensión/reanudación; la hora de Windows está correcta.
- Solución: Habilita chrony o timesyncd; implementa resincronización post-reanudación; el workaround rápido es
wsl --shutdowny luego relanzar.
2) Síntoma: apt-get update dice “Release file is not valid yet”
- Causa raíz: El reloj del guest está atrasado respecto al timestamp de la metadata del repositorio.
- Solución: Arregla la hora primero. No desactives las comprobaciones de fecha del repositorio; eso degrada la seguridad disfrazado de conveniencia.
3) Síntoma: la hora está desfasada exactamente por tu offset de huso horario
- Causa raíz: Configuración de huso horario incorrecta dentro de la distro, no deriva.
- Solución: Ajusta el huso con
timedatectl set-timezone(systemd) o herramientas específicas de la distro. Mantén el reloj en UTC; muestra local según sea necesario.
4) Síntoma: la hora es correcta al arrancar, deriva bajo carga intensa de CPU
- Causa raíz: El guest no recibe rebanadas de CPU de forma fiable; la disciplina de tiempo es débil; kernel/WSL antiguo.
- Solución: Actualiza WSL/kernel; usa chrony; reduce la inanición extrema de CPU; evita fijar WSL a recursos mínimos si eso rompe la contabilización del tiempo.
5) Síntoma: chrony/timesyncd no puede alcanzar servidores en VPN
- Causa raíz: La red corporativa bloquea UDP/123; NTP permitido solo a servidores internos o mediante proxy especial.
- Solución: Apunta tu servicio de tiempo a servidores NTP aprobados; si no existen, escala con red/seguridad para obtener una ruta aprobada. No túneles NTP público desde endpoints corporativos.
6) Síntoma: “System clock synchronized: yes” pero las apps aún se quejan del tiempo
- Causa raíz: La app usa tokens/certs cacheados creados durante el desfase; o el problema es tiempo monotónico vs reloj de pared; o no es tiempo en absoluto.
- Solución: Limpia/reinicia los procesos afectados después de arreglar la hora; verifica con las fechas de certificados; confirma el reloj de pared real con
date -Isy compara.
7) Síntoma: advertencias “time went backwards” en journald con frecuencia
- Causa raíz: Stepping repetido por configuración agresiva o fuente de tiempo inestable; o reanudación causa gran salto hacia atrás.
- Solución: Usa chrony con stepping controlado (
makestepsolo al inicio) y deslizado luego; implementa resincronización al reanudar para evitar saltos grandes.
Microrrelatos corporativos desde las trincheras de desfase horario
Microrrelato 1: El incidente causado por una suposición errónea
La empresa tenía un entorno mixto Windows/Linux y WSL2 era el estándar no oficial. Todo iba bien hasta que el equipo desplegó un nuevo repositorio interno de paquetes con certificados TLS de corta duración emitidos por una CA interna. La CA estaba bien gestionada. Los certificados eran válidos. El repositorio era aburrido en el mejor sentido.
Entonces empezaron a fallar builds. No todos. Ni siquiera la mayoría. Solo un conjunto rotativo de desarrolladores, sobre todo usuarios de portátil, sobre todo quienes cerraban la tapa entre reuniones. El error era consistente: “certificate is not yet valid.” Los equipos de seguridad recibieron alertas. El equipo de repositorios fue culpado. Alguien sugirió que el reloj de la CA estaba mal (no lo estaba).
La suposición errónea fue simple: “Si la hora de Windows está bien, la hora de WSL debe estar bien.” Es un pensamiento reconfortante, como creer que los backups funcionan porque el dashboard está verde. Un SRE finalmente hizo que un desarrollador ejecutara date en WSL2 junto a la hora de Windows. El guest estaba siete minutos atrás. Eso fue suficiente para caer frente al límite NotBefore del certificado.
La solución no fue heroica. Habilitaron un servicio de sincronización de tiempo adecuado en WSL2, lo apuntaron a los servidores NTP internos ya usados por hosts Linux, y añadieron un trabajo ligero de “resincronización al reanudar” en Windows que reiniciaba WSL para el grupo de usuarios más afectados. Una vez estable la hora, los errores TLS desaparecieron. El equipo de la CA dejó de recibir correos enfadados. El equipo del repo dejó de recibir correos enfadados. Todos volvieron a ignorar el tiempo—hasta el siguiente incidente, porque así trabaja la gente.
Microrrelato 2: La optimización que salió mal
Otra organización tenía una iniciativa de duración de batería. Ajustaron portátiles para “eficiencia”, lo que incluyó políticas agresivas de suspensión y ahorro de CPU. Alguien también recomendó limitar servicios en background. En WSL2, los desarrolladores comenzaron a quitar servicios para reducir “overhead”, claro que sí. Algunos incluso deshabilitaron demonios de sincronización con la lógica: “no soy un servidor”.
Un mes después, aparecieron fallos intermitentes de autenticación contra un servicio interno respaldado por Kerberos. Otra vez: no era para todos, ni siempre. Los fallos tendían a ocurrir por la tarde, a menudo tras una reunión larga. Los desarrolladores culparon al VPN. El VPN culpó al DNS. El DNS culpó a “algo con Linux”. El clásico triángulo corporativo de la culpa.
El verdadero culpable fue la deriva del reloj dentro de WSL2 tras ciclos repetidos de suspensión/reanudación, agravada por la optimización: no había demonio de tiempo para corregirla. La tolerancia de Kerberos no es una sugerencia. Cuando la deriva cruzó el umbral, los tickets fueron rechazados. Los fallos parecían “contraseña incorrecta” para la capa de aplicación, que es una broma cruel interpretada por protocolos.
La reversión fue simple: reactivar la sincronización de tiempo y relajar las configuraciones de suspensión más agresivas para desarrolladores que usaban WSL2 intensamente. La vida de la batería bajó ligeramente. La productividad se recuperó significativamente. La lección cayó como siempre: “Tu portátil no es un servidor, pero tu portátil ejecuta sistemas que se preocupan por el tiempo como un servidor”.
Microrrelato 3: La práctica aburrida pero correcta que salvó el día
Un equipo cercano a finanzas ejecutaba una pipeline de build y release localmente en WSL2 porque la capacidad CI corporativa estaba al límite. No era ideal, pero era la realidad. El líder del equipo tenía una regla innegociable: cada entorno dev debía apuntar a las mismas fuentes NTP internas que los hosts de producción Linux, y debía ser verificable.
Así estandarizaron chrony en WSL2, con una configuración gestionada mediante un pequeño script de bootstrap. No confiaban en “funciona en mi máquina”. Confiaban en “chronyc tracking muestra offset bajo”. También registraban una simple señal de salud: una comprobación diaria que guardaba offset y stratum en un archivo local. No porque fuera glamuroso—sino porque convirtió el tiempo en una propiedad medible.
Un día, un cambio de red corporativa bloqueó accidentalmente UDP/123 en un subconjunto de VLANs Wi‑Fi. Los desarrolladores empezaron a ver problemas raros en otros lugares, pero este equipo detectó el problema de tiempo temprano porque su comprobación diaria empezó a reportar fuentes no alcanzables. Tenían evidencia, no corazonadas.
Mientras otros grupos discutían si “internet estaba caído”, este equipo cambió temporalmente a una fuente NTP aprobada alternativa en un segmento de red diferente y siguió entregando. Más tarde, la red corrigió la política. Nadie escribió un postmortem dramático. Así es el éxito: aburrido, correcto y mayormente invisible.
Listas de verificación / plan paso a paso
Checklist A: Estabilización única (haz esto una vez por máquina)
- Actualiza WSL y el kernel (lado Windows) y reinicia si es necesario.
- Confirma que la hora de Windows está disciplinada (hora de dominio o sincronización fiable).
- Dentro de WSL2, confirma el estado de systemd (
ps -p 1). - Habilita un demonio de sincronización de tiempo:
- Si systemd está presente y quieres simple: habilita
systemd-timesyncd. - Si ves deriva crónica: instala y ejecuta
chrony.
- Si systemd está presente y quieres simple: habilita
- Apunta a fuentes NTP aprobadas (NTP interno si es corporativo; de lo contrario pools públicos estables si está permitido).
- Verifica el offset (estado de timesyncd o
chronyc tracking).
Checklist B: Fiabilidad post-suspensión (el plan “realidad portátil”)
- Reproduce el bug: cierra la tapa 5–10 minutos, reanuda, ejecuta
date -Is. - Si ocurre deriva: decide entre:
- Workaround rápido: reiniciar WSL (
wsl --shutdown). - Fijación durable: implementar reinicio del servicio al reanudar (timesyncd/chrony) o reinicio de WSL vía Programador de Tareas de Windows.
- Workaround rápido: reiniciar WSL (
- Después de implementar: repite la prueba suspensión/reanudación y verifica que el offset se mantenga pequeño.
Checklist C: Cuando las redes corporativas interfieren
- Asume que UDP/123 está bloqueado hasta que se demuestre lo contrario.
- Encuentra servidores de tiempo aprobados (NTP interno, controladores de dominio o fuentes de tiempo sancionadas).
- Configura tu demonio para usar solo esos servidores.
- Verifica alcanzabilidad y tracking con chrony/timesyncd.
- Si no existen: escala. El tiempo es una dependencia de seguridad, no una preferencia personal.
Preguntas frecuentes
1) ¿Por qué WSL2 deriva más que “Linux normal” en hardware físico?
Porque es una VM con un modelo de planificación y temporizador distinto, y la suspensión/hibernación del portátil añade discontinuidades. El bare metal suele tener un comportamiento de temporizador de hardware más estricto y menos casos límite de suspensión/reanudación en el guest.
2) ¿Debería ejecutar sudo date -s cuando ocurre?
No. Ajustar la hora manualmente provoca saltos que pueden romper procesos en ejecución y oculta el problema real: la falta de disciplina continua. Usa un demonio de tiempo y arregla el comportamiento post-reanudación.
3) ¿Es systemd-timesyncd suficiente, o necesito chrony?
timesyncd es suficiente cuando la red es estable y la deriva es leve. Si ves sesgos repetidos post-suspensión, conectividad intermitente o correcciones grandes, chrony suele ser la mejor herramienta.
4) Mi WSL2 no tiene systemd. ¿Estoy atado?
No estás atado, pero estás jugando en modo difícil. Puedes habilitar systemd en WSL (recomendado) o ejecutar chrony sin la supervisión de systemd. Esto último funciona, pero es más fácil de errar y más difícil de mantener consistente.
5) ¿Por qué la deriva del tiempo rompe tanto apt y git?
apt valida timestamps de la metadata del repositorio; TLS valida ventanas de validez de certificados. Ambos son características de seguridad. Un tiempo incorrecto es indistinguible de un ataque o corrupción, así que el comportamiento correcto es fallar.
6) ¿Puede Docker dentro de WSL2 empeorar esto?
Docker en sí no “causa” deriva, pero cargas intensas de contenedores pueden aumentar la contención de CPU. Si el guest se queda sin CPU o tu demonio de tiempo está ausente/mal configurado, la deriva se hace visible más rápido.
7) ¿Por qué mis logs se ven fuera de orden?
Si el reloj de pared salta hacia atrás o adelante, las marcas temporales de los logs lo seguirán. Tus sistemas pueden seguir funcionando, pero la observabilidad se vuelve poco fiable. Usa tiempo monotónico para duraciones y mantén el reloj de pared disciplinado.
8) ¿Cuál es un offset aceptable para trabajo de desarrollo?
Manténlo dentro de un segundo si puedes; unos pocos segundos suelen estar bien para la mayoría de tareas. Cuando entras en minutos, espera fallos de autenticación y TLS. En entornos corporativos con seguridad estricta, incluso un pequeño desfase puede ser problemático.
9) Si la hora de Windows es correcta, ¿por qué WSL2 no la hereda perfectamente?
Porque “heredar” no es un flujo constante; está mediado por integración de virtualización y comportamiento del guest. Suspensión/reanudación, demoras de planificación y configuración del guest aún pueden producir desfase.
10) ¿Es seguro reiniciar WSL con frecuencia?
Es seguro en el sentido de que es una operación soportada. No es seguro para estados no guardados: mata procesos en ejecución en WSL. Trátalo como reiniciar una VM: bien cuando está planificado, descortés cuando se hace a mitad de una carga de trabajo.
Siguientes pasos que puedes hacer hoy
Haz esto en orden. Detente cuando el problema pare.
- Mide: ejecuta
date -Isytimedatectlen WSL2. Confirma si es deriva o huso horario. - Confirma el servicio de sincronización: si systemd está presente, comprueba
systemctl status systemd-timesyncd(o chrony si está instalado). - Arregla lo básico: habilita un demonio (timesyncd o chrony), apúntalo a fuentes aprobadas y verifica el offset.
- Maneja la suspensión: si el desfase aparece tras reanudar, implementa una acción determinista—reinicia el servicio de tiempo o, si es necesario, reinicia WSL—disparada al despertar.
- Valida con una prueba de fallo: repite la comprobación de validez TLS y la actualización de repositorios. No declares victoria hasta que el síntoma original haya desaparecido.
Si tomas un consejo con opinión: trata el tiempo como infraestructura, incluso en un portátil. Especialmente en un portátil. Tus herramientas ahora son sistemas distribuidos con sudadera.