Gestionar servicios con systemd: guía práctica

Gestionar servicios con systemd: guía práctica

Gestionar servicios con systemd: guía práctica

systemd es el gestor de servicios estándar en la mayoría de distribuciones Linux modernas. Aprende a crear tus propios servicios, controlarlos con systemctl y leer sus logs con journalctl.

Por Javier · Actualizado: 2026-05-26

systemd es el gestor de servicios e init predeterminado en las principales distribuciones Linux modernas (Debian, Ubuntu, Fedora, Arch). Con un archivo unit file de texto plano y tres comandos —enable, start, status— puedes registrar cualquier proceso como servicio con arranque automático, reinicio ante fallos y logs centralizados en el journal.

Si tu servidor arranca servicios a medias, esto va contigo

Tienes un servidor en casa o en una VPS, y hay dos o tres scripts que necesitas que corran al arrancar. Los metiste en rc.local, o pusiste un @reboot en cron, y funciona… la mayoría de las veces. Pero cuando el proceso muere en silencio a las 3 de la mañana, te enteras porque algo deja de responder, no porque el sistema te haya avisado.

Quizá has oído hablar de systemd y lo has dejado pasar porque parece mucho aparato para lo que necesitas: unit files, targets, dependencias… Da la sensación de que es para sysadmins de empresa, no para alguien que mantiene su homelab en los ratos libres. Es normal pensarlo.

Este post es un tutorial directo. Al final tendrás un servicio real corriendo bajo systemd, configurado para arrancar solo, reiniciarse si cae, y con logs consultables desde un solo comando. No necesitas saber más de systemd del que vas a leer aquí para empezar a usarlo bien.

Por qué importa

Restart automático incluido

Con `Restart=on-failure` en el unit file, systemd relanza el proceso si muere. Sin cron ni watchdogs externos.

Logs sin configurar nada

`journalctl -u tu-servicio` muestra el historial completo desde el arranque, sin archivos de log separados.

Orden de arranque declarativo

`After=network.target` garantiza que tu servicio espera a que la red esté lista. Un campo, cero scripts.

Limita permisos fácilmente

Con `User=` y `Group=` en la sección [Service] el proceso corre sin root, reduciendo superficie de ataque.

Qué es systemd y por qué lo encuentras en casi todo

systemd es el sistema de init que arranca como proceso PID 1 cuando el kernel termina de cargarse. A partir de ahí, es el encargado de levantar todo lo demás: la red, el servidor SSH, el entorno gráfico, tus propios scripts… todo pasa por él.

Lo crearon Lennart Poettering y Kay Sievers en 2010. En pocos años desplazó a SysV init y Upstart en Debian, Ubuntu, Fedora, Arch, openSUSE y la mayoría de distribuciones de uso general. No está en todas: Alpine Linux usa OpenRC y Void Linux usa runit, así que si trabajas con esas distros, esto no aplica directamente.

Hay quien tiene opinión fuerte sobre systemd —la comunidad Linux rara vez se pone de acuerdo en nada fácilmente—, pero en la práctica, si tienes un homelab con Debian o Ubuntu, ya lo estás usando. Más vale conocerlo bien.

Los unit files: la pieza clave para definir un servicio

Un servicio en systemd se describe en un archivo de texto plano con extensión .service. Se llama unit file. Es lo que le dice a systemd cómo arrancar tu proceso, con qué usuario, cuándo hacerlo y qué hacer si falla.

Las tres secciones de un unit file

  • [Unit] — descripción y dependencias con otros servicios o recursos del sistema
  • [Service] — cómo arrancar, parar y reiniciar el proceso
  • [Install] — en qué punto del arranque debe activarse

Un ejemplo mínimo para un script Python que quieras dejar corriendo en tu servidor:

[Unit]
Description=Mi script de monitorización casero
After=network.target

[Service]
ExecStart=/home/javi/scripts/monitor.py
Restart=on-failure
User=javi

[Install]
WantedBy=multi-user.target

After=network.target le dice a systemd que espere a que la red esté disponible antes de arrancar. Restart=on-failure hace que si el proceso muere inesperadamente, systemd lo relance solo. Sin esas dos líneas, tienes un servicio frágil.

Dónde se guardan los unit files

En Debian y Ubuntu hay dos ubicaciones relevantes:

  • /lib/systemd/system/ — unit files que instalan los paquetes del sistema. No los toques directamente.
  • /etc/systemd/system/ — los tuyos, los que creas a mano. Si hay conflicto de nombres, estos tienen prioridad.

Crear tu primer servicio personalizado paso a paso

Supón que tienes un script en /opt/homelab/backup.sh que quieres ejecutar como servicio en segundo plano. Esto es lo que harías en Debian/Ubuntu:

1. Crea el unit file

sudo nano /etc/systemd/system/backup-homelab.service

Contenido del archivo:

[Unit]
Description=Backup homelab automatizado
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash /opt/homelab/backup.sh
Restart=on-failure
User=javi
Group=javi

[Install]
WantedBy=multi-user.target

2. Recarga la configuración de systemd

Cada vez que creas o modificas un unit file, hay que avisar a systemd:

sudo systemctl daemon-reload

Sin este paso, systemd sigue viendo la versión anterior del archivo.

3. Habilita el servicio para que arranque con el sistema

sudo systemctl enable backup-homelab.service

Esto crea un symlink en el target de arranque. No arranca el servicio en ese momento, solo lo registra para el próximo boot.

4. Arráncalo manualmente para probarlo

sudo systemctl start backup-homelab.service

5. Comprueba que está corriendo

sudo systemctl status backup-homelab.service

Si ves Active: active (running), todo va bien. Si ves failed, el siguiente apartado te explica cómo investigar.

Comandos imprescindibles: systemctl en el día a día

Una vez que tienes servicios definidos, estos son los comandos que más usarás:

Comando Qué hace
systemctl start servicio Arranca el servicio ahora
systemctl stop servicio Para el servicio
systemctl restart servicio Para y vuelve a arrancar
systemctl reload servicio Recarga config sin matar el proceso (si el servicio lo soporta)
systemctl enable servicio Lo activa para el arranque automático
systemctl disable servicio Lo desactiva del arranque
systemctl status servicio Estado actual y últimas líneas de log
systemctl daemon-reload Recarga todos los unit files tras modificarlos

Dos más que conviene tener a mano:

# Ver todos los servicios activos
systemctl list-units --type=service --state=running

# Ver los que han fallado
systemctl --failed

systemctl --failed es especialmente útil cuando algo no arranca y no sabes qué. Te da la lista de los servicios en estado failed directamente, sin tener que revisar cada uno a mano.

Leer logs con journalctl sin volverte loco

systemd tiene su propio sistema de logging: el journal. Los logs de todos los servicios van ahí, y se leen con journalctl. No necesitas buscar archivos dispersos por /var/log/ para cada servicio.

Comandos básicos:

# Logs de un servicio concreto
journalctl -u backup-homelab.service

# Solo las últimas 50 líneas
journalctl -u backup-homelab.service -n 50

# Seguir el log en tiempo real (como tail -f)
journalctl -u backup-homelab.service -f

# Logs del arranque actual
journalctl -u backup-homelab.service -b

Cuando algo falla, lo primero que hay que hacer es journalctl -u nombre-del-servicio -n 100. El 90% de las veces el error está en las últimas líneas: un path incorrecto, un usuario sin permisos, una dependencia que no se cargó.

Truco útil: journalctl -xe muestra los últimos logs del journal completo con contexto extra. Sirve para ver qué pasó justo antes de que un servicio fallara al arrancar, especialmente cuando el problema está en algo de lo que depende y no en el propio servicio.

Seguridad y resiliencia básicas en tus servicios

Con tres líneas extra en el unit file ya tienes algo bastante más robusto que un script en cron o un nohup. No hace falta configuración avanzada para obtener un resultado decente.

Corre el servicio como un usuario sin privilegios

Por defecto, los servicios corren como root. Si tu script no necesita permisos de root, define un usuario:

[Service]
User=javi
Group=javi

Si el proceso tiene un bug gordo o se ve comprometido, el daño queda contenido al usuario javi y no afecta al sistema entero.

Resiliencia con Restart=

Restart=on-failure
RestartSec=5s

RestartSec añade una pausa antes de reintentar. Sin eso, si tu servicio falla en un bucle rápido, systemd lo relanza tan rápido que puede saturar el sistema. Cinco segundos es un buen punto de partida para servicios caseros.

Si quieres un timeout de parada limpia:

TimeoutStopSec=10

Evita que systemd espere indefinidamente a que un proceso termine. Si a los 10 segundos no ha parado limpiamente, lo mata.

Secretos fuera del unit file

Si tu servicio necesita una contraseña o un token de API, no los pongas directamente en ExecStart=. Pueden quedar expuestos en la salida de systemctl status o en logs. Usa un archivo de entorno:

[Service]
EnvironmentFile=/etc/homelab/secrets.env

Y en /etc/homelab/secrets.env (con permisos 600, solo root puede leerlo):

API_TOKEN=tu_token_aqui

Así los secretos quedan separados del unit file, que puede ser consultado por cualquier usuario del sistema con systemctl cat.

Preguntas frecuentes

Q: ¿Vale systemd para mis scripts caseros de arranque?

A: Funciona muy bien para eso. Cualquier script que necesites que arranque con el sistema y se reinicie si falla puede convertirse en un unit file .service en minutos. Solo necesitas definir el comando en ExecStart= y añadir Restart=on-failure.

Q: ¿Qué pasa si mi servicio muere solo en mitad del día?

A: Con Restart=on-failure en el unit file, systemd lo relanza automáticamente sin que tengas que hacer nada. Puedes ver cuántas veces ha caído y por qué con journalctl -u nombre-del-servicio, sin buscar archivos de log dispersos.

Q: ¿Por qué no usar un simple script en /etc/rc.local?

A: Puedes, pero rc.local no gestiona reinicios automáticos, no integra logs en el journal y no controla el orden de arranque con precisión. Con systemd tienes todo eso con cuatro líneas en un unit file y sin mantener lógica de reinicio a mano.

Q: »¿Cómo

A: »Añadiendo

del unit file le dices a systemd que espere a que la red esté disponible antes de lanzarlo. Es una línea, y evita el típico error de conexión rechazada al arrancar.»]

Q: »¿Qué

A: »En

puedes especificar User= y Group= con el usuario que prefieras. El proceso arrancará con esos permisos reducidos, lo que es la práctica recomendada para cualquier servicio que exponga red o acceda a datos sensibles.»]

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *