Ejecutar systemd en WSL: Qué funciona ahora (y qué sigue fallando)

¿Te fue útil?

Quisiste un entorno Linux en Windows que se comporte como los servidores que realmente ejecutas. Entonces escribiste
systemctl status en WSL y obtuviste el clásico comentario seco: “System has not been booted with systemd.”
De repente tu “máquina de desarrollo rápida” se convierte en una especie de placa de cultivo con demonios medio operativos, registros faltantes y servicios
que solo arrancan si recuerdas activarlos.

La buena noticia: systemd en WSL ahora es un modo realmente soportado, no un montón de parches. La mala noticia: todavía no es una
VM completa, sigue sin ser tu kernel de producción y algunas cosas fallan de maneras que parecen personales.
Este es el mapa práctico: qué funciona, qué falla y cómo depurarlo como si estuvieras de guardia.

El estado actual: systemd en WSL hoy

Si estás en WSL2 y con un paquete WSL relativamente reciente, puedes habilitar systemd por distribución usando
/etc/wsl.conf. WSL entonces lanzará systemd como PID 1 dentro de la distro, y el resto de tus servicios
se comportan como en una máquina Linux normal—en su mayoría.

“En su mayoría” aquí tiene significado. WSL no es un hipervisor genérico. Es un kernel Linux alojado por Windows con una capa
de integración estrecha. Algunas tuberías son diferentes por diseño: la red está virtualizada; los montajes se traducen; el
ciclo de vida está impulsado por sesiones; Windows sigue teniendo las llaves de la gestión de energía y la red del host.

Mi guía con opinión:

  • Usa systemd en WSL cuando necesites gestión realista de servicios (Docker Engine, podman, sshd,
    timers, journald, servicios mediadas por dbus).
  • No uses WSL como producción (sí, la gente lo intenta). Trátalo como un entorno de desarrollo/CI con
    comportamiento parecido al de producción, no como una base de producción.
  • Mantén un límite entre “servicios Linux” y “responsabilidades del host Windows”. Cuando difuminas ese
    límite, la resolución de problemas se vuelve arte de performance.

Cómo arranca realmente systemd dentro de WSL (y por qué importa)

Tradicionalmente, WSL lanzaba tu shell (o el comando configurado) directamente; no había un sistema init. Eso significaba:
no PID 1 supervisando servicios, ningún target de arranque consistente y ningún registro gestionado por journald. Si un demonio moría,
moría silenciosamente o dejaba un archivo PID obsoleto como una pequeña lápida.

Con systemd habilitado, WSL inicia systemd como PID 1. D-Bus viene junto, y las unidades systemd pueden ejecutarse
normalmente. Ahora tienes una forma coherente de iniciar servicios, definir dependencias, establecer políticas de reinicio y usar
timers en lugar de “lo puse en mi archivo rc y esperé”.

Pero el “arranque” de WSL no es un arranque de hardware. Es un inicio en espacio de usuario dentro de un entorno gestionado. Dos consecuencias
aparecen de inmediato:

  1. El ciclo de vida está ligado a la instancia WSL. Cuando WSL se detiene (o se termina), tus servicios se detienen.
    Cuando arranca, ocurre el orden de unidades, pero no es lo mismo que un arranque completo de servidor con descubrimiento de dispositivos.
  2. Las capas de integración pueden sobreescribir los valores por defecto de Linux. La resolución DNS, las interfaces de red y los montajes
    pueden comportarse de manera diferente que en una instalación normal de distribución.

La lección práctica: trata systemd en WSL como “gestión real de servicios Linux corriendo en un contenedor huésped limitado”,
no como “instalé Ubuntu”. Este encuadre evita muchas suposiciones equivocadas.

Datos interesantes y contexto histórico

Estos son puntos cortos y concretos que explican por qué este tema sigue siendo delicado:

  1. WSL1 no usaba un kernel Linux en absoluto; traducía llamadas del sistema Linux a llamadas del kernel NT de Windows.
    Ese modelo fue ingenioso, pero limitó la compatibilidad para cargas de trabajo dependientes del kernel.
  2. WSL2 cambió a un kernel Linux real ejecutándose en una VM ligera. Por eso los contenedores y los cgroups se volvieron viables.
  3. Durante años, systemd no estuvo soportado en WSL, en parte porque WSL no se presentaba como un sistema tradicional arrancado con propiedad de PID 1 y gestión de dispositivos.
  4. Los primeros intentos de “systemd en WSL” dependían de scripts envoltorios y trucos manuales de PID 1. Funcionaron hasta que dejaron de hacerlo, y rompieron de maneras maravillosamente confusas.
  5. Las distribuciones Linux esperan cada vez más systemd. Incluso cuando un servicio puede ejecutarse sin él, el empaquetado y la integración suelen asumir que existen unidades systemd.
  6. systemd no es solo “un init”; es una suite (journald, resolved, networkd, logind, timers, dependencias de unidades). En WSL, puede que quieras exactamente algunos de estos y no otros.
  7. cgroup v2 es la opción moderna por defecto en muchos entornos. Eso importa para Docker, podman y cualquier control de recursos; WSL2 ha mejorado el soporte de cgroups gradualmente.
  8. La red de WSL históricamente usaba NAT con una IP de VM cambiante. Eso está bien para llamadas salientes y doloroso para servicios entrantes a menos que lo planifiques.
  9. WSL regenera partes de tu configuración Linux (notablemente /etc/resolv.conf) a menos que le digas que no, lo que choca con las expectativas de systemd-resolved.

Qué funciona bien (lo suficiente) con systemd en WSL

Gestión de servicios que se comporta como Linux

El beneficio principal es obvio: systemctl funciona. Las unidades pueden iniciarse al “arranque” (inicio de la instancia WSL),
reiniciarse en caso de fallo y expresar dependencias. Eso significa:

  • sshd puede ser un servicio, no un comando manual que olvidas.
  • trabajos tipo cron pueden ser timers de systemd con registros y manejo de fallos.
  • los servicios que usan dbus se comportan como en servidores.

journald hace que depurar sea menos supersticioso

Sin journald, terminas raspando archivos aleatorios bajo /var/log y preguntándote por qué no hay nada. Con systemd, puedes consultar registros estructurados por unidad, por arranque y por rango de tiempo. No es magia, pero es predecible—mi sabor favorito de la magia.

Docker Engine y compañía pueden ser más “nativos de Linux”

Muchos equipos usan Docker Desktop con integración WSL, lo que puede funcionar bien sin systemd. Pero si quieres ejecutar
Docker Engine dentro de la distro como lo harías en un host Linux, el soporte de systemd elimina muchos fricciones:
archivos de unidad, patrones de activación por socket y arranque predecible.

Los timers de systemd son una alternativa sensata a “ejecutar en background”

Las sesiones WSL aparecen y desaparecen. Los procesos en background que iniciaste manualmente pueden desaparecer, o seguir ejecutándose y
sorprenderte después. Timers + servicios te dan programación idempotente e inspeccionable.

Qué todavía falla o sigue siendo extraño

DNS y resolv.conf: la trampa perenne

A WSL le gusta gestionar DNS por ti. A systemd-resolved le gusta gestionar DNS por ti. Ponlos juntos y puedes obtener:
resolución de nombres ausente, comportamiento diferente entre el host y WSL, o “funciona hasta que me reconecto al Wi‑Fi”.

La solución normalmente no es complicada, pero requiere elegir quién posee la configuración. O permites que WSL genere
/etc/resolv.conf y no ejecutas systemd-resolved, o desactivas la generación de WSL y lo configuras correctamente
para resolved. La indecisión es la peor herramienta de gestión de configuración.

La red para servicios entrantes todavía no es “como en un servidor”

La red entrante depende de cómo Windows expone puertos a la VM WSL. Tu servicio puede estar escuchando en
127.0.0.1 dentro de WSL y ser inaccesible desde Windows, o a la inversa. A veces la dirección de enlace “correcta”
es contraintuitiva. A veces cambia con actualizaciones.

Semántica de montajes: /mnt/c es conveniente y lento

El sistema de archivos de Windows montado bajo /mnt/c es genial para interoperabilidad y terrible para cargas
que quieren semánticas y velocidad de sistema de archivos Linux (compilaciones pesadas en metadatos, bases de datos, repos grandes). systemd no
arregla eso; solo organiza el dolor.

No todos los parámetros del kernel se comportan como en tu centro de datos

El kernel de WSL es real, pero está gestionado. Algunos módulos, sysctls y comportamientos de dispositivos pueden diferir de tu flota.
Si pruebas algo sensible al kernel, valida también en una VM Linux real.

Broma #1: WSL con systemd es como darle a tu portátil de desarrollo un buscador de incidencias—de repente tiene opiniones sobre el tiempo de actividad.

Tareas prácticas: comandos, salidas y decisiones

La forma más rápida de entender si tu configuración es “suficientemente sana” es interrogarla como lo harías en un host de producción. Abajo hay comandos reales, cómo debería verse una salida realista y la decisión que tomas.

Tarea 1: Confirma que estás en WSL2 (no WSL1)

cr0x@server:~$ uname -r
5.15.133.1-microsoft-standard-WSL2

Qué significa: Si la cadena del kernel incluye microsoft-standard-WSL2, estás en WSL2.

Decisión: Si estás en WSL1, detente. el soporte de systemd es para WSL2. Convierte la distro a WSL2 antes de continuar.

Tarea 2: Verifica que PID 1 sea systemd

cr0x@server:~$ ps -p 1 -o pid,comm,args
  PID COMMAND         COMMAND
    1 systemd         /sbin/init

Qué significa: Que PID 1 sea systemd es todo el asunto.

Decisión: Si PID 1 es init o bash, systemd no está habilitado (o WSL no reinició limpiamente).

Tarea 3: Comprueba la configuración de habilitación de systemd en WSL

cr0x@server:~$ cat /etc/wsl.conf
[boot]
systemd=true

Qué significa: Este es el interruptor por distro.

Decisión: Si falta/está en false, configúralo y luego reinicia la instancia WSL desde Windows (o termina esa distro) para que tome efecto.

Tarea 4: Prueba que systemd funciona (no solo está presente)

cr0x@server:~$ systemctl is-system-running
running

Qué significa: running es sano. También podrías ver degraded si alguna unidad falló.

Decisión: Si degraded, lista inmediatamente las unidades fallidas y arregla la primera falla que importe.

Tarea 5: Lista unidades fallidas y elige la pelea correcta

cr0x@server:~$ systemctl --failed
  UNIT                    LOAD   ACTIVE SUB    DESCRIPTION
● systemd-resolved.service loaded failed failed Network Name Resolution
● snapd.service            loaded failed failed Snap Daemon

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state.
SUB    = The low-level unit activation state, often a more detailed state.
2 loaded units listed.

Qué significa: Algunos valores por defecto fallan en WSL, dependiendo de la distro y la configuración.

Decisión: Si la unidad fallida es irrelevante (como snapd en muchas configuraciones de desarrollo en WSL), enmárcala (mask). Si es resolved, arregla primero la propiedad de DNS.

Tarea 6: Inspecciona por qué falló una unidad (desde la perspectiva de systemd)

cr0x@server:~$ systemctl status systemd-resolved.service --no-pager -l
● systemd-resolved.service - Network Name Resolution
     Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Mon 2026-02-05 09:12:17 UTC; 25s ago
       Docs: man:systemd-resolved.service(8)
    Process: 412 ExecStart=/lib/systemd/systemd-resolved (code=exited, status=1/FAILURE)
     Status: "Failed to read /etc/resolv.conf: Too many levels of symbolic links"

Qué significa: Un clásico bucle: resolved quiere un enlace simbólico al resolv.conf stub, WSL puede reescribirlo y obtienes un circo de symlinks.

Decisión: Decide quién posee /etc/resolv.conf. Luego implementa limpiamente y reinicia la unidad.

Tarea 7: Comprueba quién controla DNS ahora mismo

cr0x@server:~$ ls -l /etc/resolv.conf
-rw-r--r-- 1 root root 116 Feb  5 09:10 /etc/resolv.conf

Qué significa: Un archivo regular típicamente sugiere que WSL lo generó (o lo fijaste manualmente).

Decisión: Si quieres systemd-resolved, normalmente deseas que /etc/resolv.conf sea un symlink al stub de resolved o a un archivo generado—sin que WSL lo reescriba.

Tarea 8: Confirma que journald captura logs (y no está silenciosamente inútil)

cr0x@server:~$ journalctl -b -n 10 --no-pager
Feb 05 09:12:01 server systemd[1]: Starting Network Name Resolution...
Feb 05 09:12:17 server systemd[1]: systemd-resolved.service: Main process exited, code=exited, status=1/FAILURE
Feb 05 09:12:17 server systemd[1]: systemd-resolved.service: Failed with result 'exit-code'.
Feb 05 09:12:17 server systemd[1]: Failed to start Network Name Resolution.
Feb 05 09:12:20 server systemd[1]: Starting OpenSSH Daemon...
Feb 05 09:12:20 server sshd[522]: Server listening on 0.0.0.0 port 22.
Feb 05 09:12:20 server systemd[1]: Started OpenSSH Daemon.

Qué significa: Tienes registros con alcance de arranque. Esa es tu fuente de verdad ahora.

Decisión: Si journald está vacío o muestra errores, arregla el logging antes de perseguir bugs de servicio. Sin registros estás depurando por intuición.

Tarea 9: Comprueba la salud de dbus (muchas cosas dependen silenciosamente de él)

cr0x@server:~$ systemctl status dbus --no-pager
● dbus.service - D-Bus System Message Bus
     Loaded: loaded (/lib/systemd/system/dbus.service; static)
     Active: active (running) since Mon 2026-02-05 09:12:00 UTC; 1min 2s ago
TriggeredBy: ● dbus.socket
       Docs: man:dbus-daemon(1)
   Main PID: 210 (dbus-daemon)
      Tasks: 1 (limit: 18947)
     Memory: 2.3M
     CGroup: /system.slice/dbus.service
             └─210 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only

Qué significa: dbus está en funcionamiento, la activación por socket funciona.

Decisión: Si dbus está muerto, espera “comportamientos raros” por todas partes: hostnamectl, timedatectl, resolved y herramientas relacionadas con logind.

Tarea 10: Verifica la versión de cgroup (a los contenedores les importa)

cr0x@server:~$ stat -fc %T /sys/fs/cgroup
cgroup2fs

Qué significa: cgroup2fs indica cgroup v2. Configuraciones antiguas podrían mostrar tmpfs y requerir diferente configuración de contenedores.

Decisión: Si ejecutas Docker Engine o podman, alinea las expectativas del driver de cgroup con lo disponible.

Tarea 11: Si Docker está instalado, comprueba la unidad del daemon

cr0x@server:~$ systemctl status docker --no-pager
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-02-05 09:12:45 UTC; 35s ago
TriggeredBy: ● docker.socket
       Docs: man:dockerd(8)
   Main PID: 900 (dockerd)
      Tasks: 18
     Memory: 78.4M
     CGroup: /system.slice/docker.service
             └─900 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Qué significa: Daemon en ejecución, activación por socket, ruta de cgroup con aspecto normal.

Decisión: Si Docker falla, revisa cgroups, supuestos de iptables/nft y si estás colisionando con la integración de Docker Desktop.

Tarea 12: Comprueba qué está escuchando y dónde (127.0.0.1 vs 0.0.0.0)

cr0x@server:~$ ss -lntp
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 0      4096   0.0.0.0:22         0.0.0.0:*     users:(("sshd",pid=522,fd=3))
LISTEN 0      4096   127.0.0.1:5432     0.0.0.0:*     users:(("postgres",pid=1203,fd=6))

Qué significa: sshd es accesible en todas las interfaces dentro de WSL; postgres está enlazado solo al loopback.

Decisión: Si Windows no puede alcanzar un servicio, primero revisa las direcciones de enlace. “Está en ejecución” no es “es alcanzable”.

Tarea 13: Confirma el tipo de montaje para tu directorio de proyecto

cr0x@server:~$ df -T .
Filesystem     Type  1K-blocks      Used Available Use% Mounted on
/dev/sdd       ext4  263174212  18234568 231513928   8% /

Qué significa: Si estás en ext4 dentro del sistema de archivos Linux, el rendimiento suele ser aceptable.

Decisión: Si tu proyecto vive bajo /mnt/c (típicamente 9p o similar), muévelo al sistema de archivos de la distro para compilaciones/bases de datos pesadas.

Tarea 14: Identifica si WSL reescribe resolv.conf a tus espaldas

cr0x@server:~$ grep -n "generateResolvConf" /etc/wsl.conf || true

Qué significa: Normalmente ninguna salida significa comportamiento por defecto (WSL puede generar resolv.conf).

Decisión: Si quieres DNS determinista con systemd-resolved, establece explícitamente generateResolvConf=false y gestiona el archivo/enlace simbólico tú mismo.

Tarea 15: Comprueba el rendimiento de arranque y culpa a las unidades lentas

cr0x@server:~$ systemd-analyze blame | head
3.214s snapd.service
1.122s docker.service
 812ms systemd-resolved.service
 402ms ssh.service
 211ms systemd-journald.service

Qué significa: Tienes tiempos a nivel de unidad. Esto es oro cuando “WSL se siente lento hoy”.

Decisión: Enmascara o deshabilita unidades que son irrelevantes en WSL y ralentizan cada inicio.

Tarea 16: Demuestra que un timer funciona y produce logs

cr0x@server:~$ systemctl list-timers --all --no-pager | head
NEXT                        LEFT     LAST                        PASSED  UNIT                         ACTIVATES
Mon 2026-02-05 09:20:00 UTC 2min 10s Mon 2026-02-05 09:15:00 UTC 2min ago apt-daily.timer              apt-daily.service
Mon 2026-02-05 10:00:00 UTC 42min    Mon 2026-02-05 09:00:00 UTC 17min ago man-db.timer                man-db.service

Qué significa: Los timers están programados y registrados.

Decisión: Si dependes de tareas programadas, prefiere timers sobre hacks en shell. Si los timers llenan logs o consumen CPU, ajústalos o desactívalos.

Guion de diagnóstico rápido

Cuando systemd-en-WSL “está roto”, rara vez falla de una forma novedosa. La mayoría de las interrupciones son el mismo pequeño conjunto de modos de fallo con diferentes disfraces. Aquí está el orden que te lleva al cuello de botella rápido.

Primero: ¿systemd es realmente PID 1 y el sistema está en ejecución?

  • ps -p 1 -o comm,args → si no es systemd, detente y arregla la habilitación/reinicia WSL.
  • systemctl is-system-running → si está degraded, lista las unidades fallidas y arregla la primera relevante.

Segundo: ¿Los registros son utilizables?

  • journalctl -b -n 50 → si está vacío, no tienes observabilidad; arregla journald/permisos de almacenamiento o tus expectativas.
  • journalctl -u <service> -b → si el servicio falla, prefiere esto sobre archivos de log aleatorios.

Tercero: ¿Es DNS/red o es el servicio mismo?

  • resolvectl status (si usas resolved) o inspecciona /etc/resolv.conf.
  • ss -lntp para confirmar direcciones de enlace y listeners.
  • ip addr + ip route para confirmar que las interfaces y la ruta por defecto existen.

Cuarto: ¿El rendimiento lo mata un montaje o una unidad lenta?

  • df -T y saneamiento de rutas: no ejecutes bases de datos en /mnt/c si quieres felicidad.
  • systemd-analyze blame para identificar unidades de arranque lentas; deshabilita lo que no necesitas.

Quinto: Cargas de contenedores—confirma cgroups y supuestos del daemon

  • stat -fc %T /sys/fs/cgroup para confirmar cgroup v2.
  • systemctl status docker y journalctl -u docker -b para errores del daemon.

El objetivo no es “probar arreglos al azar”. El objetivo es clasificar el problema en menos de cinco minutos.

Tres microhistorias corporativas (todas reales, ninguna trazable)

Microhistoria 1: El incidente causado por una suposición equivocada

Un equipo cercano a finanzas estandarizó en WSL para desarrollo porque redujo la varianza en los portátiles. Añadieron systemd
para que los servicios pudieran arrancar “como en prod.” Funcionó durante meses. Luego llegó un nuevo desarrollador, clonó el repo, ejecutó
el bootstrap y su malla de servicios local nunca arrancó correctamente.

La suposición errónea fue sutil: asumieron que el “arranque” de WSL era equivalente a un arranque de VM y que las unidades systemd
estarían corriendo antes del primer prompt del desarrollador de forma fiable. En la práctica, el inicio de la instancia WSL se
dispara al lanzar la distro, y el timing depende de lo que haga el host. El script de bootstrap ejecutó inmediatamente un comando cliente
contra un servicio que todavía estaba arrancando, falló una vez y luego almacenó el estado de fallo en una configuración local.

El síntoma parecía un problema de red: timeouts, conexiones rechazadas y una persona insistiendo “funciona en mi máquina”, que es tanto una
afirmación como un estilo de vida. La causa raíz fue solo orden: los servicios estaban bien pero no listos cuando se les consultó, y el script no tenía reintentos/retroceso.

La solución fue aburrida: añadir chequeos de readiness (systemd After= y Wants= donde correspondiera, más un bucle de reintentos en el cliente con timeouts), y dejar de tratar el comportamiento del primer arranque como determinista. También añadieron
un único comando “health” que comprobaba unidades críticas e imprimía salida accionable.

Microhistoria 2: La optimización que salió mal

Otro equipo perseguía builds más rápidas. Notaron que mantener el código bajo /mnt/c facilitaba editar desde herramientas de Windows, pero las compilaciones eran lentas. Alguien propuso una “optimización”: enlazar con enlaces simbólicos salidas de build y caches de vuelta al almacenamiento de Windows para que sobrevivieran reinicios de WSL y se compartieran entre distros.

Aceleró algunas builds pequeñas y luego detonó como solo las optimizaciones de E/S pueden hacerlo: las builds más grandes empezaron a fallar de forma intermitente. Vieron caches de artefactos corruptos, errores de permisos espurios y tormentas de file watchers. systemd no fue la causa directa, pero lo hizo más visible porque los servicios en background ahora estaban ejecutándose de forma fiable—indexadores, servidores de lenguaje y file watchers estaban activos y amplificando los peores rasgos del sistema de archivos.

El problema clásico: el sistema de archivos montado desde Windows tenía semánticas y rendimiento diferentes. Las operaciones de metadatos eran más lentas, los bloqueos de archivos se comportaban distinto y toda la canalización se volvió sensible al timing. El equipo pasó una semana “ajustando” antes de admitir que el plan era defectuoso.

La solución fue mantener caches pesados y repos dentro del sistema de archivos Linux (ext4 en el disco virtual de WSL), y exponer solo los artefactos finales a Windows si hacía falta. Mantuvieron un paso explícito de “sync” en lugar de intentar que dos mundos compartieran un directorio caliente.

Microhistoria 3: La práctica aburrida pero correcta que salvó el día

Un grupo de plataforma mantenía un entorno de desarrollo basado en WSL para docenas de ingenieros. La configuración incluía systemd,
Docker, un espejo de registry local y algunos agentes internos. Este era el tipo de entorno que funciona hasta que un martes por la mañana todos actualizan algo y el caos florece.

Su práctica aburrida: mantenían un script mínimo versionado de “diagnóstico dorado” que ejecutaba las mismas comprobaciones cada vez: PID 1, unidades fallidas, últimos logs de arranque, propiedad DNS, sockets en escucha, tipo de disco para el directorio de trabajo y salud del daemon de contenedores. Imprimía líneas simples de aprobado/fallado y sugería el siguiente comando.

Cuando una actualización de WSL cambió el comportamiento de la red lo suficiente como para romper conexiones entrantes en un subconjunto de portátiles, el grupo no pasó horas discutiendo sobre qué máquina estaba maldita. Ejecutaron el script, vieron que los servicios estaban escuchando en 127.0.0.1, y Windows ya no podía alcanzarlos. El patrón fue consistente.

Porque tenían una línea base y registros, pudieron diseñar una solución dirigida: ajustar direcciones de enlace para servicios de desarrollo, actualizar reglas de firewall en el host y documentar una sola solución temporal para usuarios afectados mientras esperaban un cambio más permanente en el lado de Windows. No fue glamoroso, pero evitó una caída lenta de productividad.

Errores comunes: síntoma → causa raíz → solución

1) “System has not been booted with systemd”

Síntoma: systemctl da errores, las unidades no se pueden gestionar.

Causa raíz: systemd no está habilitado, o la instancia WSL no se reinició después de cambiar la configuración.

Solución: Establece [boot] systemd=true en /etc/wsl.conf y reinicia la instancia WSL. Confirma que PID 1 es systemd.

2) DNS funciona una vez y luego falla tras cambios de red

Síntoma: apt update falla, nombres internos dejan de resolverse tras cambios de VPN/Wi‑Fi.

Causa raíz: Conflicto de propiedad: WSL autogenerando /etc/resolv.conf mientras systemd-resolved espera control (o viceversa).

Solución: Elige un propietario. Si usas resolved, establece generateResolvConf=false y enlaza /etc/resolv.conf al archivo esperado por resolved sin bucles. Si no usas resolved, desactívalo/enmácaralo.

3) Servicios corren pero son inaccesibles desde Windows

Síntoma: curl localhost:PORT funciona dentro de WSL pero no desde Windows, o al revés.

Causa raíz: Desajuste en la dirección de enlace (127.0.0.1 vs 0.0.0.0), suposiciones de NAT/port forwarding o firewall del host.

Solución: Usa ss -lntp para ver dónde está enlazado. Enlaza los servicios de desarrollo de forma intencional. No adivines. Si es necesario, ajusta reglas de firewall en Windows.

4) WSL se siente lento “tras habilitar systemd”

Síntoma: El inicio de la distro se siente más pesado; los comandos van lentos; picos de CPU al arrancar.

Causa raíz: Servicios innecesarios que se inician automáticamente (snapd, timers de apt, indexadores), o elección de sistema de archivos (trabajar bajo /mnt/c).

Solución: Usa systemd-analyze blame y systemctl --failed. Deshabilita/enmascara unidades irrelevantes. Mueve proyectos pesados al sistema de archivos Linux.

5) Docker dentro de WSL falla extrañamente (iptables, cgroups, permisos)

Síntoma: El daemon Docker no arranca, los contenedores no pueden crear redes, errores sobre cgroups o nft.

Causa raíz: Expectativas desajustadas: cgroup v2 vs v1, diferencias en el backend del firewall o conflicto con la integración de Docker Desktop.

Solución: Confirma el modo de cgroup, inspecciona journalctl -u docker -b y elige un modelo: gestionado por Docker Desktop o gestionado por la distro. Mezclarlos aumenta la entropía.

6) systemd-resolved falla con bucles de symlink

Síntoma: resolved no arranca; los errores mencionan la profundidad de enlaces simbólicos de /etc/resolv.conf.

Causa raíz: Cadena de symlinks incorrecta, a menudo debido a regeneración por WSL o ediciones manuales sobre los valores por defecto de la distro.

Solución: Elimina el bucle y reconstruye el estado deseado. Asegura un único propietario del archivo y que WSL no lo regenere en contra de tu voluntad.

7) Los timers se ejecutan cuando no los quieres

Síntoma: Uso aleatorio de CPU/red; apt-daily despierta durante demos; los ventiladores giran como un jet.

Causa raíz: Los timers por defecto de la distro no están ajustados para “entorno de desarrollo en portátil”.

Solución: Desactiva o reprograma timers que no necesites. Valida con systemctl list-timers y revisa logs para el impacto real.

Listas de verificación / plan paso a paso

Paso a paso: habilitar systemd de forma segura

  1. Confirma WSL2: ejecuta uname -r y busca la cadena del kernel WSL2.
  2. Habilita systemd en la distro: edita /etc/wsl.conf:

    cr0x@server:~$ sudo sh -c 'cat > /etc/wsl.conf <<EOF
    [boot]
    systemd=true
    EOF'
    
  3. Reinicia la instancia WSL: desde Windows, termina la distro o reinicia WSL para que el cambio aplique.
  4. Verifica PID 1: ps -p 1 -o comm,args.
  5. Chequea estado degradado: systemctl is-system-running, luego systemctl --failed.
  6. Haz del DNS una elección deliberada: decide si usar systemd-resolved. Si no lo necesitas, enmárcalo y sigue.

    cr0x@server:~$ sudo systemctl mask systemd-resolved.service
    Created symlink /etc/systemd/system/systemd-resolved.service → /dev/null.
    
  7. Desactiva unidades lentas/no necesarias: usa systemd-analyze blame y deshabilita a los ofensores que no usas.
  8. Mueve trabajos sensibles al rendimiento a ext4: guarda repos/bases de datos en el sistema de archivos Linux, no en /mnt/c.

Lista de verificación: configuración de desarrollo parecida a producción (la versión sensata)

  • Servicios críticos tienen unidades systemd con políticas de reinicio.
  • Los logs se consultan vía journalctl, no “cualquier archivo que exista”.
  • La propiedad del DNS es explícita y documentada.
  • Las suposiciones de red entrante se prueban (desde Windows y dentro de WSL).
  • Los timers se podan a lo que realmente quieres.
  • Repos y bases de datos viven en el sistema de archivos Linux.
  • La cadena de herramientas de contenedores tiene un solo propietario (integración Docker Desktop o Docker en la distro), no ambos.

Lista de verificación: cuándo no te molestes con systemd en WSL

  • Solo necesitas una shell, compiladores y unas pocas herramientas CLI.
  • Tu flujo es “ejecutar un proceso en primer plano” y matarlo cuando termines.
  • Dependes de servicios nativos de Windows y solo usas WSL para scripting.

Preguntas frecuentes

1) ¿Necesito systemd en WSL para ejecutar Docker?

No estrictamente. Docker Desktop puede integrarse con WSL sin que gestiones systemd.
Pero si quieres un Docker Engine estilo Linux dentro de la distro con gestión estándar de unidades, systemd ayuda.
Elige un modelo y comprométete con él.

2) ¿Por qué systemctl funciona pero mi servicio aún no arranca en el “arranque” de WSL?

El “arranque” de WSL es el “inicio de la instancia”, y el timing varía. Asegura que tu unidad tenga las dependencias correctas y usa chequeos de readiness.
Luego verifica systemctl is-enabled e inspecciona journalctl -u your.service -b.

3) ¿Debería ejecutar systemd-resolved en WSL?

Solo si lo necesitas y estás dispuesto a poseer la configuración DNS explícitamente. Muchos entornos de desarrollo están bien dejando que WSL gestione
/etc/resolv.conf y enmascarando resolved. La peor opción es ejecutar ambos “a medias”.

4) ¿Por qué faltan mis logs bajo /var/log?

Con systemd, muchos servicios registran en journald, no en archivos planos. Usa journalctl. Si quieres logs en archivos, configura el servicio
o el reenvío de journald deliberadamente.

5) ¿Es systemd en WSL suficientemente estable para el trabajo diario?

Sí para flujos de trabajo de desarrollo, especialmente si mantienes configuraciones simples y evitas trampas de sistema de archivos y DNS.
No si tu definición de “estable” incluye “se comporta exactamente como nuestro kernel de producción y red”.

6) ¿Por qué mi servicio escucha pero es inaccesible desde Windows?

Normalmente está enlazando a 127.0.0.1 dentro de WSL, o cambió el firewall/port forwarding de Windows. Comienza con
ss -lntp y enlaza deliberadamente. Confirma desde ambos lados.

7) ¿Habilitar systemd ralentizará WSL?

Puede, si tu distro habilita un montón de servicios/timers que no necesitas. La solución es directa: mide con
systemd-analyze blame, luego deshabilita/enmasa el ruido.

8) ¿Puedo usar timers de systemd en lugar de cron en WSL?

Sí, y probablemente deberías. Los timers tienen mejor logging y control de dependencias. Solo recuerda que si la instancia WSL no está en ejecución,
los timers no se dispararán hasta que lo esté.

9) ¿Cuál es el modo de fallo más común de systemd-en-WSL?

Conflictos de propiedad de DNS, seguidos por unidades “extra” lentas o fallidas (snapd, actualizadores automáticos) que no fueron diseñadas para el ciclo de vida de WSL.

10) Si esto es para desarrollo, ¿por qué ser tan estricto con los diagnósticos?

Porque el tiempo de inactividad en desarrollo es tiempo de inactividad real—pagado por ingenieros en vez de por clientes. Además porque una ruta de diagnóstico limpia evita que el equipo
cultive soluciones de imitación que rompen más adelante.

Próximos pasos que realmente puedes tomar

systemd en WSL es ahora una herramienta legítima: puedes gestionar servicios, obtener registros coherentes y ejecutar un entorno de desarrollo con forma de producción
sin chapuzas. Pero WSL aún tiene su propia física. Trátalo como un host Linux con restricciones y con Windows como la plataforma—no como un pequeño
servidor que casualmente vive en un portátil.

Pasos prácticos:

  1. Habilita systemd, reinicia WSL y verifica PID 1 + systemctl is-system-running.
  2. Elimina servicios irrelevantes: deshabilita/enmascara lo que no pertenece a tu entorno de desarrollo.
  3. Elige un propietario DNS y hazlo cumplir. Las medias tintas crean los incidentes más duros.
  4. Mueve repos/bases de datos sensibles al rendimiento fuera de /mnt/c y dentro de ext4.
  5. Escribe un pequeño script de “health check” del equipo que ejecute las mismas 8–10 comprobaciones cada vez.

Cita (idea parafraseada), atribuida: a Werner Vogels se le suele atribuir el principio de que deberías “construirlo, ejecutarlo y ser responsable de ello”
como parte de la cultura de confiabilidad.

Broma #2: Si enmascaras snapd en WSL y nada se rompe, has descubierto la criatura más rara en ops: una dependencia que no necesitabas.

← Anterior
DNS seguro en Windows: DoH/DoT — Qué funciona realmente
Siguiente →
Recuperar contraseñas y claves Wi‑Fi antes de formatear Windows

Deja un comentario