Las unidades pueden parecer correctas, systemctl start puede informar de éxito y, diez segundos después, el servicio queda inactivo. O se reinicia cada medio minuto hasta que el límite de arranques lo detiene. Ninguno de los dos comportamientos es una falla de red: la unidad describe una vida de proceso que no coincide con lo que el cliente hace en realidad. El cliente puede hacer fork y salir, o configurar la sesión y salir de inmediato.

Por qué la unidad queda inactiva segundos después de un arranque correcto

systemd deduce el estado del proceso que inició, así que Type= es una afirmación sobre ese proceso, no documentación. Con Type=simple, la unidad cuenta como activa mientras el comando se ejecuta y queda inactiva cuando vuelve. Por eso un cliente que entrega la conexión a un ayudante y sale parece un fallo, incluso con el túnel levantado. Entonces el registro muestra un patrón de inicio y parada que se lee como un binario defectuoso.

Lee el tipo de unidad junto al comportamiento del cliente antes de tocar la configuración de red.

Elige el tipo que coincida con el cliente

Dos patrones cubren la mayoría de las CLI de proveedores: un comando que configura una sesión y sale, y un comando que hace fork de un ayudante antes de volver. Cada uno necesita una forma de unidad distinta.

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/protonvpn-cli connect -f
ExecStop=/usr/bin/protonvpn-cli disconnect

oneshot con RemainAfterExit=true mantiene la unidad activa después de que el comando vuelve, lo que encaja con el patrón de configurar y salir, y el comando de parada da al servicio un cierre limpio. Un cliente que hace fork conserva la misma forma, pero necesita Type=forking para que systemd siga al hijo. Define Restart=on-failure, RestartSec=30 y un StartLimitBurst finito, para que una caída del proveedor no se convierta en un bucle de reinicios que entierre el error.

Nunca dejes que un cliente supervisado se convierta en demonio

Los supervisores fuera de systemd chocan con la misma pared. Un script de runit que lanza un cliente demonizado vuelve de inmediato al supervisor, que lee el retorno como un fallo y arranca otra copia. Todo supervisor espera poseer el proceso en primer plano, tal como sshd -D se queda delante. Quita la bandera de demonio de los comandos supervisados y deja que el supervisor haga el trabajo en segundo plano. Los scripts envoltorio que vuelven antes de que exista el túnel causan la misma confusión.

Un proceso que se desengancha es invisible para todo lo que debía vigilarlo.

La sesión termina y se lleva el túnel consigo

Una sesión de escritorio posee el cliente que lanza. Termina el inicio de sesión y el bus de sesión desaparece, llevándose el túnel, lo que explica por qué la conexión de un cliente gráfico suele caer al cerrarse la última ventana. Los servidores deberían usar una unidad de sistema o un perfil de NetworkManager que suba solo. Una unidad de usuario solo tiene sentido cuando el túnel debe terminar con el inicio de sesión, así que lígala al objetivo de la sesión gráfica y dilo en su descripción.

El usuario del servicio es la otra mitad del mismo problema. Una clave propiedad de root con modo 0600 es ilegible para una unidad que corre con otra cuenta, haga lo que haga sudo en tu shell.

systemctl cat openvpn-server@work
sudo chown -R openvpn:network /etc/openvpn/server
sudo find /etc/openvpn -type f -perm /077 -ls

Ordena los dependientes cuando la dirección ya exista

Cuando un demonio se enlaza a una dirección de túnel que aún no se ha creado, sale con Cannot assign requested address. La reparación es un orden explícito, no un bucle de reintentos.

[Unit]
After=network.target [email protected]
Requires=sys-devices-virtual-net-wg0.device

After= ordena las tareas, mientras que Requires= en la unidad del dispositivo ata el dependiente a la existencia de la interfaz, lo que es más fuerte que esperar solo al objetivo de red. Recarga el gestor tras editar y reinicia el servicio dependiente, y luego lee su registro en lugar de suponer que el orden surtió efecto. Envía la salida del cliente al registro con StandardOutput=journal o una opción de log, porque un cliente supervisado que escribe en un archivo que nadie abre se ve idéntico a uno que nunca arrancó.

Después reinicia una vez y confirma que la unidad está activa cuando aparece el dispositivo del túnel. Una reparación verificada solo con systemctl start no ha probado el orden de arranque que debía reparar.

Artículos relacionados