Los logs de un servidor crecen sin parar: si no se rotan acaban llenando el disco, y si se borran demasiado pronto no estarán disponibles cuando tengas que investigar un incidente o responder a una auditoría. En Linux hay dos piezas que controlan esto: logrotate, que rota los ficheros de texto de /var/log, y systemd-journald, que gestiona su propio almacén binario. En este tutorial definirás una política de retención y la aplicarás con ambas herramientas en Ubuntu 24.04: una aplicación propia, los logs de autenticación con retención de un año y el journal con un límite de tamaño y antigüedad.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. En Debian 12 los comandos son los mismos.
- Un usuario no root con privilegios
sudo. - Espacio libre suficiente en disco para la retención que elijas (en el paso 1 verás cómo estimarlo).
Paso 1: Definir la política de retención
Antes de tocar configuración, decide cuánto tiempo necesitas conservar cada tipo de log y dónde. Las normativas más habituales fijan estos mínimos:
| Norma | Qué exige sobre los logs |
|---|---|
| PCI DSS v4.0 (requisito 10.5.1) | Conservar el historial de auditoría al menos 12 meses, con los últimos 3 meses disponibles de inmediato |
| RGPD | No fija un plazo: los logs con datos personales solo se conservan el tiempo necesario para su finalidad |
| ISO/IEC 27001 | No fija un plazo: debe estar definido en tu política y aplicarse de forma consistente |
NotaConsulta con tu responsable de cumplimiento el plazo exacto que aplica a tu caso. Esta guía usa un ejemplo habitual: 30 días para logs de aplicación y 12 meses para los de autenticación.
Para estimar cuánto ocupará, mira el tamaño actual de los logs y cuánto crecen al día:
sudo du -sh /var/log/*.log /var/log/*/ 2>/dev/null | sort -h | tail -n 10
Un log de texto comprimido con gzip suele quedarse en un 5-10 % de su tamaño original, así que 12 meses de auth.log rara vez superan unos pocos cientos de megabytes.
Paso 2: Revisar cómo funciona logrotate en Ubuntu
logrotate viene instalado en Ubuntu. Comprueba la versión y que el temporizador de systemd que lo ejecuta cada día está activo:
logrotate --version
systemctl list-timers logrotate.timer
logrotate 3.21.0
...
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2026-09-26 00:00:00 UTC 13h left Thu 2026-09-25 00:00:03 UTC 10h ago logrotate.timer logrotate.service
La configuración se reparte en dos sitios:
/etc/logrotate.conf: valores por defecto globales (en Ubuntu, rotación semanal y 4 copias) y la líneainclude /etc/logrotate.d./etc/logrotate.d/: un fichero por paquete o aplicación (rsyslog,nginx,apt...). Las directivas de cada bloque sustituyen a las globales.
logrotate guarda la fecha de la última rotación de cada fichero en /var/lib/logrotate/status. Así sabe si toca rotar, aunque el servidor haya estado apagado.
Las directivas que vas a usar en esta guía son:
| Directiva | Qué hace |
|---|---|
daily, weekly, monthly | Frecuencia de rotación |
rotate N | Número de ficheros rotados que se conservan; el más antiguo se borra |
maxsize 100M | Rota antes de tiempo si el fichero supera ese tamaño (se evalúa cada vez que se ejecuta logrotate) |
compress / delaycompress | Comprime con gzip los rotados, dejando sin comprimir el más reciente |
dateext | Añade la fecha al nombre en lugar de un número (app.log-20260925) |
missingok / notifempty | No da error si falta el fichero y no rota ficheros vacíos |
create 0640 usuario grupo | Crea el fichero nuevo con esos permisos tras rotar |
copytruncate | Copia el fichero y lo vacía, para aplicaciones que no saben reabrir su log |
postrotate ... endscript | Comando que se ejecuta tras rotar, normalmente para que el servicio reabra el log |
Paso 3: Rotar los logs de una aplicación propia
Supón una aplicación que se ejecuta como servicio systemd miapp.service, con el usuario miapp, y escribe en /var/log/miapp/. Sustituye estos nombres por los de tu aplicación. Si todavía no existe, crea el directorio con el propietario correcto:
sudo install -d -m 0750 -o miapp -g adm /var/log/miapp
Crea el fichero de configuración de logrotate:
sudo nano /etc/logrotate.d/miapp
Añade este bloque:
/var/log/miapp/*.log {
daily
rotate 30
maxsize 100M
missingok
notifempty
compress
delaycompress
dateext
dateformat -%Y%m%d-%s
create 0640 miapp adm
su miapp adm
sharedscripts
postrotate
systemctl kill --signal=HUP miapp.service >/dev/null 2>&1 || true
endscript
}
Qué hace cada parte importante:
dailyconrotate 30conserva 30 días.maxsize 100Mrota antes si un día hay un pico de tráfico.dateformat -%Y%m%d-%sincluye la marca de tiempo en segundos, para que dos rotaciones el mismo día (pormaxsize) no choquen de nombre.su miapp admhace que logrotate trabaje con ese usuario. Es necesario cuando el directorio no pertenece a root; sin él, logrotate se niega a rotar por seguridad.- El bloque
postrotateenvíaSIGHUPal servicio para que reabra el fichero.sharedscriptshace que se ejecute una sola vez aunque haya varios.log.
Si tu aplicación no reabre el log con SIGHUP, elimina el bloque postrotate ... endscript y la línea create, y añade copytruncate. Funciona con cualquier programa, a cambio de poder perder las líneas escritas justo entre la copia y el vaciado.
Comprueba la configuración en modo de prueba. La opción -d muestra lo que haría sin tocar nada:
sudo logrotate -d /etc/logrotate.d/miapp
reading config file /etc/logrotate.d/miapp
...
rotating pattern: /var/log/miapp/*.log after 1 days (30 rotations)
empty log files are not rotated, old logs are removed
switching euid from 0 to 999 and egid from 0 to 4
considering log /var/log/miapp/app.log
Now: 2026-09-25 10:20
Last rotated at 2026-09-25 10:00
log does not need rotating (log has already been rotated)
Fuerza una rotación real para verificar que el servicio sigue escribiendo en el fichero nuevo:
sudo logrotate -f -v /etc/logrotate.d/miapp
ls -l /var/log/miapp/
-rw-r----- 1 miapp adm 0 Sep 25 10:21 app.log
-rw-r----- 1 miapp adm 48213 Sep 25 10:21 app.log-20260925-1758795660
Tras la siguiente rotación, app.log-20260925-... se comprimirá como .gz por el efecto de delaycompress. Espera a que la aplicación registre algo y confirma que app.log vuelve a crecer.
Paso 4: Conservar los logs de autenticación durante 12 meses
En Ubuntu, /var/log/auth.log lo escribe rsyslog y lo rota el bloque de /etc/logrotate.d/rsyslog, que solo guarda 4 semanas. No puedes declarar el mismo fichero en dos bloques (logrotate falla con duplicate log entry), así que primero quítalo del bloque de rsyslog:
sudo nano /etc/logrotate.d/rsyslog
Borra la línea /var/log/auth.log de la lista de ficheros y guarda. El resto del bloque queda igual.
Nota
/etc/logrotate.d/rsysloges un fichero de configuración del paquete. Si una actualización de rsyslog trae una versión nueva, apt te preguntará si conservas la tuya: responde que sí para no perder el cambio.
Crea un bloque propio para auth.log:
sudo nano /etc/logrotate.d/auth-retention
/var/log/auth.log {
weekly
rotate 53
missingok
notifempty
compress
delaycompress
dateext
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
Con rotación semanal y 53 copias conservas algo más de 12 meses. El script rsyslog-rotate es el mismo que usa el bloque original para que rsyslog reabra sus ficheros.
Valida toda la configuración de logrotate, no solo el fichero nuevo, para detectar duplicados:
sudo logrotate -d /etc/logrotate.conf 2>&1 | grep -iE 'error|duplicate' || echo "Configuración correcta"
Configuración correcta
Paso 5: Limitar el tamaño y la antigüedad del journal
Además de los ficheros de texto, systemd-journald guarda los logs de todos los servicios en /var/log/journal/. Por defecto no borra nada hasta ocupar el 10 % del sistema de ficheros (con un máximo de 4 GB), sin límite de antigüedad. Mira cuánto ocupa ahora:
journalctl --disk-usage
Archived and active journals take 612.0M in the file system.
Crea un fichero de configuración adicional en lugar de editar el principal, para que las actualizaciones no lo sobrescriban:
sudo mkdir -p /etc/systemd/journald.conf.d
sudo nano /etc/systemd/journald.conf.d/retention.conf
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=2G
MaxRetentionSec=90d
Storage=persistentgarantiza que el journal se guarda en disco y sobrevive a los reinicios.SystemMaxUselimita el espacio total, ySystemKeepFreedeja siempre ese margen libre en el disco.MaxRetentionSec=90dborra las entradas de más de 90 días aunque quede espacio.
Aplica los cambios reiniciando el servicio:
sudo systemctl restart systemd-journald
Para limpiar de inmediato lo que ya supera el nuevo límite, usa --vacuum-time o --vacuum-size:
sudo journalctl --vacuum-time=90d
Vacuuming done, freed 0B of archived journals from /var/log/journal/...
Comprueba cuál es la entrada más antigua que se conserva:
journalctl -q -o short-iso --no-pager | head -n 1
2026-06-27T08:14:02+00:00 servidor kernel: Linux version 6.8.0-84-generic ...
Si necesitas que el journal cubra 12 meses, sube MaxRetentionSec a 1year y ajusta SystemMaxUse a lo que estimaste en el paso 1. El journal no se comprime tan bien como gzip, así que para retenciones largas suele ser más eficiente conservar los ficheros de texto rotados y dejar el journal en unas semanas.
Paso 6: Verificar la política con el tiempo
La primera rotación no demuestra que la retención funciona: lo que importa es que los ficheros antiguos se borren al llegar al límite. Pasadas unas semanas, revisa:
ls -1 /var/log/miapp/ | wc -l
ls -1 /var/log/auth.log* | head -n 3
sudo grep -E 'miapp|auth.log' /var/lib/logrotate/status
31
/var/log/auth.log
/var/log/auth.log-20260920
/var/log/auth.log-20260913.gz
"/var/log/miapp/app.log" 2026-9-25-0:0:3
"/var/log/auth.log" 2026-9-20-0:0:2
Si se ejecuta logrotate con errores, aparecerán en su servicio:
journalctl -u logrotate.service --since "7 days ago"
Recuerda que los logs de un único servidor desaparecen con él. Para cumplir retenciones largas de forma fiable, copia los ficheros rotados (*.gz) a otro sistema, por ejemplo un servidor de backups o almacenamiento de objetos, y aplica allí también la política de borrado.
Solución de problemas
error: skipping "/var/log/miapp/app.log" because parent directory has insecure permissions: el directorio no pertenece a root o es escribible por un grupo distinto de root. Añade la directivasu usuario grupocon el propietario del directorio, como en el paso 3.error: duplicate log entry for /var/log/auth.log: el mismo fichero aparece en dos bloques. Elimínalo de uno de ellos.- La aplicación sigue escribiendo en el fichero rotado (
app.log-2026...crece yapp.logse queda vacío): el servicio no reabre el log. Revisa que responde aSIGHUPo cambia acopytruncate. maxsizeno rota a tiempo: logrotate solo se ejecuta una vez al día. Si necesitas comprobarlo más a menudo, crea un override consudo systemctl edit logrotate.timery define[Timer]con una líneaOnCalendar=vacía seguida deOnCalendar=hourly.
Conclusión
Tienes una política de retención definida y aplicada: 30 días con límite de tamaño para la aplicación, 12 meses para los logs de autenticación y el journal acotado en espacio y antigüedad. Como siguientes pasos, puedes registrar las acciones administrativas con auditd, eliminar datos personales de los logs antes de conservarlos con la guía de anonimización de logs, y centralizar los logs de varios servidores en un único sistema con su propia retención.
