logrotate es la herramienta que usa Linux para que los ficheros de log no crezcan sin límite: los renombra periódicamente, comprime las copias antiguas y borra las que superan el periodo de retención. En Ubuntu 24.04 ya se encarga de los logs del sistema; tu trabajo es añadir reglas para los logs de tus propias aplicaciones. En esta guía entenderás cómo se ejecuta logrotate, escribirás una regla para una aplicación, la probarás sin riesgo y verás cómo rotar por tamaño o con más frecuencia.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Una aplicación que escriba logs en ficheros. Si no tienes ninguna, en el paso 2 crearás un log de ejemplo.

Paso 1: Entender cómo se ejecuta logrotate

logrotate viene instalado en Ubuntu. Comprueba la versión:

logrotate --version
logrotate 3.21.0

logrotate no es un servicio que esté siempre en marcha: se ejecuta una vez al día mediante un temporizador de systemd, revisa todas las reglas y rota lo que toca. Consulta cuándo es la próxima ejecución:

systemctl list-timers logrotate.timer
NEXT                        LEFT     LAST                        PASSED  UNIT            ACTIVATES
Fri 2026-09-26 00:00:00 UTC 13h left Thu 2026-09-25 00:00:04 UTC 10h ago logrotate.timer logrotate.service

Y el resultado de la última ejecución:

journalctl -u logrotate.service -n 20 --no-pager

La configuración se reparte en tres sitios:

RutaUso
/etc/logrotate.confOpciones globales por defecto e inclusión de /etc/logrotate.d
/etc/logrotate.d/Una regla por aplicación o paquete (nginx, rsyslog, apt...)
/var/lib/logrotate/statusFecha de la última rotación de cada fichero

Echa un vistazo a la configuración global:

grep -v '^#' /etc/logrotate.conf | grep -v '^$'
weekly
su root adm
rotate 4
create
include /etc/logrotate.d

Estas opciones se aplican a todas las reglas salvo que una regla las redefina: rotación semanal, 4 copias y crear un fichero vacío tras rotar. Lo habitual es no tocar este fichero y poner todo lo específico en /etc/logrotate.d/.

Paso 2: Preparar un log de ejemplo

Para practicar, simula una aplicación llamada myapp que escribe en /var/log/myapp/, con un usuario propio. Si ya tienes una aplicación real, adapta rutas y usuarios.

Crea el usuario y el directorio. El directorio pertenece a root y solo los ficheros de log pertenecen a la aplicación; así logrotate puede trabajar como root sin problemas de permisos:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo mkdir -p /var/log/myapp
sudo install -o myapp -g adm -m 0640 /dev/null /var/log/myapp/app.log
sudo install -o myapp -g adm -m 0640 /dev/null /var/log/myapp/error.log

Genera algo de contenido escribiendo como el usuario de la aplicación:

for i in $(seq 1 2000); do echo "$(date -Is) petición $i atendida"; done | sudo -u myapp tee -a /var/log/myapp/app.log > /dev/null
echo "$(date -Is) error de ejemplo" | sudo -u myapp tee -a /var/log/myapp/error.log > /dev/null
ls -l /var/log/myapp
-rw-r----- 1 myapp adm 88893 Sep 25 10:50 app.log
-rw-r----- 1 myapp adm    43 Sep 25 10:50 error.log

Paso 3: Escribir la regla de rotación

Crea un fichero en /etc/logrotate.d/ con el nombre de la aplicación:

sudo nano /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d
    create 0640 myapp adm
    sharedscripts
    postrotate
        systemctl kill --signal=HUP myapp.service > /dev/null 2>&1 || true
    endscript
}

Qué hace cada directiva:

  • daily: rota cada día. Otras opciones son weekly, monthly y yearly.
  • rotate 14: conserva 14 copias; la más antigua se borra.
  • missingok: no da error si no hay ficheros que coincidan.
  • notifempty: no rota ficheros vacíos.
  • compress y delaycompress: comprime con gzip, pero deja sin comprimir la copia más reciente. Así, si la aplicación tarda en soltar el fichero antiguo, puede seguir escribiendo en él sin corromper nada.
  • dateext y dateformat: las copias se llaman app.log-20260925 en lugar de app.log.1, lo que facilita encontrarlas por fecha.
  • create 0640 myapp adm: tras rotar, crea un fichero vacío con esos permisos y propietario.
  • sharedscripts: ejecuta postrotate una sola vez aunque el patrón *.log coincida con varios ficheros.
  • postrotate ... endscript: comandos que se ejecutan después de rotar. Aquí se envía SIGHUP al servicio para que cierre el fichero antiguo y abra el nuevo. El || true evita que la regla falle si el servicio no está en marcha.

Paso 4: Probar la regla

Antes de esperar a la ejecución nocturna, prueba la regla en modo depuración. Con -d logrotate muestra lo que haría sin tocar nada ni actualizar el fichero de estado:

sudo logrotate -d /etc/logrotate.d/myapp
reading config file /etc/logrotate.d/myapp
...
rotating pattern: /var/log/myapp/*.log  after 1 days (14 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/myapp/app.log
Creating new state
  Now: 2026-09-25 10:52
  Last rotated at 2026-09-25 10:00
  log does not need rotating (log has been already rotated)

La primera vez que logrotate ve un fichero lo registra en el estado sin rotarlo, por eso dice que no hace falta. Para comprobar que la rotación funciona de verdad, fuérzala con -f y muestra el detalle con -v:

sudo logrotate -f -v /etc/logrotate.d/myapp

Revisa el resultado:

ls -l /var/log/myapp
-rw-r----- 1 myapp adm     0 Sep 25 10:53 app.log
-rw-r----- 1 myapp adm 88893 Sep 25 10:50 app.log-20260925
-rw-r----- 1 myapp adm     0 Sep 25 10:53 error.log
-rw-r----- 1 myapp adm    43 Sep 25 10:50 error.log-20260925

Los ficheros actuales están vacíos, con los permisos de create, y las copias llevan la fecha. No están comprimidas por delaycompress: se comprimirán en la siguiente rotación.

Por último, confirma que la configuración completa sigue siendo válida, porque un error de sintaxis en cualquier fichero de /etc/logrotate.d/ puede afectar a la ejecución diaria:

sudo logrotate -d /etc/logrotate.conf 2>&1 | grep -i error

Si no aparece nada, no hay errores.

Paso 5: Usar copytruncate cuando la aplicación no reabre el log

Algunas aplicaciones abren el fichero de log al arrancar y nunca lo sueltan. Si logrotate lo renombra, siguen escribiendo en la copia antigua y el log nuevo queda vacío. Para ellas existe copytruncate: copia el contenido a la copia rotada y después vacía el original, sin que la aplicación note nada.

/var/log/legacyapp/*.log {
    daily
    rotate 7
    missingok
    notifempty
    compress
    delaycompress
    copytruncate
}

Con copytruncate no hace falta create ni postrotate. Su inconveniente es que las líneas escritas entre la copia y el vaciado se pueden perder, así que úsalo solo cuando la aplicación no ofrezca una forma de reabrir el log.

Paso 6: Rotar por tamaño

Si una aplicación genera mucho log de forma irregular, la rotación por tiempo puede dejar ficheros enormes. Tienes tres directivas:

  • size 100M: rota cuando el fichero supera 100 MB, ignorando la frecuencia (daily, weekly).
  • maxsize 100M: rota según la frecuencia configurada, pero también antes si supera 100 MB.
  • minsize 1M: rota según la frecuencia, pero solo si el fichero tiene al menos 1 MB.

La opción más práctica suele ser maxsize, combinada con una frecuencia. Así quedaría la regla de myapp en /etc/logrotate.d/myapp (sustituye la anterior, porque un mismo fichero no puede estar en dos reglas):

/var/log/myapp/*.log {
    daily
    maxsize 100M
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d-%H
    create 0640 myapp adm
    sharedscripts
    postrotate
        systemctl kill --signal=HUP myapp.service > /dev/null 2>&1 || true
    endscript
}

Fíjate en el dateformat con la hora (-%H): si la rotación por tamaño ocurre más de una vez al día, cada copia necesita un nombre distinto.

Ten en cuenta que logrotate solo comprueba el tamaño cuando se ejecuta, y por defecto lo hace una vez al día. Para que maxsize o size actúen a tiempo, ejecútalo cada hora sobrescribiendo el temporizador:

sudo systemctl edit logrotate.timer

Añade en la zona editable:

[Timer]
OnCalendar=
OnCalendar=hourly

La línea OnCalendar= vacía borra el valor original antes de fijar el nuevo. Guarda y comprueba el cambio:

systemctl list-timers logrotate.timer

La columna NEXT debe mostrar la próxima hora en punto. Las reglas con daily no se ven afectadas: logrotate consulta el fichero de estado y solo las rota una vez al día.

Solución de problemas

error: skipping "/var/log/myapp/app.log" because parent directory has insecure permissions. El directorio es escribible por cualquier usuario o por un grupo distinto de root, y logrotate se niega a trabajar en él por seguridad. Deja el directorio como propiedad de root (como en el paso 2) o añade a la regla la directiva su con el usuario y grupo propietarios del directorio, por ejemplo su myapp myapp.

La aplicación sigue escribiendo en app.log-20260925 y app.log queda vacío. La aplicación no ha reabierto el fichero. Revisa que el comando de postrotate sea el correcto para ella o cambia a copytruncate.

La regla nunca rota. Comprueba en /var/lib/logrotate/status la fecha registrada para el fichero y revisa la última ejecución con journalctl -u logrotate.service. Un error de sintaxis en otra regla puede aparecer ahí.

error: /etc/logrotate.d/myapp:1 duplicate log entry for /var/log/myapp/app.log. El mismo fichero está cubierto por dos reglas. Cada log debe aparecer en una sola.

Conclusión

Has visto cómo se ejecuta logrotate en Ubuntu 24.04, has creado una regla con compresión, retención de 14 días y recarga del servicio, la has probado con -d y -f, y sabes cuándo usar copytruncate y cómo rotar por tamaño. Como siguientes pasos, revisa las reglas que ya instalan paquetes como Nginx en /etc/logrotate.d/ para usarlas de modelo, limita también el tamaño del diario de systemd con SystemMaxUse y envía los logs antiguos a un almacenamiento externo si necesitas conservarlos más tiempo.