Ubuntu 24.04 systemd unit overrides: arregla servicios sin editar archivos del proveedor (caso #8)

¿Te fue útil?

Cambiaste /lib/systemd/system/something.service a las 2 a.m., el servicio “funcionó”, y luego una actualización de paquete deshizo silenciosamente tu arreglo.
Ahora estás frente a un bucle de reinicio, preguntándote qué parte de tu memoria te está engañando.

Ubuntu 24.04 es territorio systemd. La acción correcta casi nunca es “editar el archivo unit del proveedor”. La acción correcta son los overrides: drop-ins,
claros, auditables y reversibles. Obtienes el arreglo sin fragilidad—y dejas de perder contra dpkg.

El modelo mental: qué lee systemd y en qué orden

systemd es un combinador de configuración. No “carga un archivo de servicio”. Construye la configuración final de la unidad desde múltiples capas y luego la ejecuta.
Si lo tratas como un único archivo, seguirás llevándote sorpresas.

De dónde vienen los unit files (Ubuntu 24.04)

En Ubuntu verás comúnmente:

  • /lib/systemd/system/: unit files del proveedor (instalados por paquetes). No son tuyos.
  • /etc/systemd/system/: overrides del administrador y unidades personalizadas. Estos sí son tuyos.
  • /run/systemd/system/: unidades en tiempo de ejecución y drop-ins transitorios. Efímeros; duran hasta el reinicio.

La prioridad es efectivamente: /etc gana sobre /run gana sobre /lib (con matices), además de los drop-ins aplicados en orden lexicográfico.
La regla práctica sigue siendo útil: si quieres una solución estable, ponla en /etc.

Drop-ins: el escalpelo limpio

El mecanismo canónico de override es un archivo drop-in:
/etc/systemd/system/<unit>.d/override.conf.
Contiene sólo los deltas que quieres, no una copia completa de la unidad. Eso importa porque es legible, revisable y resistente a la evolución de la unidad del proveedor.

También puedes colocar múltiples drop-ins (p. ej., 10-limits.conf, 20-env.conf). systemd los carga en orden.
Esto facilita responder “quién cambió qué” en lugar de “alguien editó el unit file en su lugar y ahora es un copo de nieve único”.

La diferencia entre editar y sobrescribir (y por qué importa)

Editar el unit file del proveedor es una tentación atractiva. Es rápido, y crea deuda técnica con una sola pulsación.
En el momento en que el paquete se actualice, dpkg:

  • sobrescribirá la unidad (si no la marcaste como conffile), o
  • mostrará prompts que se “resuelven” durante emergencias, o
  • dejará un lío .dpkg-dist/.dpkg-old que nadie recuerda reconciliar.

Los overrides evitan todo eso. El paquete puede hacer lo que quiera. Tu intención sigue aplicándose.

Una cita para mantenerte honesto

“Los bugs sutiles son los que aparecen después de cambios que olvidaste que hiciste.” — idea parafraseada atribuida a ingenieros de operaciones con experiencia

Mantén tus cambios donde puedas verlos. Los overrides son precisamente eso.

Ocho hechos y un poco de historia (por qué existen los overrides)

  1. systemd debutó en 2010 (Lennart Poettering y Kay Sievers) y reemplazó un zoológico de scripts init por archivos unit declarativos.
  2. Ubuntu adoptó systemd por defecto en 15.04; para 24.04 ya no es “nuevo”, es la suposición operativa detrás del empaquetado de servicios.
  3. Los drop-ins fueron diseñados para empaquetado de distribuciones: los proveedores envían valores por defecto seguros; los operadores añaden política de sitio sin bifurcar la unidad.
  4. Las rutas de búsqueda de unit files son parte de la interfaz; systemd está intencionalmente construido para fusionar configuración desde múltiples ubicaciones, no sólo “leer un archivo”.
  5. systemctl edit es el flujo de trabajo recomendado; crea directorios y maneja el editor de forma segura, incluyendo “cambios en seco y luego recarga”.
  6. Sobrescribir ExecStart= requiere limpiarlo primero; systemd lo trata como una lista, no como una cadena única. Si olvidas la línea de reinicio, ejecutarás dos starts (o ninguno).
  7. Existe una capa de tiempo de ejecución en /run; herramientas y generators pueden crear unidades transitorias, útil para lógica de arranque pero complicado al depurar.
  8. systemd tiene fuerte introspección: systemctl cat, systemd-analyze, journalctl -u, y systemctl show te permiten ver lo que en realidad decidió.

Broma #1: Editar /lib/systemd/system en producción es como “solo probar en prod” — rápido, emocionante y sólo ocasionalmente limitante para la carrera.

Caso #8: un override limpio que sobrevive actualizaciones

Aquí está la situación que veo constantemente en Ubuntu 24.04:
un servicio del proveedor arranca bien la mayoría de los días, pero bajo carga alcanza límites (descriptores de archivo, procesos, bloqueo de memoria), o necesita una variable de entorno adicional,
o el directorio de trabajo es incorrecto, o debería esperar por un montaje. La tentación es editar el unit file donde vive. No lo hagas.

Tu objetivo es: (1) identificar el cambio mínimo, (2) implementarlo en /etc/systemd/system como drop-in, y
(3) demostrar que systemd está ejecutando la configuración fusionada que pretendías.

Patrones típicos de override que son “seguros y aburridos”

  • Límites de recursos: LimitNOFILE=, TasksMax=, MemoryMax= — estables y de baja dramatización.
  • Orden de arranque: After=, Requires=, Wants= — evita condiciones de carrera con montajes y redes.
  • Entorno: Environment=, EnvironmentFile= — mantiene secretos fuera de los unit files; usa archivos con permisos.
  • Comportamiento de reinicio: Restart=on-failure, RestartSec=, StartLimitIntervalSec= — afina, pero no escondas fallos reales.
  • Cambios en ExecStart: factibles, pero merecen cuidado extra y un plan de rollback.

Cuándo no sobrescribir

Si el servicio está roto porque el binario está mal, el archivo de configuración es incorrecto o falta una dependencia, un override no te salvará.
Los overrides sirven para cambiar cómo systemd ejecuta un programa correcto, no para parchear el propio programa.

Broma #2: Si “arreglas” un segfault con Restart=always, felicitaciones—has inventado un generador muy rápido de logs.

Guion de diagnóstico rápido: encuentra el cuello de botella

Cuando un servicio está poco saludable, puedes pasar 30 minutos leyendo unit files… o puedes pasar 3 minutos mirando la salida correcta.
Este es el orden que uso en producción.

1) Establece el síntoma: estado, código de salida y último error

  • Revisa el estado: ¿está failed, activating, o en ejecución pero degradado?
  • Revisa el código de salida: status=203/EXEC vs status=1/FAILURE vs un kill por OOM son universos distintos.
  • Revisa las últimas líneas de log: no hagas scroll; pide a journald las últimas 50 líneas con timestamps.

2) Confirma qué está ejecutando realmente systemd

  • Imprime la unidad fusionada: systemctl cat muestra proveedor + drop-ins.
  • Inspecciona propiedades: systemctl show -p ExecStart,Environment,LimitNOFILE para confirmar valores efectivos.
  • Comprueba si un generator creó algo en /run: si es así, tus cambios persistentes podrían estar siendo superados o complementados.

3) Sólo entonces edita: cambio mínimo, rollback predecible

  • Crea un drop-in con systemctl edit.
  • Ejecuta systemd-analyze verify si cambiaste partes con sintaxis compleja.
  • daemon-reload, luego restart, luego valida.

Tareas prácticas (comandos, significado de salidas, decisiones)

A continuación hay tareas reales que puedes ejecutar en Ubuntu 24.04. Cada una incluye qué significa la salida y qué decisión tomar a continuación.
Usaré nginx.service como ejemplo porque es común, pero el flujo es idéntico para bases de datos, agentes, exporters y demonios personalizados.

Task 1: Encuentra dónde vive el unit file

cr0x@server:~$ systemctl show -p FragmentPath -p DropInPaths nginx.service
FragmentPath=/lib/systemd/system/nginx.service
DropInPaths=/etc/systemd/system/nginx.service.d/override.conf

Significado: FragmentPath es el archivo principal que systemd usa. DropInPaths lista los overrides aplicados.

Decisión: Si tu cambio está en /lib, tienes una granada en la mano. Muévelo a un drop-in en /etc.

Task 2: Lee la unidad fusionada, no sólo el fragmento del proveedor

cr0x@server:~$ systemctl cat nginx.service
# /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
PIDFile=/run/nginx.pid

# /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65536

Significado: Esto es lo que systemd aplicará. Es la verdad. Todo lo demás es comentario.

Decisión: Si la unidad fusionada no muestra tu cambio, estás editando el lugar equivocado o olvidaste daemon-reload.

Task 3: Comprueba el estado en vivo y la última razón de salida

cr0x@server:~$ systemctl status nginx.service --no-pager
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
    Drop-In: /etc/systemd/system/nginx.service.d
             └─override.conf
     Active: failed (Result: exit-code) since Mon 2025-12-30 10:12:07 UTC; 15s ago
       Docs: man:nginx(8)
    Process: 2197 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
        CPU: 45ms

Significado: status=1/FAILURE indica que nginx se ejecutó y devolvió fallo (a menudo error de configuración), no un problema de exec.

Decisión: Ve a los logs a continuación; no reescribas ExecStart hasta saber que es necesario.

Task 4: Extrae logs recientes para la unidad, con timestamps

cr0x@server:~$ journalctl -u nginx.service -n 50 --no-pager -o short-iso
2025-12-30T10:12:07+00:00 server nginx[2197]: nginx: [emerg] invalid number of arguments in "worker_connections" directive in /etc/nginx/nginx.conf:12
2025-12-30T10:12:07+00:00 server systemd[1]: nginx.service: Main process exited, code=exited, status=1/FAILURE
2025-12-30T10:12:07+00:00 server systemd[1]: nginx.service: Failed with result 'exit-code'.

Significado: El servicio falló por la configuración de la aplicación. systemd no es el problema hoy.

Decisión: Arregla la configuración de nginx. Los overrides no ayudarán. Si tu cambio pretendía arreglar una ruta de configuración, valida esa hipótesis.

Task 5: Confirma si existe un drop-in y qué contiene

cr0x@server:~$ systemctl edit nginx.service --full
# (editor opens the full unit)

Significado: --full crea una copia completa de la unidad en /etc/systemd/system. Es una herramienta contundente.

Decisión: Prefiere systemctl edit nginx.service (drop-in). Usa --full sólo si debes reemplazar la unidad por completo.

Task 6: Crea un drop-in apropiado (recomendado)

cr0x@server:~$ systemctl edit nginx.service
# (editor opens /etc/systemd/system/nginx.service.d/override.conf)

Añade algo como:

cr0x@server:~$ sudo cat /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65536
TasksMax=4096

Significado: No estás bifurcando la unidad. Estás aplicando política por encima.

Decisión: Mantén los overrides pequeños. Si tu override.conf es más largo que el archivo del proveedor, estás escribiendo tu propia unidad—hazte responsable explícitamente.

Task 7: Recarga systemd después de cambiar archivos de unidad

cr0x@server:~$ sudo systemctl daemon-reload

Significado: systemd vuelve a leer las definiciones de unidad. Sin esto, puede mantener versiones antiguas.

Decisión: Si los cambios “no se aplican”, sospecha primero que olvidaste recargar. Segundo sospecha: editaste un archivo que systemd no está usando.

Task 8: Verifica los valores efectivos que systemd aplicará

cr0x@server:~$ systemctl show nginx.service -p LimitNOFILE -p TasksMax -p Environment
LimitNOFILE=65536
TasksMax=4096
Environment=

Significado: Esta es la configuración efectiva después de fusionar todos los fragmentos y drop-ins.

Decisión: Si esperabas un valor y no está aquí, encuentra qué te está sobreescribiendo (orden de drop-ins, unidad completa en /etc, o una unidad transitoria).

Task 9: Sobrescribe ExecStart correctamente (limpia primero)

Este es el que la gente hace mal. En systemd, muchas directivas son de tipo lista. ExecStart= es una de ellas.
Para reemplazarla, debes limpiar la lista existente.

cr0x@server:~$ sudo cat /etc/systemd/system/nginx.service.d/10-execstart.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' -c /etc/nginx/nginx.conf

Significado: El ExecStart= vacío reinicia la lista; la línea siguiente pasa a ser el único ExecStart.

Decisión: Si no reseteas, podrías acabar con múltiples líneas ExecStart. Mejor caso: el inicio falla. Peor caso: “funciona” hasta que deja de hacerlo.

Task 10: Detecta una tormenta de reinicios y deténla de forma segura

cr0x@server:~$ systemctl show nginx.service -p NRestarts -p Restart -p RestartUSec
NRestarts=27
Restart=on-failure
RestartUSec=100ms

Significado: El servicio está oscilando rápidamente. Esto puede llenar los logs y esconder la primera falla.

Decisión: Detén y enmascara temporalmente mientras depuras (si es seguro), o aumenta RestartSec= vía drop-in para ralentizar el bucle.

Task 11: Comprueba si estás luchando contra una sustitución completa de unidad en /etc

cr0x@server:~$ systemctl show nginx.service -p FragmentPath
FragmentPath=/etc/systemd/system/nginx.service

Significado: Alguien creó una unidad completa en /etc, que sobrescribe completamente la unidad del proveedor.

Decisión: Si no querías poseer toda la unidad, elimina la unidad completa y reemplázala con drop-ins. Esto es una resaca común de “usamos –full una vez”.

Task 12: Identifica problemas de orden/dependencias (montajes, red, etc.)

cr0x@server:~$ systemctl list-dependencies --reverse nginx.service
nginx.service
● multi-user.target

Significado: Las dependencias inversas muestran quién quiere este servicio. Esto es “quién se romperá si nginx está abajo.”

Decisión: Si targets críticos dependen de él, planifica cambios con precaución y usa recargas escalonadas o ventanas de mantenimiento.

Task 13: Verifica la sintaxis de la unidad antes de reiniciar servicios críticos

cr0x@server:~$ systemd-analyze verify /etc/systemd/system/nginx.service.d/10-execstart.conf

Significado: Normalmente la ausencia de salida significa “no se encontraron problemas”. Si hay un error de sintaxis, lo verás antes de hacer el corte en producción.

Decisión: Usa verify cuando toques directivas complicadas (ExecStart, dependencias, sandboxing). Es más barato que una tormenta de pagers.

Task 14: Revertir overrides limpiamente

cr0x@server:~$ sudo systemctl revert nginx.service
Removed "/etc/systemd/system/nginx.service.d/override.conf".
Removed "/etc/systemd/system/nginx.service.d/10-execstart.conf".

Significado: revert elimina los drop-ins y devuelve la unidad al estado del proveedor (o lo que quede).

Decisión: Usa esto cuando tu override empeoró las cosas y necesitas un botón rápido “volver a la línea base conocida”.

Task 15: Confirma qué overrides están aplicados actualmente (con orden de archivos)

cr0x@server:~$ systemctl show nginx.service -p DropInPaths
DropInPaths=/etc/systemd/system/nginx.service.d/10-execstart.conf /etc/systemd/system/nginx.service.d/override.conf

Significado: El orden importa. El orden lexicográfico importa. Tu archivo 90-* vencerá a tu archivo 10-*.

Decisión: Si estás apilando múltiples cambios, nómbralos intencionalmente. No dejes que “override.conf” se convierta en un cajón de trastos.

Task 16: Demuestra que el proceso en ejecución recibió los límites que estableciste

cr0x@server:~$ systemctl show nginx.service -p MainPID
MainPID=2418
cr0x@server:~$ cat /proc/2418/limits | head -n 8
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             4096                 4096                 processes

Significado: Esto muestra lo que el kernel realmente aplica al proceso.

Decisión: Si los límites en /proc no coinciden, puede que tengas múltiples procesos (master/worker), o el servicio hace fork y aplica límites de forma distinta. Verifica el PID correcto.

Tres microhistorias corporativas desde el terreno

Microhistoria 1: Un incidente causado por una suposición equivocada

Una empresa SaaS mediana tenía una flota de servidores Ubuntu ejecutando un forwarder de logs como servicio systemd.
El forwarder comenzó a fallar tras una actualización de seguridad rutinaria. Los ingenieros vieron que el servicio usaba
un unit file en /lib/systemd/system y asumieron “es estable, no cambiará mucho.”

Meses antes, alguien había “editado temporalmente” la unidad del proveedor en su lugar para añadir una variable de entorno:
Environment=HTTP_PROXY=.... Estaba sin documentar, sin revisión e invisible para la gestión de configuración porque no estaba en /etc.
La actualización de seguridad reemplazó el paquete, y el proxy desapareció. El forwarder no pudo alcanzar el colector y los logs dejaron de fluir.

La alerta que saltó no fue “forwarder de logs caído”. Fue aguas abajo: un dashboard quedó en blanco silenciosamente,
luego un job de exportación de cumplimiento falló porque esperaba logs. La gente persiguió el sistema equivocado durante una hora.
La primera pista estuvo en journald: errores de conexión repetidos después de la hora de la actualización del paquete.

La solución fue aburrida: un drop-in bajo /etc/systemd/system para establecer el proxy, más una nota en el runbook.
La recomendación del postmortem fue más tajante: nunca cambiar unidades del proveedor directamente, e incorporar una comprobación de auditoría de unidades
en la detección de deriva de configuración.

Microhistoria 2: Una optimización que salió mal

Otra compañía ejecutaba un servicio sensible a latencia con ajustes agresivos de reinicio.
Alguien notó que después de un crash, el tiempo de recuperación era demasiado lento para su gusto.
Redujeron RestartSec a 100ms y aumentaron StartLimitBurst “para mantenerlo disponible.”

Redujo el tiempo entre crashes y reinicios. Ese fue el problema.
Un bug latente de configuración empezó a ocasionar fallos ocasionales. En lugar de un crash limpio y un reinicio estable,
el servicio entró en un bucle de caídas rápido. La CPU se disparó, los logs explotaron y otros servicios en la misma máquina
empezaron a perder deadlines por la presión de I/O.

Luego la contrapartida: el rate limiting de journald entró en acción. Los mismos logs necesarios para depurar la falla original se volvieron
incompletos. Mientras tanto, el sistema de monitorización veía “servicio arriba” intermitentemente y no paginó de inmediato.
Todos perdieron tiempo porque los síntomas se extendieron por toda la máquina.

La recuperación fue detener la unidad, revertir el override y luego reintroducir valores sensatos:
Restart=on-failure, RestartSec=2s y un límite de inicio moderado.
La verdadera optimización fue cambiar el chequeo de salud para detectar “reinicios rápidos” como fallo y alertar antes.

Microhistoria 3: Una práctica aburrida pero correcta que salvó el día

Una gran empresa tenía una política: todas las modificaciones systemd debían ser drop-ins, nombradas con un prefijo y un número de ticket,
y cada override debía ser visible en un informe de inventario extraído con systemctl show en cada host.
Sonaba a burocracia hasta que no lo fue.

Un proveedor envió una unidad actualizada para un agente crítico, cambiando las opciones por defecto de sandboxing.
En un subconjunto de servidores, el agente dejó de acceder a un directorio que necesitaba. El incidente pudo haberse convertido en una
búsqueda de “funciona en mi nodo” de varios días porque distintos equipos poseían distintos entornos.

En cambio, el ingeniero on-call sacó el informe de inventario y vio inmediatamente qué servidores tenían un override que tocaba
acceso al sistema de ficheros (p. ej., ReadWritePaths) y cuáles no. La convención de nombres del override lo hizo buscable.
Desplegaron un drop-in de una línea para alinear el comportamiento, reiniciaron el agente con seguridad y siguieron adelante.

La práctica no evitó el cambio del proveedor. Evitó la confusión. En producción, la claridad es una característica.

Errores comunes: síntoma → causa raíz → arreglo

1) “Mi override no se aplica”

Síntoma: Editaste un drop-in, reiniciaste el servicio y nada cambió.

Causa raíz: Olvidaste systemctl daemon-reload, o editaste un archivo en la ruta equivocada, o una unidad completa en /etc suplanta al proveedor + drop-ins.

Arreglo: Ejecuta systemctl show -p FragmentPath -p DropInPaths unit; luego daemon-reload; luego systemctl cat unit para confirmar la configuración fusionada.

2) “Sobrescribí ExecStart y ahora no arranca”

Síntoma: El servicio falla con mensajes extraños, o intenta ejecutar múltiples comandos.

Causa raíz: Añadiste ExecStart=... sin limpiar la lista existente.

Arreglo: En tu drop-in: añade una línea en blanco ExecStart= antes del nuevo ExecStart=.... Recarga y reinicia.

3) “La actualización del paquete revirtió mi arreglo”

Síntoma: El comportamiento del servicio cambia justo después de apt upgrade.

Causa raíz: Editaste /lib/systemd/system/*.service directamente (territorio del proveedor).

Arreglo: Vuelve a aplicar el cambio como un drop-in bajo /etc/systemd/system/<unit>.d/. Considera systemctl revert para limpiar copias accidentales de unidades completas.

4) “Arranca manualmente pero no via systemd”

Síntoma: Ejecutar el binario en una shell funciona; start vía systemd falla.

Causa raíz: Variables de entorno faltantes, directorio de trabajo distinto, o sandboxing más estricto en el contexto de systemd.

Arreglo: Compara systemctl show -p Environment -p WorkingDirectory; añade EnvironmentFile= o WorkingDirectory= en un drop-in; verifica logs.

5) “El servicio oscila y deja la máquina inservible”

Síntoma: CPU alta, logs masivos, “el servicio sigue reiniciándose”.

Causa raíz: Política de reinicio demasiado agresiva (Restart=always, RestartSec minúsculo), o un bucle real de crashes enmascarado por el auto-restart.

Arreglo: Ralentízalo: Restart=on-failure, RestartSec=2s. Detén la unidad, captura logs, arregla la causa raíz y luego reinicia.

6) “Mi override se rompió después de añadir varios drop-ins”

Síntoma: Las configuraciones parecen “cambiar aleatoriamente” según el host.

Causa raíz: El orden de los drop-ins difiere o otro archivo sobreescribe la misma directiva más tarde.

Arreglo: Usa numeración explícita (10-, 20-, 90-). Comprueba DropInPaths. Consolida directivas en conflicto.

7) “No ve un directorio montado en el arranque”

Síntoma: El servicio falla en el arranque, pero funciona tras un reinicio manual.

Causa raíz: Faltan dependencias de orden en la unidad de montaje; el servicio arranca antes de que el sistema de ficheros esté listo.

Arreglo: Añade un drop-in con RequiresMountsFor=/path o los apropiados After=/Requires=. Recarga y prueba el comportamiento al reiniciar.

Listas de verificación / plan paso a paso

Checklist A: Hacer un override seguro (el enfoque por defecto)

  1. Obtén la verdad actual: systemctl cat unit y systemctl show -p FragmentPath -p DropInPaths unit.
  2. Decide el cambio más pequeño posible (límites, env, orden, política de reinicio).
  3. Crea drop-in: sudo systemctl edit unit.
  4. Añade sólo las directivas que necesitas. Evita copiar el unit del proveedor.
  5. Valida sintaxis si tocaste cosas complejas: systemd-analyze verify ....
  6. sudo systemctl daemon-reload.
  7. Reinicia y verifica: sudo systemctl restart unit luego systemctl status unit.
  8. Prueba la configuración efectiva: systemctl show -p ... unit.
  9. Prueba el efecto en tiempo de ejecución (límites/env) vía /proc o diagnósticos específicos del servicio.

Checklist B: Debes reemplazar ExecStart (cambio de alto riesgo)

  1. Captura el ExecStart actual: systemctl show -p ExecStart unit.
  2. Crea un archivo drop-in dedicado (no lo escondas): /etc/systemd/system/unit.d/10-execstart.conf.
  3. Resetea la lista primero: incluye una línea en blanco ExecStart=.
  4. Incluye cualquier ExecStartPre=, WorkingDirectory= y archivos de entorno necesarios.
  5. Verifica: systemd-analyze verify.
  6. Recarga y reinicia.
  7. Tén listo un rollback: systemctl revert unit (o elimina el drop-in) y reinicia.

Checklist C: Revertir y volver a la línea base

  1. Detén el servicio si está oscilando: sudo systemctl stop unit.
  2. Haz snapshot de la unidad fusionada actual: systemctl cat unit en tus notas de incidente.
  3. Revertir overrides: sudo systemctl revert unit.
  4. Recarga: sudo systemctl daemon-reload.
  5. Arranca: sudo systemctl start unit.
  6. Confirma logs: journalctl -u unit -n 50.

Preguntas frecuentes

1) ¿Debo alguna vez editar archivos en /lib/systemd/system?

No, no como práctica. Trátalo como firmware del proveedor: legible, no editable. Usa drop-ins en /etc/systemd/system.
Si debes experimentar, hazlo en un host desechable y traduce el resultado a un override.

2) ¿Cuál es la diferencia entre systemctl edit y editar un archivo manualmente?

systemctl edit crea la estructura de directorios correcta, abre el archivo adecuado y se alinea con el modelo de systemd.
Las ediciones manuales están bien si conoces las rutas, pero systemctl edit reduce errores de “ubicación equivocada”.

3) ¿Por qué mi override de ExecStart= no reemplazó al anterior?

Porque ExecStart es de tipo lista. Añade una línea en blanco ExecStart= para limpiar la lista primero, luego añade tu nuevo ExecStart=....

4) ¿Cómo veo la unidad final que usa systemd?

Usa systemctl cat unit para la configuración fusionada y systemctl show -p FragmentPath -p DropInPaths unit para ver fuentes y drop-ins aplicados.

5) ¿Necesito daemon-reload cada vez?

Si cambiaste archivos de unidad o drop-ins, sí. Reiniciar un servicio no implica confiablemente volver a leer la definición de unidad.
daemon-reload es barato; los outages no lo son.

6) ¿Cuál es la forma más limpia de eliminar un override?

sudo systemctl revert unit. Elimina los drop-ins y devuelve a los valores por defecto del proveedor. Luego ejecuta daemon-reload.

7) ¿Puedo usar drop-ins para cambiar dependencias como After= y Requires=?

Sí, y es uno de los mejores usos. Si un servicio depende de un montaje, considera RequiresMountsFor=/path.
Para dependencias de red, ten cuidado: “red arriba” no es lo mismo que “dependencia remota alcanzable”.

8) Mi override funciona en un servidor pero no en otro. ¿Por qué?

Razones más comunes: otro drop-in lo sobreescribe después; hay una unidad completa en /etc en un host; o un generator produjo algo en /run.
Compara systemctl show -p FragmentPath -p DropInPaths entre hosts.

9) ¿Es mejor poner todo en un solo override.conf?

No siempre. Un archivo es fácil hasta que se convierte en un cajón de trastos. Para cambios mayores, separa drop-ins por propósito con numeración:
10-limits.conf, 20-env.conf, 90-hardening.conf. El orden queda explícito.

10) ¿Cómo confirmo que mis cambios de límites aplican realmente al proceso?

Obtén el PID con systemctl show -p MainPID y revisa /proc/<pid>/limits. Eso es lo que el kernel hace cumplir.

Conclusión: próximos pasos que puedes hacer hoy

En Ubuntu 24.04, los overrides de systemd son la forma adulta de arreglar servicios. Sobreviven a las actualizaciones, mantienen tu intención separada de los valores del proveedor,
y hacen la respuesta a incidentes más rápida porque la pregunta “qué cambió” se responde en segundos.

Pasos prácticos siguientes:

  • Elige un servicio que hayas “tocado” antes. Ejecuta systemctl show -p FragmentPath -p DropInPaths y comprueba si hay ediciones en /lib.
  • Si las hay, migra los cambios a un drop-in bajo /etc/systemd/system/<unit>.d/.
  • Estandariza la nomenclatura de drop-ins (numerados, por propósito). Tu yo del futuro es una persona distinta con distinto sueño.
  • Enseña a tu equipo dos comandos: systemctl cat y systemctl revert. Uno encuentra la verdad; el otro te compra un rollback.

Haz esto unas cuantas veces y dejarás de tratar a systemd como una caja negra. No es magia. Es sólo muy particular respecto a dónde pones tus ediciones.

← Anterior
VPN sitio a sitio: conectar dos oficinas en una sola red (un plan simple que funciona)
Siguiente →
DNS: zona BIND9 no carga — errores de sintaxis comunes y soluciones rápidas

Deja un comentario