Sysadmin

Systemd Avanzado: Creación de Servicios y Reincio Automático

Systemd Avanzado: Creación de Servicios y Reincio Automático

Crear un servicio systemd personalizado es una habilidad fundamental para cualquier sysadmin que gestione sistemas Linux en producción. En un entorno empresarial con cientos de servidores y servicios custom, la fiabilidad y la gestión centralizada se vuelven prioritarias. La configuración de un unit file systemd no solo garantiza que una aplicación o un script se inicien correctamente al arrancar el sistema, sino que también permite definir dependencias, gestionar reinicios automáticos en caso de fallo y aislar los procesos para una mayor seguridad. Este enfoque reduce drásticamente los tiempos de inactividad y simplifica la resolución de problemas, proporcionando un control granular sobre la ejecución de procesos críticos. Lee también: Automatización Sysadmin: Evita Que Tu Éxito Te Despida

Tested on: Ubuntu 24.04 LTS · Debian 12 · CentOS Stream 9 · Septiembre 2026

Requisitos Previos / Entorno de Prueba

Para seguir esta guía, necesitarás un sistema Linux con systemd (prácticamente todas las distribuciones modernas lo usan). Asegúrate de tener acceso como usuario con privilegios sudo para crear y gestionar los servicios. No se requieren softwares específicos, solo un editor de texto como nano o vim.

Dónde van los unit files y cuál elegir

Los unit files de systemd son archivos de configuración que describen cómo systemd debe gestionar un recurso (un servicio, un punto de montaje, un socket, etc.). Su ubicación es crucial para el correcto funcionamiento y para la mantenibilidad del sistema.

Existen varios directorios donde systemd busca los unit files, ordenados por prioridad (el último tiene precedencia):

  • /usr/lib/systemd/system/: Contiene los unit files instalados por los paquetes del sistema operativo y las aplicaciones. Estos archivos no deben modificarse directamente, ya que serían sobrescritos por las actualizaciones del paquete.
  • /etc/systemd/system/: Es el directorio preferido para los servicios personalizados y para las modificaciones a los servicios existentes. Aquí puedes crear tus propios unit files o sobrescribir partes de unit files del sistema (utilizando el mecanismo de los ‘override’ o ‘drop-in files’).
  • /run/systemd/system/: Utilizada para unit files generados dinámicamente o temporales. No es una ubicación para unit files manuales.

Para nuestros propósitos, es decir, la creación de un servicio personalizado, el directorio /etc/systemd/system/ es la elección correcta. Crearemos un archivo app.service en su interior.

Anatomía de un servicio: [Unit], [Service], [Install]

Un unit file de tipo service se divide típicamente en tres secciones principales, cada una con un rol específico:

  • [Unit]: Esta sección contiene metadatos genéricos sobre la unit, como una descripción legible por el usuario (Description=) y las dependencias de otras units (After=, Requires=, Wants=). Aquí es donde se define el orden de inicio y las relaciones con otros servicios.
  • [Service]: Esta es la sección más importante para un servicio. Define el comando a ejecutar (ExecStart=), el usuario bajo el que debe ejecutarse el servicio (User=), las directivas de reinicio (Restart=, RestartSec=) y otras opciones de ejecución.
  • [Install]: Esta sección es utilizada por systemctl enable para determinar cómo el servicio debe habilitarse al inicio. WantedBy= especifica bajo qué target el servicio debe habilitarse (ej. multi-user.target para un sistema multiusuario sin GUI).

Aquí tienes un ejemplo de unit file básico para una aplicación genérica denominada app:

sudo nano /etc/systemd/system/app.service

Luego pega el siguiente contenido:

[Unit]
Description=App
After=network-online.target
Wants=network-online.target

[Service]
User=app
EnvironmentFile=/etc/app.env
ExecStart=/opt/app/bin/app
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Guarda y cierra el archivo. Este archivo define un servicio simple pero robusto. Lee también: Hardening SSH en Linux: Guía Completa 2026

Iniciar después de la red: After y Wants

Para muchos servicios, especialmente aquellos que se comunican por red, es fundamental que arranquen solo después de que la interfaz de red esté completamente configurada y funcionando. Las directivas After= y Wants= en la sección [Unit] gestionan precisamente esto.

  • After=network-online.target: Indica a systemd que este servicio debe iniciarse después de que network-online.target haya sido alcanzado. network-online.target es un target especial que generalmente se activa solo cuando las interfaces de red están activas y tienen una dirección IP.
  • Wants=network-online.target: Crea una dependencia débil. Si network-online.target falla o no existe, nuestro servicio intentará iniciarse de todos modos. Para una dependencia más fuerte, usarías Requires=, lo que causaría el fallo de nuestro servicio si la dependencia no se satisficiera. Wants= suele ser suficiente y más flexible.

Estas directivas son cruciales para evitar que los servicios intenten conectarse a recursos de red aún no disponibles, previniendo errores al inicio.

Reinicio automático con Restart y RestartSec

La resiliencia es un aspecto clave en producción. systemd ofrece potentes mecanismos para garantizar que los servicios críticos permanezcan activos incluso en caso de caída. Las directivas Restart= y RestartSec= en la sección [Service] son fundamentales para esto.

  • Restart=on-failure: Especifica cuándo el servicio debe reiniciarse automáticamente. Las opciones comunes son:
  • no: Nunca reiniciar.
  • on-success: Reiniciar solo si el proceso termina con éxito.
  • on-failure: Reiniciar si el proceso termina con un código de error, o si es terminado por una señal (pero no si es un reinicio limpio o un proceso de apagado).
  • on-abnormal: Reiniciar si el proceso termina de forma anómala (ej. a causa de una señal).
  • on-watchdog: Reiniciar si el temporizador de watchdog expira.
  • always: Reiniciar siempre, independientemente del código de salida.

on-failure es una elección común y robusta para la mayoría de las aplicaciones que no deberían terminar inesperadamente.

  • RestartSec=5: Define un retardo en segundos antes de que systemd intente reiniciar el servicio. Esto es útil para evitar un ciclo de reinicio rápido que podría sobrecargar el sistema o enmascarar un problema subyacente. Un valor de 5 segundos es un buen punto de partida.

Con estas dos directivas, systemd se convierte en un guardián activo de tu servicio, interviniendo automáticamente en caso de problemas.

Ejecutar como usuario no privilegiado

Por razones de seguridad, ningún servicio debería ejecutarse nunca como usuario root a menos que sea estrictamente necesario (y casi nunca lo es). La directiva User= (y opcionalmente Group=) en la sección [Service] permite especificar el usuario y el grupo bajo los que se ejecutará el servicio.

En el ejemplo, User=app indica que el servicio se ejecutará con el usuario app. Si este usuario no existe, systemd fallará el inicio del servicio. Es una buena práctica crear un usuario de sistema dedicado para cada servicio, con privilegios mínimos y una shell no interactiva (ej. /sbin/nologin).

sudo useradd -r -s /sbin/nologin app

Esto aísla el proceso y limita los daños potenciales en caso de compromiso del servicio.

Variables de entorno y EnvironmentFile

A menudo los servicios requieren variables de entorno para su configuración (ej. cadenas de conexión a bases de datos, claves API). En lugar de codificarlas en el unit file, es preferible cargarlas desde un archivo externo utilizando EnvironmentFile= en la sección [Service].

EnvironmentFile=/etc/app.env

El archivo /etc/app.env debería contener las variables en el formato KEY=VALUE, una por línea:

sudo nano /etc/app.env
DATABASE_URL=jdbc:postgresql://localhost:5432/myapp
API_KEY=your_secret_key

Asegúrate de que los permisos de este archivo sean restrictivos (ej. chmod 600 /etc/app.env) para proteger la información sensible. Este enfoque mejora la seguridad y la flexibilidad, permitiendo modificar la configuración sin tocar el unit file principal. Lee también: Ansible: gestionar variables de entorno y archivos de configuración

Habilitar, iniciar y verificar el servicio

Una vez creado y configurado el unit file, es hora de ponerlo en funcionamiento.

  1. Recargar la configuración de systemd: Después de crear o modificar un unit file, systemd debe ser informado de los cambios. Esto se hace con daemon-reload:
sudo systemctl daemon-reload
  1. Verificar la sintaxis: Siempre es una buena idea verificar que no haya errores de sintaxis en el archivo antes de intentar el inicio.
sudo systemd-analyze verify /etc/systemd/system/app.service

Si no devuelve salida, el archivo es sintácticamente correcto.

  1. Habilitar el servicio: enable crea un enlace simbólico del archivo del servicio al directorio multi-user.target.wants/ (o similar), asegurando que el servicio se inicie automáticamente al arrancar. La opción --now lo inicia inmediatamente.
sudo systemctl enable --now app
  1. Verificar el estado del servicio: Para comprobar si el servicio está activo, en ejecución y sin errores, usa status:
systemctl status app

Deberías ver Active: active (running) y las últimas líneas de log.

Leer los logs del servicio

Cuando un servicio no funciona como se espera, los logs son tu recurso más valioso. systemd centraliza los logs a través de journald, accesibles con el comando journalctl.

Para visualizar los logs de un servicio específico:

journalctl -u app

Para visualizar los logs en tiempo real (como tail -f):

journalctl -u app -f

Esto te permite monitorear la salida de tu servicio y diagnosticar cualquier problema en tiempo real. También puedes filtrar por fecha, prioridad y otras opciones. Para más detalles, consulta la documentación oficial de systemd.

Errores Comunes y Resolución de Problemas

Incluso con la mejor configuración, pueden ocurrir errores. Aquí tienes algunos de los más comunes y cómo resolverlos:

  • Servicio no encontrado: systemctl status app devuelve Unit app.service could not be found.. Esto generalmente significa que el archivo app.service no está en el directorio correcto o que systemctl daemon-reload no se ha ejecutado después de la creación/modificación del archivo.
  • Permisos incorrectos: Si el servicio no logra iniciar y journalctl muestra errores de permisos, verifica que el usuario especificado en User= tenga los permisos adecuados para los archivos y directorios que el servicio necesita acceder. También, si usas EnvironmentFile=, asegúrate de que el usuario tenga permisos de lectura sobre ese archivo y que sus permisos sean 600 para proteger la información sensible. Es una práctica sólida ejecutar sudo journalctl -u app para ver los logs detallados y buscar mensajes como «Permission denied».
  • Ruta de ExecStart incorrecta: Asegúrate de que la ruta al ejecutable en ExecStart= sea absoluta y correcta. Un error común es usar una ruta relativa o una ruta que no existe. Si el ejecutable es un script, asegúrate de que tenga permisos de ejecución (chmod +x /opt/app/bin/app).
  • Variables de entorno faltantes o incorrectas: Si tu aplicación falla al iniciar y los logs indican problemas de configuración, revisa el archivo EnvironmentFile= y asegúrate de que todas las variables de entorno necesarias estén definidas correctamente y sin errores de sintaxis.
  • Fallo de dependencia: Si el servicio depende de otros servicios (ej. una base de datos) y estos no están disponibles, el servicio podría fallar. Usa After= y Wants= o Requires= correctamente para establecer las dependencias. Si un servicio depende de una base de datos, por ejemplo, asegúrate de que el servicio de la base de datos esté active (running) antes de intentar iniciar tu aplicación.

Conclusiones con Puntos Clave Operativos

La creación de servicios systemd personalizados es una habilidad que transforma la gestión de aplicaciones en entornos Linux. Al dominar el unit file, los sysadmins pueden garantizar la fiabilidad, seguridad y automatización de sus sistemas. Los puntos clave a recordar son:

  1. Ubicación del unit file: Siempre en /etc/systemd/system/ para servicios personalizados.
  2. Estructura clara: Las secciones [Unit], [Service] y [Install] son esenciales para una configuración robusta.
  3. Resiliencia con Restart=on-failure y RestartSec=5: Asegura que tus servicios se recuperen automáticamente de fallos inesperados, minimizando el downtime.
  4. Seguridad con User=: Ejecuta los servicios con usuarios dedicados y no privilegiados para limitar el impacto de posibles vulnerabilidades.
  5. Configuración flexible con EnvironmentFile=: Separa las variables de entorno sensibles del unit file para mayor seguridad y facilidad de gestión.
  6. Dominio de systemctl y journalctl: Estas herramientas son tus mejores aliadas para habilitar, verificar y depurar tus servicios.

Al aplicar estos principios, no solo construirás servicios más robustos y seguros, sino que también optimizarás la gestión operativa de tu infraestructura, un paso crucial para cualquier profesional de TI que busque eficiencia y control en entornos de producción complejos. Una organización sanitaria pública, por ejemplo, podría usar estos principios para asegurar que sus sistemas de registro de pacientes o de gestión de citas estén siempre disponibles, incluso ante fallos inesperados de software, garantizando una atención continua y fiable a sus usuarios.

Comparte este artículo:

Escrito por

Rosario Giordano

Rosario Giordano es administrador de sistemas y consultor de TI especializado en c iberseguridad y cloud, con más de 20 años de experiencia en la gestión de infraestructuras Linux empresariales. Sus áreas de especialización incluyen el hardening de SSH, plataformas Kubernetes , bases de datos PostgreSQL, virtualización con VMware/Proxmox y el cumplimiento de los marcos de seguridad NIS2 e ISO 27001.