Crear un servicio systemd para cualquier aplicación
Cuando tienes un proceso que debe correr siempre en tu VPS (una API, un bot, un worker, un script de monitoreo), la forma correcta de mantenerlo vivo es convertirlo en un servicio systemd. Systemd es el gestor de servicios por defecto en casi todas las distribuciones Linux modernas, y aprender a escribir un archivo de unit te ahorra montones de dolores de cabeza.
Qué es systemd
Systemd es el primer proceso que arranca Linux (PID 1) y se encarga de iniciar, detener y supervisar el resto de servicios del sistema. Si un servicio muere, systemd puede reiniciarlo; si necesita arrancar al boot, systemd lo hace antes de que alguien inicie sesión. Todo se configura con archivos de texto plano llamados units, que terminan en .service.
Anatomía de un archivo .service
Crea un archivo en /etc/systemd/system/miapp.service con esta plantilla básica:
[Unit] Description=Mi aplicación personalizada After=network.target [Service] Type=simple User=appuser Group=appuser WorkingDirectory=/opt/miapp ExecStart=/opt/miapp/venv/bin/python /opt/miapp/main.py Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Cada sección tiene un propósito específico. Vamos a desglosarlas.
Sección [Unit]
Description es texto libre que aparece cuando consultas el estado del servicio. After=network.target le dice a systemd que no arranque este servicio hasta que la red esté lista. Si tu app necesita base de datos local, puedes poner After=postgresql.service.
Sección [Service]
Aquí va lo importante. Type=simple es lo más común: systemd asume que el proceso definido en ExecStart es el servicio mismo y no se bifurca. User y Group indican con qué identidad correr; nunca uses root salvo que sea estrictamente necesario. WorkingDirectory es el equivalente a hacer cd antes de ejecutar, útil si tu app usa rutas relativas.
ExecStart es el comando completo para arrancar la app. Importante: usa siempre rutas absolutas, porque systemd no carga el PATH del usuario como lo haría una sesión interactiva. Restart=on-failure hace que systemd reinicie el servicio si termina con código de error, y RestartSec=5 le dice que espere 5 segundos entre intentos.
Variables de entorno
Si necesitas pasar variables, tienes dos opciones. La directa:
Environment="API_KEY=abc123" Environment="DEBUG=false"
La recomendada para secretos es usar un archivo separado:
EnvironmentFile=/etc/miapp.env
Y en /etc/miapp.env pones las variables una por línea. Asegúrate de que ese archivo tenga permisos restrictivos (chmod 600).
Habilitar y gestionar el servicio
Después de crear el archivo, recarga systemd para que lo detecte y activa el servicio:
sudo systemctl daemon-reload sudo systemctl enable miapp sudo systemctl start miapp
El enable registra el servicio para arrancar al boot; el start lo lanza de inmediato. Puedes combinarlos con enable --now. Para ver el estado actual:
sudo systemctl status miapp
Leer logs con journalctl
Todo lo que tu aplicación imprima a stdout y stderr queda capturado automáticamente en el journal de systemd. Para consultar logs:
sudo journalctl -u miapp sudo journalctl -u miapp -f sudo journalctl -u miapp --since "1 hour ago"
El flag -f los sigue en tiempo real como un tail -f, y --since acepta expresiones humanas muy cómodas. Esto elimina la necesidad de redirigir logs a archivos manualmente.
Comandos diarios
Los que vas a usar constantemente: systemctl restart miapp, systemctl stop miapp, systemctl disable miapp. Cada vez que edites el archivo .service, recuerda correr daemon-reload antes del restart para que los cambios surtan efecto.