Skip to content

Logrotate è l’utility standard di Linux per la gestione automatizzata dei file di log testuali. Opera attraverso rotazione, compressione e rimozione programmata, evitando che i log di servizi come Nginx, Apache, MySQL e PHP-FPM saturino il disco. Su un web server LEMP/LAMP di produzione, logrotate gestisce tipicamente 15-30 configurazioni distinte.

Questa guida copre l’intero ciclo operativo di logrotate: dall’installazione alla configurazione avanzata, dall’esecuzione con systemd timer (che ha sostituito cron come default) fino alle configurazioni production-ready per i servizi più comuni. Include anche le sezioni su journald, container Docker/Kubernetes, sicurezza e troubleshooting.

A riguardo potrebbe interessarti la guida su come leggere il log del web server e l’approfondimento sull’analisi dei log di un web server Linux.

Cos’è logrotate e perché è ancora rilevante

Nel panorama Linux attuale convivono due sistemi di logging. Da un lato systemd-journald, che raccoglie log strutturati in formato binario da tutti i servizi gestiti da systemd, interrogabili con journalctl. Dall’altro, i tradizionali file di log testuali scritti direttamente dalle applicazioni in /var/log/ o in directory custom.

Logrotate opera esclusivamente sulla seconda categoria. Servizi come Nginx, Apache, MySQL, PHP-FPM, Varnish e qualsiasi applicazione custom che scrive log su file di testo necessitano ancora di un meccanismo di rotazione esterno. Senza logrotate, un access log di Nginx su un sito con 50.000 visite/giorno può crescere di 500 MB al mese, saturando rapidamente il disco.

Logrotate risolve il problema con un approccio dichiarativo: per ogni file di log si definisce una configurazione che specifica frequenza di rotazione, numero di copie da conservare, compressione, e comandi da eseguire prima o dopo la rotazione. Il tutto viene eseguito automaticamente da un timer di sistema.

Se logrotate è già installato sulla macchina, basta aprire una shell ed eseguire il comando seguente per verificare come i log di sistema vengano periodicamente ruotati e compressi:

ls -lh /var/log/*.gz /var/log/*.1 2>/dev/null

Installazione e versioni

Logrotate è preinstallato su tutte le distribuzioni Linux server principali. In caso contrario, l’installazione richiede un singolo comando.

Installazione su distribuzioni principali

# Debian / Ubuntu
apt install logrotate

# RHEL 9 / Rocky Linux / AlmaLinux
dnf install logrotate

# Verifica versione installata
logrotate --version

L’installazione crea i seguenti file e directory:

  • /etc/logrotate.conf — configurazione principale
  • /etc/logrotate.d/ — configurazioni per-servizio
  • /var/lib/logrotate/status — file di stato con i timestamp delle ultime rotazioni
  • /lib/systemd/system/logrotate.timer — timer systemd (distribuzioni moderne)

Versioni recenti e changelog

Il progetto logrotate è ospitato su GitHub e rilascia aggiornamenti regolari. Le versioni recenti hanno introdotto miglioramenti significativi in termini di sicurezza e funzionalità.

VersioneDataNovità principali
3.22.0Giugno 2024Specifier %z in dateformat per offset timezone. Nomi utente/gruppo tra virgolette nella direttiva create. Permessi default olddir impostati a 0755. File di stato non scritto su file non regolari.
3.21.0Dicembre 2023Nuova direttiva ignoreduplicates per pattern che matchano file duplicati. Opzione CLI --wait-for-state-lock per sincronizzazione tra istanze concorrenti. Espansione home directory in olddir.
3.20.1Maggio 2023Fix critico CVE-2022-1348: vulnerabilità denial-of-service via file di stato. Hardening permessi del file di stato. Supporto time_t unsigned.

Architettura di logrotate nel sistema operativo

Logrotate non è un demone residente in memoria. È un comando che viene eseguito periodicamente da un trigger esterno — storicamente cron, oggi systemd timer. A ogni esecuzione, logrotate segue questo flusso:

  1. Legge la configurazione principale (/etc/logrotate.conf) e tutti i file inclusi tramite la direttiva include
  2. Consulta il file di stato (/var/lib/logrotate/status) per determinare la data dell’ultima rotazione di ogni file di log
  3. Per ogni file di log configurato, verifica se le condizioni di rotazione sono soddisfatte (tempo trascorso, dimensione del file)
  4. Esegue la rotazione: rinomina i file, crea nuovi file, esegue gli script prerotate/postrotate, comprime i file archiviati
  5. Aggiorna il file di stato con i nuovi timestamp

La configurazione è modulare: /etc/logrotate.conf contiene i default globali e una direttiva include /etc/logrotate.d che carica tutti i file presenti in quella directory. Ogni pacchetto software installa la propria configurazione in /etc/logrotate.d/, mantenendo il sistema organizzato e manutenibile.

Esecuzione con systemd timer

Su RHEL 9, Ubuntu 22.04+, Debian 12 e le distribuzioni derivate, logrotate non viene più eseguito tramite cron. Il meccanismo di default è un systemd timer, che offre vantaggi significativi in termini di affidabilità, logging e controllo delle risorse.

Perché systemd timer ha sostituito cron

Il passaggio da cron a systemd timer non è stato arbitrario. I timer systemd risolvono problemi concreti che cron non gestisce nativamente: esecuzione garantita dopo il boot se il timer è scaduto durante lo spegnimento (Persistent=true), integrazione diretta con il journal per logging centralizzato, isolamento delle risorse tramite cgroup, e gestione delle dipendenze tra servizi.

Su RHEL 9, il file /etc/cron.daily/logrotate non esiste più. Su Ubuntu 24.04, il pacchetto logrotate installa direttamente le unità systemd senza dipendenza da cron.

Unità logrotate.timer e logrotate.service

Il timer è composto da due file unit. Il primo definisce la schedulazione:

# /lib/systemd/system/logrotate.timer
[Unit]
Description=Daily rotation of log files

[Timer]
OnCalendar=daily
AccuracySec=12h
Persistent=true

[Install]
WantedBy=timers.target

Il secondo definisce il comando da eseguire:

# /lib/systemd/system/logrotate.service
[Unit]
Description=Rotate log files

[Service]
Type=oneshot
ExecStart=/usr/sbin/logrotate /etc/logrotate.conf

OnCalendar=daily schedula l’esecuzione una volta al giorno. AccuracySec=12h consente a systemd di ritardare l’esecuzione fino a 12 ore per ottimizzare le risorse. Persistent=true garantisce che, se il timer è scaduto durante lo spegnimento della macchina, logrotate venga eseguito immediatamente al boot successivo.

Comandi di gestione

# Verificare che il timer sia attivo
systemctl status logrotate.timer

# Vedere tutti i timer schedulati
systemctl list-timers --all | grep logrotate

# Consultare i log delle esecuzioni precedenti
journalctl -u logrotate.service --since "7 days ago"

# Eseguire manualmente (senza aspettare il timer)
systemctl start logrotate.service

Personalizzazione della frequenza

Per modificare la frequenza di esecuzione, ad esempio ogni 6 ore per server ad alto traffico, creare un override con systemctl edit:

# Crea un override del timer
systemctl edit logrotate.timer

Inserire nel file di override:

[Timer]
OnCalendar=
OnCalendar=*-*-* 00/6:00:00

La prima riga OnCalendar= (vuota) resetta il valore precedente; la seconda imposta l’esecuzione ogni 6 ore. Dopo la modifica, ricaricare la configurazione con systemctl daemon-reload.

Confronto systemd timer vs cron

Aspettosystemd timercron
LoggingIntegrato in journald, consultabile con journalctlDipende da syslog/rsyslog
Catch-up dopo rebootPersistent=true esegue al boot se scadutoRichiede anacron
Isolamento risorseSupporto cgroup nativoNessuno
DipendenzeAfter/Requires per ordinamentoNon supportato
Debuggingsystemctl status, journalctl -uGrep su /var/log/syslog
DistribuzioneDefault su RHEL 9, Ubuntu 22.04+, Debian 12Legacy, ancora presente su sistemi più vecchi

Esecuzione con cron (legacy)

Sui sistemi che non utilizzano systemd o su distribuzioni più datate, logrotate viene eseguito tramite uno script in /etc/cron.daily/. Questo metodo è ancora funzionante ma non è più il default sulle distribuzioni recenti.

Lo script /etc/cron.daily/logrotate ha un contenuto minimale:

#!/bin/sh
test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

Lo script verifica l’esistenza del binario logrotate e lo esegue con il file di configurazione principale. L’orario di esecuzione è determinato da /etc/crontab:

25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

In questo esempio gli script giornalieri vengono eseguiti alle 6:25. È fondamentale assicurarsi che la macchina sia accesa in quell’orario; in caso contrario logrotate non verrà eseguito, causando la crescita incontrollata dei file di log. Per server non attivi 24/7, installare Anacron o migrare al timer systemd.

Come funziona la rotazione dei log

La rotazione prevede la cancellazione dell’ultimo file ruotato, mentre il suo posto viene preso dal penultimo, e così via lungo la catena. Consideriamo un esempio concreto: il log di accesso Nginx /var/log/nginx/access.log con rotazione settimanale e 3 copie (rotate 3).

Settimana 1

access.log viene rinominato in access.log.1. Viene creato un nuovo file access.log vuoto. Il processo Nginx riceve il segnale per scrivere sul nuovo file.

Risultato: access.log, access.log.1

Settimana 2

access.log.1 viene rinominato in access.log.2 (e compresso in access.log.2.gz se delaycompress è attivo). access.log diventa access.log.1. Viene creato un nuovo access.log.

Risultato: access.log, access.log.1, access.log.2.gz

Settimana 3

La catena si sposta di una posizione. access.log.2.gz diventa access.log.3.gz, e così via.

Risultato: access.log, access.log.1, access.log.2.gz, access.log.3.gz

Settimana 4 e successive

access.log.3.gz viene eliminato (superato il limite di rotate 3). Il file più vecchio viene sempre rimosso, mantenendo al massimo il numero di copie specificato.

Con la direttiva dateext, il naming cambia: invece di numerazione progressiva, logrotate aggiunge la data al nome del file (access.log-20260331.gz), rendendo più immediata l’identificazione temporale delle copie archiviate.

File di configurazione

La configurazione di logrotate è distribuita su più file, letti in sequenza come un unico flusso. Le opzioni definite nei file successivi sovrascrivono quelle dei file precedenti.

/etc/logrotate.conf

File di configurazione principale. Contiene i default globali applicati a tutti i log e la direttiva include che carica le configurazioni aggiuntive. Un esempio moderno da Ubuntu 24.04:

# /etc/logrotate.conf — Ubuntu 24.04

# Rotazione settimanale di default
weekly

# Mantieni 4 copie
rotate 4

# Crea nuovi file dopo la rotazione
create

# Comprimi i file ruotati
compress

# Ritarda la compressione di un ciclo
delaycompress

# Usa date nel nome dei file ruotati
dateext

# Non generare errore se il log non esiste
missingok

# Esegui come root:syslog su Ubuntu
su root syslog

# Carica le configurazioni per-servizio
include /etc/logrotate.d

La direttiva su root syslog (presente di default su Ubuntu) specifica con quali credenziali logrotate opera sui file, evitando problemi di permessi quando la directory dei log è di proprietà del gruppo syslog.

/etc/logrotate.d/

In questa directory sono contenuti i file di configurazione installati dai vari pacchetti software. Ogni servizio che genera log di testo installa qui la propria configurazione. Per vedere tutte le configurazioni attive:

ls -la /etc/logrotate.d/

Esempi comuni: /etc/logrotate.d/nginx, /etc/logrotate.d/mysql-server, /etc/logrotate.d/rsyslog. Ogni file contiene la configurazione specifica per i log di quel servizio e le opzioni scritte all’interno delle parentesi graffe sovrascrivono i default globali.

Nota: tutti i file in /etc/logrotate.d/ sono file di configurazione completi di logrotate. Un’opzione globale (fuori dalle parentesi graffe) si applica a tutti i file di log successivi. A meno che non ci sia un motivo specifico, le direttive in questi file devono essere sempre racchiuse dentro le parentesi graffe.

File di stato

Il file /var/lib/logrotate/status (il path può variare tra distribuzioni: /var/lib/logrotate.status su alcune) contiene i timestamp dell’ultima rotazione per ogni file di log. Logrotate consulta questo file a ogni esecuzione per decidere se la rotazione è necessaria.

# Esempio contenuto file di stato
"/var/log/nginx/access.log" 2026-3-31-6:25:1
"/var/log/nginx/error.log" 2026-3-31-6:25:1
"/var/log/mysql/error.log" 2026-3-28-6:25:1

A partire dalla versione 3.20.1, i permessi del file di stato sono stati rafforzati per prevenire la vulnerabilità CVE-2022-1348. Il file non viene più scritto su file non regolari (symlink, device file) come misura di sicurezza aggiuntiva.

Ordine di elaborazione e precedenza

Logrotate legge i file di configurazione in questo ordine:

  1. /etc/logrotate.conf — dall’inizio fino alla riga include
  2. I file in /etc/logrotate.d/ — in ordine alfabetico
  3. /etc/logrotate.conf — dalla riga dopo include fino alla fine

Le opzioni globali (fuori dalle parentesi graffe) si applicano a cascata: un’opzione definita in logrotate.conf viene ereditata da tutti i file successivi, a meno che non venga sovrascritta localmente dentro le parentesi graffe di una specifica configurazione. I file con estensioni taboo (.rpmorig, .rpmsave, .swp, ~) vengono ignorati.

Direttive di logrotate

Le direttive si inseriscono nei file di configurazione dentro /etc/logrotate.d/ per controllare il comportamento della rotazione. Sono organizzate qui per categoria funzionale.

Rotazione e frequenza

DirettivaDescrizione
dailyRotazione giornaliera.
weeklyRotazione settimanale (quando il giorno corrente è inferiore a quello dell’ultima rotazione o è passata più di una settimana).
monthlyRotazione al primo giorno del mese.
yearlyRotazione quando l’anno corrente cambia.
rotate NMantieni N copie ruotate. rotate 0 elimina subito i file ruotati.
maxage NElimina i file ruotati più vecchi di N giorni.
size SRuota solo quando il file supera la dimensione S (100k, 10M, 1G). Ignora i criteri temporali.
minsize SRuota quando il file supera S E l’intervallo temporale è scaduto.
maxsize SRuota quando il file supera S, indipendentemente dall’intervallo temporale. Utile per log ad alto volume.
notifemptyNon ruotare il log se è vuoto.
ifemptyRuota anche se vuoto (default).
missingokNon generare errore se il file di log non esiste.

Compressione

DirettivaDescrizione
compressComprimi i file ruotati con gzip (default).
nocompressNon comprimere i file ruotati.
compresscmd CMDUsa un comando di compressione alternativo (es. bzip2, xz, zstd).
uncompresscmd CMDComando per la decompressione (default: gunzip).
compressext EXTEstensione per i file compressi (segue il comando di compressione configurato).
compressoptions OPTOpzioni per il comando di compressione. Default per gzip: -9 (compressione massima).
delaycompressRinvia la compressione al ciclo successivo. Essenziale quando il servizio potrebbe ancora scrivere sul file appena ruotato.

Naming e archiviazione

DirettivaDescrizione
dateextUsa la data nel nome del file ruotato (es. access.log-20260331) invece della numerazione progressiva.
dateformat FMTFormato della data per dateext. Specifier ammessi: %Y, %m, %d, %s, %z (3.22.0+). Default: -%Y%m%d. I valori devono essere ordinabili lessicograficamente.
extension EXTMantieni l’estensione originale dopo la rotazione. Es. mylog.1.foo.gz anziché mylog.foo.1.gz.
olddir DIRSposta i file ruotati nella directory specificata. Deve trovarsi sullo stesso filesystem.
noolddirRuota nella stessa directory del file originale (default).
start NNumerazione iniziale dei file ruotati. Default: 1.

Creazione e permessi

DirettivaDescrizione
create MODE OWNER GROUPCrea il nuovo file di log subito dopo la rotazione con i permessi specificati. Es. create 0640 www-data adm.
nocreateNon creare un nuovo file di log dopo la rotazione.
copyCopia il file di log senza modificare l’originale. Utile per snapshot.
copytruncateCopia il file e tronca l’originale a zero byte. Usare solo quando il servizio non supporta la riapertura del file di log. Rischio: piccola finestra di perdita dati tra copia e troncamento.
su USER GROUPEsegui la rotazione con le credenziali specificate. Fondamentale quando la directory dei log non è di proprietà di root. Es. su www-data adm.

Dalla versione 3.22.0, i nomi utente e gruppo nella direttiva create possono essere racchiusi tra virgolette per supportare nomi contenenti spazi.

Script hooks

DirettivaDescrizione
prerotate/endscriptComandi eseguiti (con /bin/sh) prima della rotazione, solo se la rotazione avverrà effettivamente.
postrotate/endscriptComandi eseguiti dopo la rotazione. Uso tipico: segnalare al servizio di riaprire il file di log.
firstaction/endscriptEseguito una volta prima di qualsiasi rotazione nel pattern.
lastaction/endscriptEseguito una volta dopo tutte le rotazioni nel pattern.
sharedscriptsEsegui prerotate/postrotate una sola volta per l’intero pattern, non per ogni singolo file. Indispensabile quando il pattern matcha più file.
nosharedscriptsEsegui gli script per ogni singolo file ruotato (default).

Inclusione e filtering

DirettivaDescrizione
include FILE_OR_DIRLegge il file o tutti i file nella directory specificata come configurazioni aggiuntive. I file nella directory vengono letti in ordine alfabetico.
tabooext [+] LISTLista di estensioni da ignorare quando si leggono directory con include. Default: .rpmorig, .rpmsave, .swp, ~. Il prefisso + aggiunge alla lista anziché sostituirla.
ignoreduplicates(3.21.0+) Ignora i file duplicati matchati da pattern diversi, evitando errori di “duplicate log entry”.

Opzioni della riga di comando

OpzioneDescrizione
-d, --debugDry-run: mostra cosa verrebbe fatto senza apportare modifiche. Implica -v.
-f, --forceForza la rotazione di tutti i log, anche se non necessaria. Utile dopo modifiche alla configurazione.
-v, --verboseModalità verbosa. Mostra i dettagli delle operazioni eseguite.
-s, --state FILEUsa un file di stato alternativo. Utile quando logrotate viene eseguito da utenti diversi per set di log distinti.
-l, --log FILEScrivi i messaggi di log nel file specificato anziché su stderr.
-m, --mail CMDComando per l’invio dei log via email. Default: /bin/mail -s.
--wait-for-state-lock(3.21.0+) Attendi il rilascio del lock sul file di stato anziché fallire immediatamente. Utile quando più istanze di logrotate possono essere eseguite in parallelo.

Configurazioni pratiche per servizi comuni

Le configurazioni seguenti sono testate in produzione e rappresentano le best practice attuali per i servizi più comuni su un web server Linux.

Nginx

/var/log/nginx/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
    endscript
}

Il segnale USR1 dice a Nginx di riaprire i file di log senza reload della configurazione. Questo è il metodo corretto per Nginx: non usare copytruncate perché Nginx mantiene un file descriptor aperto e continuerebbe a scrivere nel file ruotato (ora rinominato), non nel nuovo file. Con create + USR1, Nginx chiude il vecchio descriptor e apre il nuovo file.

Per approfondire la configurazione di Nginx, vedi la guida ai certificati SSL con Certbot su Nginx.

Apache HTTP Server

/var/log/apache2/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
    sharedscripts
    postrotate
        if invoke-rc.d apache2 status > /dev/null 2>&1; then
            invoke-rc.d apache2 reload > /dev/null
        fi
    endscript
}

Apache gestisce la riapertura dei log tramite un reload graceful della configurazione. Lo script postrotate verifica prima che Apache sia in esecuzione per evitare errori.

MySQL / MariaDB

/var/log/mysql/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640 mysql adm
    su mysql adm
    postrotate
        if [ -x /usr/bin/mysqladmin ]; then
            /usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs
        fi
    endscript
}

La direttiva su mysql adm è fondamentale: i file di log MySQL sono di proprietà dell’utente mysql e senza questa direttiva logrotate fallirebbe con errori di permessi. Il comando flush-logs dice a MySQL di chiudere e riaprire i file di log.

PHP-FPM

/var/log/php*-fpm.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    postrotate
        [ -r /run/php/php-fpm.pid ] && kill -USR1 $(cat /run/php/php-fpm.pid)
    endscript
}

Come Nginx, PHP-FPM supporta il segnale USR1 per la riapertura dei file di log. Il pattern php*-fpm.log copre multiple versioni di PHP installate in parallelo.

Applicazioni custom

Per applicazioni che non supportano la riapertura dei file di log tramite segnale, usare copytruncate:

/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    su myapp myapp
    maxsize 100M
}

In questo caso, copytruncate copia il contenuto del file e poi lo tronca a zero byte. L’applicazione continua a scrivere sullo stesso file descriptor senza interruzioni. La direttiva maxsize 100M forza la rotazione anche prima della scadenza temporale se il file supera i 100 MB — utile per log ad alto volume.

Logrotate e journald

Su sistemi con systemd, journald è il sistema di logging primario. Raccoglie log strutturati in formato binario da tutti i servizi systemd, dal kernel e dai messaggi syslog. La gestione dello spazio è automatica e configurabile in /etc/systemd/journald.conf.

# /etc/systemd/journald.conf — parametri di gestione spazio
[Journal]
SystemMaxUse=500M         # Spazio massimo occupato dai journal
SystemKeepFree=1G         # Spazio libero minimo da mantenere su disco
MaxRetentionSec=30day     # Elimina i journal più vecchi di 30 giorni
MaxFileSec=1week          # Ruota il file journal corrente ogni settimana

Logrotate e journald sono complementari, non in competizione. Journald gestisce i log dei servizi systemd (e li ruota autonomamente), mentre logrotate gestisce i file di log testuali scritti direttamente dalle applicazioni. Nella pratica, questa è la suddivisione tipica:

  • Journald gestisce: log del kernel, log di systemd-resolved, log di servizi configurati per scrivere su stdout/stderr (catturati da systemd)
  • Logrotate gestisce: access/error log di Nginx e Apache, slow query log di MySQL, log di PHP-FPM, log di applicazioni custom che scrivono su file

Per consultare i log di un servizio specifico tramite journald: journalctl -u nginx.service --since "1 hour ago". Per la rotazione manuale: journalctl --rotate && journalctl --vacuum-time=30d.

Logrotate in ambienti containerizzati

Nei container, la strategia di logging è fondamentalmente diversa rispetto ai server tradizionali. La regola generale è: le applicazioni containerizzate devono scrivere log su stdout/stderr, delegando la gestione alla piattaforma di orchestrazione.

Docker

Docker cattura stdout/stderr dei container tramite logging driver. Il driver di default (json-file) scrive i log in file JSON sul filesystem dell’host e supporta rotazione nativa:

# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

Questa configurazione limita ogni file di log a 10 MB e mantiene 5 copie, per un massimo di 50 MB per container. Logrotate è necessario in Docker solo quando le applicazioni scrivono su file di log montati come bind mount, una pratica da evitare quando possibile.

Kubernetes

In Kubernetes, il kubelet gestisce la rotazione dei log dei container con due parametri:

  • containerLogMaxSize — dimensione massima di ogni file di log (default: 10 MB)
  • containerLogMaxFiles — numero massimo di file di log per container (default: 5)

Logrotate in Kubernetes è rilevante solo per i log a livello di nodo (/var/log/ sull’host) o per pod specifici che scrivono su persistent volume. Per il logging centralizzato, la pratica standard prevede agent di raccolta come Fluentd, Filebeat o Promtail che inviano i log a sistemi centralizzati (Elasticsearch, Loki).

Quando NON usare logrotate

La decisione è lineare:

  • L’applicazione scrive su stdout/stderr → la piattaforma (Docker, Kubernetes) gestisce la rotazione. Non serve logrotate.
  • L’applicazione scrive su file di testo su disco (direttamente o su volume montato) → serve logrotate o un meccanismo equivalente.
  • I log vanno a un sistema centralizzato (syslog remoto, Fluentd, agent) → il sistema centralizzato gestisce retention e rotazione. Non serve logrotate.

Sicurezza e hardening

La direttiva su

Logrotate viene eseguito come root. Senza la direttiva su, logrotate accede alle directory dei log con i privilegi di root, il che può causare errori quando la directory dei log è di proprietà di un utente di servizio. L’errore tipico è:

error: skipping "/var/log/mysql/error.log" because parent directory has insecure permissions
(It's world readable and writable, or not owned by root)

La soluzione è sempre specificare su con l’utente e il gruppo proprietari della directory:

/var/log/mysql/*.log {
    su mysql adm
    # ...altre direttive
}

Permessi del file di stato

La vulnerabilità CVE-2022-1348 permetteva a un utente locale di causare un denial-of-service manipolando il file di stato. Dalla versione 3.20.1, logrotate applica controlli più stringenti:

  • Il file di stato non viene scritto su file non regolari (symlink, device, pipe)
  • I permessi del file di stato sono più restrittivi anche in presenza di ACL

Verificare che il file di stato abbia permessi corretti: ls -la /var/lib/logrotate/status. Deve essere leggibile/scrivibile solo da root.

Sicurezza degli script postrotate

Gli script postrotate vengono eseguiti come root tramite /bin/sh. Seguire queste regole:

  • Usare sempre path assoluti nei comandi (/usr/sbin/nginx, non nginx)
  • Evitare interpolazione di variabili da fonti esterne
  • Verificare l’esistenza del processo prima di inviare segnali ([ -f /var/run/nginx.pid ] && ...)
  • Mantenere gli script minimali: un singolo comando per segnalare il servizio

Distruzione sicura con shred

Per file di log contenenti dati sensibili (log di autenticazione, log di transazioni), la direttiva shred sovrascrive i file prima della cancellazione, rendendo il recupero molto più difficile:

/var/log/auth.log {
    daily
    rotate 7
    compress
    shred
    shredcycles 3
}

shredcycles 3 specifica il numero di passaggi di sovrascrittura. Considerare le implicazioni sulle performance per file di grandi dimensioni e il fatto che shred non è efficace su tutti i tipi di filesystem (es. filesystem copy-on-write come ZFS o Btrfs).

Per approfondimenti sulla sicurezza dei server, vedi la guida alla sicurezza di WordPress.

Troubleshooting

Errori comuni e soluzioni

ErroreCausaSoluzione
parent directory has insecure permissionsLa directory dei log non è di proprietà di root e manca la direttiva suAggiungere su USER GROUP con l’utente proprietario della directory
error: stat of /var/log/X failedIl file di log specificato nel pattern non esisteAggiungere missingok alla configurazione
duplicate log entry for /var/log/XLo stesso file è matchato da più pattern in configurazioni diverseRimuovere il duplicato o usare ignoreduplicates (3.21.0+)
File di stato corrottoInterruzione durante la scrittura, crash, disco pienoRinominare il file di stato (mv status status.bak) e lasciare che logrotate ne crei uno nuovo. Tutti i log verranno ruotati alla prossima esecuzione.
Log non vengono ruotatiTimer systemd non attivo o cron non configuratoVerificare con systemctl status logrotate.timer o controllare /etc/cron.daily/logrotate

Debug con dry-run

Il dry-run è lo strumento essenziale per testare le configurazioni senza apportare modifiche. Esegue l’intera logica di logrotate mostrando cosa verrebbe fatto:

# Dry-run dell'intera configurazione
logrotate -d /etc/logrotate.conf

# Dry-run di un singolo file di configurazione
logrotate -d /etc/logrotate.d/nginx

L’output mostra per ogni file di log: se la rotazione è necessaria, quali file verrebbero rinominati, quali script verrebbero eseguiti. Eventuali errori di sintassi o di permessi vengono segnalati senza conseguenze. Eseguire sempre un dry-run dopo ogni modifica alla configurazione prima di attendere la prossima esecuzione automatica.

Forzare la rotazione manuale

# Forza la rotazione di tutti i log
logrotate -f /etc/logrotate.conf

# Forza la rotazione solo di Nginx
logrotate -f /etc/logrotate.d/nginx

La rotazione forzata è utile dopo l’aggiunta di nuove configurazioni, la rimozione manuale di vecchi file di log, o per verificare che lo script postrotate funzioni correttamente. Il file di stato viene aggiornato con i nuovi timestamp.

Verificare i log di esecuzione

Per verificare che logrotate venga eseguito regolarmente e senza errori:

# Sistemi con systemd timer
journalctl -u logrotate.service --since "7 days ago"

# Sistemi con cron
grep logrotate /var/log/syslog

# Ultimo timestamp di esecuzione
cat /var/lib/logrotate/status | head -20

Per un monitoraggio più completo dei log del server, vedi la guida all’analisi log con tail e l’approfondimento su come fare SEO da terminale.

Conclusione

Logrotate resta il tool di riferimento per la gestione dei file di log testuali su Linux. I punti chiave da ricordare:

  • Execution layer: il meccanismo di trigger è migrato da cron a systemd timer su tutte le distribuzioni recenti. Verificare con systemctl status logrotate.timer.
  • Direttiva su: sempre specificarla quando la directory dei log non è di proprietà di root. È la causa più comune di errori.
  • create vs copytruncate: preferire create con segnale USR1/reload al servizio. Usare copytruncate solo come fallback quando il servizio non supporta la riapertura dei log.
  • Container: in ambienti Docker/Kubernetes, valutare se logrotate è davvero necessario. Se l’applicazione scrive su stdout/stderr, la piattaforma gestisce la rotazione autonomamente.
  • Test: eseguire logrotate -d dopo ogni modifica alla configurazione prima di affidarsi all’esecuzione automatica.

Riferimenti: repository GitHub logrotate, man page logrotate.conf(5), man page logrotate(8).

Articoli correlati

21 min lettura

Ridurre i tempi di risposta del server è vitale per abbattere il TTFB e dominare metriche come LCP e INP. Workflow tecnico per aumentare la velocità dell'hosting: dalla transizione verso VPS alla configurazione avanzata dello stack LEMP per ottenere server realmente accelerati.
33 mi piace
5 min lettura

Configurazione tecnica di Certbot per Nginx su Ubuntu 22.04 e 24.04 LTS. La procedura aggiornata per installare il client Let's Encrypt via Snap, abbandonare il vecchio PPA e automatizzare i certificati SSL/TLS 1.3, inclusa la gestione dei wildcard tramite DNS challenge.
13 mi piace

Autore

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ultimi articoli aggiornati

16 min lettura

Metodologia operativa per la diagnosi di problemi su web server Linux tramite l'analisi dei log di sistema e applicativi. Il testo dettaglia l'ispezione di /var/log, l'interrogazione dei demoni con journalctl per monitorare lo stack LEMP e la configurazione di logrotate.
0 mi piace
21 min lettura

I crawler di Meta e Amazon generano milioni di richieste senza back-off: come quantificarli nei log, verificarne l'autenticità e fermarli con cache, robots.txt, rate limiting e WAF, senza perdere i link preview.
1 mi piace
22 min lettura

Difendere WordPress dai commenti spam con una strategia defense in depth a tre layer: configurazioni applicative, regole edge su Cloudflare, barriere a livello web server. Honeypot PHP, regole .htaccess e Nginx modernizzate, Cloudflare Turnstile, fail2ban. Snippet completi pronti da incollare.
0 mi piace
22 min lettura

Analisi tecnica della persistenza dei dati nel protocollo HTTP tramite header Set-Cookie. Comprendere la meccanica dei cookie, attributi come Max-Age e i limiti di Googlebot come crawler stateless è essenziale per diagnosticare problemi di rendering e involuntary cloaking.
4 mi piace
19 min lettura

Analisi dell'architettura RAG nativa per WordPress sviluppata interamente in PHP e MySQL, senza dipendenze da database vettoriali esterni. Il sistema supera i limiti della ricerca lessicale integrando la ricerca semantica su VPS o hosting condivisi con meno di 1GB di RAM.
3 mi piace

Richiedi un preventivo SEO e Google Ads

Porta il tuo sito web al livello successivo con l’esperienza di EVE Milano. La nostra agenzia di Search Marketing ha ricevuto oltre

User Access Addon Required

This shortcode requires the CF7 Database User Access addon to display data.

Please purchase and install the User Access addon to enable this feature.

Purchase User Access Addon

richieste di preventivo, un segnale chiaro della fiducia che imprenditori e manager, come te, ripongono nella nostra specializzazione tecnica e verticale nella SEO e PPC. Se la tua organizzazione cerca competenze specifiche per emergere nei risultati di Google, noi siamo pronti a fornire quel valore aggiunto. Richiedi un preventivo ora e scopri la differenza tra noi e gli altri.
Richiedi un preventivo

Vuoi ricevere un avviso al mese con le nuove guide pubblicate?

Iscriviti alla newsletter!