coldwa.st
Todas las guíasProgramaciónWebDatosHerramientasBases de datosHaskellConceptosCabal y buildsToolchainCompiladorRendimientoEditor y HLS

Coldwast

Generador de archivos de servicio systemd

Escribe el comando que arranca tu aplicación y obtén una unidad .service lista para colocar en /etc/systemd/system/, con los comandos de instalación correspondientes. El generador también revisa lo que has escrito y señala los errores que hacen fallar una unidad en el primer arranque. Todo se ejecuta en tu navegador.

Frontal de un servidor torre con rejilla metálica perforada y pequeños botones de encendido, iluminado en azul sobre fondo oscuro
El panel frontal de un servidor torre, iluminado en azul. Una vez habilitada la unidad, systemd arranca tu aplicación en una máquina como esta en cada arranque, sin que nadie inicie sesión.
Partir de

Tu archivo de unidad

 

Lo que ha detectado el generador

    Instalarlo

     

    Las cinco líneas que deciden si funciona

    ExecStart no es un shell. systemd divide la línea en argumentos por sí mismo y ejecuta el programa directamente. Una tubería, una redirección > o un && llega a tu programa como argumento literal. systemd también expande $VAR por su cuenta, así que un dólar literal se escribe $$. Cuando el generador detecta sintaxis de shell, envuelve el comando en /bin/sh -c y hace ese escape por ti.

    Usa una ruta absoluta. Una ruta como ./server se rechaza directamente. Un nombre sin ruta como node se acepta, pero systemd solo busca en sus propios directorios fijos, no en el PATH de tu shell, así que un Node instalado con nvm o una herramienta en ~/.local/bin no se encuentra.

    Type=simple o exec para casi todo. Un servidor web, un worker o un bot que se queda en primer plano es simple. exec difiere en algo útil: el arranque solo se da por bueno cuando el binario se ha ejecutado de verdad, así que una ruta errónea hace fallar systemctl start en lugar de fallar en silencio un momento después. forking es para demonios antiguos que se van solos a segundo plano, y notify solo funciona si el programa llama a sd_notify.

    Restart=on-failure, con un límite. on-failure reinicia tras un fallo o una salida distinta de cero, pero no tras una parada limpia; always reinicia incluso entonces. Por defecto systemd permite 5 arranques en 10 segundos, y con una espera de 5 segundos una app que falla nunca llega a ese límite, así que entra en un bucle infinito. StartLimitIntervalSec=300 con StartLimitBurst=5 hace que se rinda y deje un estado de fallo claro.

    Wants= y After= juntos. After=network-online.target por sí solo solo fija un orden; no activa el target. Sin Wants=network-online.target tu servicio puede arrancar antes de que la red esté lista: el clásico «funciona tras un reinicio manual, falla al arrancar la máquina».

    El aislamiento, y lo que se dejó fuera a propósito

    Con ProtectSystem=strict todo el sistema de archivos es de solo lectura para el servicio, salvo las rutas que indiques en ReadWritePaths=. PrivateTmp le da su propio /tmp, NoNewPrivileges le impide ganar permisos mediante binarios setuid, y los ajustes de kernel y cgroup le impiden cambiar el estado del sistema. Ejecuta systemd-analyze security tuapp.service antes y después: muestra una puntuación de exposición y lista cada ajuste que sigue abierto.

    Faltan a propósito dos recomendaciones habituales. MemoryDenyWriteExecute=true rompe los compiladores just-in-time, es decir Node.js, la JVM y PyPy. PrivateDevices=true no da problemas en una app web, pero rompe cualquier cosa que hable con una GPU o un puerto serie. Añádelas tú si sabes que tu programa no las necesita.

    Unas gafas sobre un escritorio delante de un monitor desenfocado que muestra código fuente de colores en un editor
    Unas gafas delante de una pantalla llena de código. Cuando una unidad falla, la respuesta también está en pantalla: systemctl status da el código de salida y journalctl la salida de tu programa.

    Cuando no arranca: los códigos de salida

    systemctl status tuapp muestra un estado como status=203/EXEC. El número indica qué paso falló antes incluso de que tu programa se ejecutara:

    EstadoSignificadoSolución habitual
    203/EXECNo se pudo ejecutar el programaRuta errónea, sin permiso de ejecución o script sin línea shebang
    200/CHDIRWorkingDirectory no existe o no es accesibleCréalo o comprueba que ProtectHome no lo oculta
    217/USERLa cuenta de User= no existeEjecuta la línea useradd de arriba
    226/NAMESPACENo se pudo montar el aislamientoUna ruta de ReadWritePaths no existe: créala o ponle el prefijo -

    Cualquier otro fallo es tu propio programa saliendo, y su salida está en journalctl -u tuapp -b.

    Cambiarlo más adelante

    Tras editar el archivo en /etc/systemd/system/, ejecuta sudo systemctl daemon-reload antes de reiniciar, o systemd seguirá usando la versión antigua. Para una unidad instalada por un paquete, no la edites en su sitio: sudo systemctl edit tuapp crea un archivo de sobrescritura que sobrevive a las actualizaciones y recarga systemd por ti.

    Relacionado: qué es un VPS, poner un proxy inverso delante de la app, lo básico de SSH y, para tareas programadas, el explicador de expresiones cron.

    Las directivas siguen las páginas de manual systemd.service(5) y systemd.exec(5). Type=exec requiere systemd 240 o posterior; todas las versiones actuales de Debian, Ubuntu, Fedora y RHEL lo cumplen.