systemd es el init system dominante en Linux (Ubuntu 15.04+, RHEL/CentOS 7+, Debian 8+, Arch, Fedora). Convertir tu script en un servicio systemd bien escrito significa reinicio automático ante fallos, logs centralizados en journald, límites de recursos y arranque paralelo con dependencias. Este generador crea archivos .service listos para copiar a /etc/systemd/system y activar con systemctl enable.
Las tres secciones de un unit file
Un .service tiene [Unit] (metadatos y dependencias: Description, After, Requires), [Service] (cómo se ejecuta: ExecStart, User, Restart, Environment) y [Install] (cuándo se activa: WantedBy=multi-user.target). Cada línea sigue formato Clave=Valor. Comentarios con # o ;.
Restart policies y healthchecks
Restart=on-failure reinicia solo si sale con código distinto de 0. Restart=always reinicia siempre (incluso si tú lo paras manualmente). Combina con RestartSec=5 y StartLimitBurst=5 para evitar loops de reinicio en fallos permanentes. Para healthchecks activos usa Type=notify y sd_notify() desde tu app.
Hardening: sandboxing con systemd
systemd ofrece un sandboxing potente sin contenedores: NoNewPrivileges=yes, PrivateTmp=yes, ProtectSystem=strict, ProtectHome=yes, PrivateDevices=yes, RestrictAddressFamilies=AF_INET AF_INET6, CapabilityBoundingSet=. Con estos flags un compromiso de la app tiene un impacto muy limitado en el host.
Logs con journald
systemd captura stdout/stderr de tu proceso y los almacena en journald. Consulta con `journalctl -u miservicio -f` (follow), `journalctl -u miservicio --since '1 hour ago'`, o exporta a JSON con `-o json` para ingesta en Loki/Elasticsearch. Configura StandardOutput=journal (default) y evita loguear al disco desde la app.
Casos de uso comunes
- Convertir un script Node/Python/Go en servicio production-ready.
- Reemplazar procesos gestionados por pm2 o supervisor con systemd nativo.
- Programar tareas complejas con timers systemd (alternativa a cron).
- Aislar servicios sensibles con sandboxing sin containers.
Buenas prácticas
- Ejecuta como usuario dedicado (no root), User= y Group=.
- Añade ProtectSystem=strict y NoNewPrivileges=yes por defecto.
- Usa EnvironmentFile= para variables sensibles en un archivo 0600.
- Recarga con `systemctl daemon-reload` tras editar unit files.