---
title: "La configurazione di logrotate che evita il disco pieno alle 3 di notte"
description: "Access log da gigabyte, laravel.log infinito, rotazioni che girano ma non comprimono: come funziona logrotate, gli errori tipici e la configurazione per un VPS LEMP."
canonical: "https://www.mauriziofonte.it/blog/post/log-rotation-vps-logrotate-configurazione-disco-pieno.html"
author: "Maurizio Fonte"
date: "2026-11-11T08:23:28+01:00"
modified: "2026-11-11T08:23:28+01:00"
section: "Linux & Server"
tags: ["Linux & Server", "VPS & Hosting"]
license: "Riuso e citazione consentiti con attribuzione e link alla fonte"
---

[Linux & Server](https://www.mauriziofonte.it/blog/cat/linux.html) [VPS & Hosting](https://www.mauriziofonte.it/blog/cat/vps.html)

# [La configurazione di logrotate che evita il disco pieno alle 3 di notte](https://www.mauriziofonte.it/blog/post/log-rotation-vps-logrotate-configurazione-disco-pieno.html)

Mercoledì 11 Novembre 2026, alle 08:23 ![La configurazione di logrotate che evita il disco pieno alle 3 di notte](https://www.mauriziofonte.it/image/005830200-log-rotation-vps-logrotate-configurazione-disco-pieno.jpg)

C'è un orario ricorrente nelle notifiche di disco pieno che ricevo dai monitoraggi dei VPS che seguo, ed è la notte fonda. Non è una coincidenza poetica: è aritmetica dei carichi. Di notte girano i backup che scrivono gigabyte temporanei, i cron che elaborano e loggano, e soprattutto di notte gli access log crescono più in fretta che di giorno, perché i bot e gli scanner non dormono e un'ondata di scansione può gonfiare un access log di centinaia di megabyte in poche ore. Se a questo aggiungi un `laravel.log` che nessuno ha mai ruotato, arrivato a qualche gigabyte di crescita organica, e una rotazione che gira una volta al giorno alle prime ore e che da qualche settimana fallisce in silenzio, hai la ricetta completa del guasto delle 3 di notte: il disco tocca il 100%, il database smette di scrivere, e la mattina il sito è giù con un errore che non nomina mai il vero colpevole. In questo articolo faccio la diagnosi completa del sistema di rotazione dei log su un VPS: come funziona davvero logrotate, dove si rompe tipicamente, gli errori di configurazione che trasformano la rotazione in un rito inefficace, e la configurazione di riferimento che applico su ogni macchina LEMP, quella che tiene `/var/log` sotto controllo senza più pensarci.

## TL;DR

> - **Diagnosi rapida:** `du -sh /var/log/* | sort -rh | head` per i colpevoli; `find / -xdev -size +100M -name "*.log"` per i log fuori da /var/log.

> - **Il log cancellato ma aperto** non libera spazio: `lsof +L1` lo smaschera; serve ruotare con reload del processo, non cancellare.
> - **`size` non è un tetto:** logrotate valuta la condizione solo quando gira (di default una volta al giorno). Per i burst serve `maxsize` con esecuzione oraria.
> - **`copytruncate` perde righe** nella finestra fra copia e troncamento: preferire `create` + segnale al processo (`postrotate`).
> - **Laravel e le app:** meglio la rotazione nativa (canale `daily`) che logrotate su file tenuti aperti dall'applicazione.
> - **Verifica:** `logrotate -d /etc/logrotate.conf` simula senza toccare niente; lo stato vive in `/var/lib/logrotate/status`.

## Perché il disco si riempie proprio di notte, e perché nessuno se ne accorge prima?

La prima metà della risposta l'ho anticipata: la notte concentra i produttori di byte, backup, cron, bot. La seconda metà è più interessante: perché la rotazione, che esiste apposta, non ha protetto la macchina? Nella mia esperienza di subentri le cause si contano sulle dita di una mano, e la più frequente è brutale: **il log incriminato non era proprio coperto dalla rotazione**. Logrotate ruota solo ciò che i file in `/etc/logrotate.d/` gli dicono di ruotare: i pacchetti Debian installano le proprie ricette per nginx, MariaDB e compagnia, ma il log dell'applicazione custom, il file su cui lo script di sincronizzazione fa append da tre anni, il log di quel servizio installato a mano, quelli non li conosce nessuno. La diagnosi parte quindi dal censimento, non dalla configurazione:

```bash
du -sh /var/log/* 2>/dev/null | sort -rh | head -15
find / -xdev -type f -size +100M \( -name "*.log" -o -name "*.log.*" \) 2>/dev/null
```

Il secondo comando è quello che trova i colpevoli veri, perché cerca su tutto il filesystem: i log applicativi vivono spessissimo fuori da `/var/log`, dentro `storage/logs` di un progetto Laravel, in `/opt`, nella home di un utente di servizio. E c'è un terzo controllo che separa i sysadmin che hanno già vissuto questa notte da quelli che la vivranno: `lsof +L1`, la lista dei file **cancellati ma ancora aperti**. Il riflesso di panico davanti al disco pieno è `rm` sul log gigante, e il risultato è il peggiore possibile: lo spazio non si libera, perché il processo tiene il file aperto e il kernel non può riciclare i blocchi, ma il file è sparito dalla vista, e `du` non torna più con `df`. È una trappola che ho descritto per esteso nella [guida ai problemi di spazio disco su VPS](https://www.mauriziofonte.it/blog/post/risolvere-problemi-spazio-disco-vps-debian-ubuntu.html), e la rotazione fatta bene esiste esattamente per non doverci mai cadere: i log non si cancellano, si ruotano, informando il processo che li scrive.

Due voci del censimento meritano una menzione perché sfuggono sistematicamente. La prima è la coppia `wtmp` e soprattutto `btmp`: il registro dei login falliti, che su un VPS con SSH esposto e sotto brute force costante può gonfiarsi di centinaia di megabyte, e che la configurazione di default ruota con una calma mensile pensata per un mondo con meno bot; se `du` lo mette in classifica, è insieme un problema di spazio e un promemoria che il rate limiting su SSH sta lavorando poco. La seconda sono i log diagnostici accesi durante un'emergenza e mai spenti: lo slow query log di MariaDB attivato per una diagnosi sei mesi fa, il debug verboso di un plugin, il log delle query rimasto acceso dopo lo sviluppo. Il censimento periodico serve anche a questo: trovare i rubinetti aperti, non solo i secchi pieni.

Questo genere di prevenzione sistematica è il cuore della manutenzione che imposto sui parchi VPS delle PMI: [nel mio profilo professionale](https://www.mauriziofonte.it/pages/about) trovi come lavoro sulle macchine che devono restare in piedi da sole, dove ogni guasto notturno evitato vale più di qualunque intervento eroico a posteriori.

## Come funziona davvero logrotate, nelle tre righe che contano

Per configurarlo bene bisogna avere chiaro il suo modello di esecuzione, perché è lì che nascono gli equivoci. Logrotate **non è un demone**: è un programma che un timer di systemd lancia una volta al giorno, legge le ricette, confronta ogni log con le condizioni (età, dimensione) e ruota ciò che le soddisfa, annotando tutto nel file di stato `/var/lib/logrotate/status`. Da questo modello discendono tre verità operative che smontano altrettanti equivoci diffusi.

La prima: **`size` non è un tetto, è una condizione valutata a campione**. `size 100M` non significa "questo log non supererà mai i 100 MB"; significa "quando logrotate passa, se lo trova sopra i 100 MB lo ruota". Fra un passaggio e l'altro ci sono ventiquattro ore, e un access log sotto scansione aggressiva in ventiquattro ore può crescere di gigabyte. La soluzione per i log a rischio burst è la coppia `maxsize` più esecuzione oraria: `maxsize` collabora con i criteri temporali (ruota alla scadenza programmata O al superamento della soglia), e il timer si porta a frequenza oraria con un override, così la finestra di esposizione scende da un giorno a un'ora.

La seconda: **la rotazione senza avviso al processo è una rotazione a metà**, ed è qui che vive il dilemma `create` contro `copytruncate`. Con `create`, logrotate rinomina il file e ne crea uno nuovo vuoto: pulito, atomico, nessuna riga persa, ma il processo che scriveva continua a tenere aperto il file rinominato finché qualcuno non gli dice di riaprire, ed è il compito dello script `postrotate` (il reload di nginx, il segnale USR1, il restart del servizio piccolo). Con `copytruncate`, logrotate copia il contenuto e tronca il file originale sul posto: nessuna collaborazione richiesta al processo, ma **le righe scritte fra la copia e il troncamento sono perse per sempre**, e su un log ad alto volume non è un'ipotesi, è una certezza statistica. La regola che applico: `create` più `postrotate` ovunque il software offra un modo civile di riaprire i log, `copytruncate` solo come ultima spiaggia per i processi che non lo offrono, sapendo cosa si paga. La [manpage di logrotate](https://manpages.debian.org/trixie/logrotate/logrotate.8.en.html) documenta entrambe con le rispettive avvertenze.

La terza: **il fallimento è silenzioso per design**. Se una ricetta ha un errore, un path sbagliato, un problema di permessi che la direttiva `su` avrebbe risolto, logrotate salta e riprova domani, e nessuno lo viene a sapere finché il disco non finisce. I due strumenti di verità: `logrotate -d /etc/logrotate.conf` esegue la simulazione completa senza toccare nulla, mostrando esattamente cosa farebbe e perché; e il journal del timer (`journalctl -u logrotate.service`) contiene gli errori che nessuno legge. Un controllo periodico su quell'unit con il pattern `OnFailure` che ho descritto nel pezzo sul [monitoraggio senza agent](https://www.mauriziofonte.it/blog/post/monitoraggio-vps-linux-systemd-timer-senza-agent-saas.html) chiude il cerchio: la rotazione che fallisce diventa una mail, non una sorpresa.

> Un sistema di log sano ha una proprietà sola: la sua occupazione ha un massimo noto e dimostrabile. Se non sai dire quanti gigabyte possono occupare i tuoi log nel caso peggiore, non hai una configurazione: hai una speranza con dentro un timer.

## La configurazione di riferimento per un VPS LEMP

Metto insieme i pezzi nella ricetta che uso come base, da adattare: copre un access log a rischio burst, con compressione e retention esplicita.

```text
# /etc/logrotate.d/nginx-custom
/var/log/nginx/*.log {
    daily
    maxsize 100M
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /run/nginx.pid ] && kill -USR1 "$(cat /run/nginx.pid)"
    endscript
}
```

Le scelte, riga per riga dove non ovvie: `rotate 14` con `daily` significa due settimane di storia, un tetto calcolabile; `compress` più `delaycompress` comprime tutto tranne l'ultimo ruotato, così il file appena chiuso resta greppabile al volo durante una diagnosi; `sharedscripts` esegue il postrotate una volta sola per l'intero glob invece che per ogni file. Sulle macchine dove i log servono anche alle diagnosi retrospettive aggiungo `dateext`, che rinomina i ruotati con la data invece della numerazione a scalare: quando cerchi "cosa è successo il 3 del mese", la differenza fra aprire il file giusto al primo colpo e contare a ritroso i suffissi è tempo di diagnosi vero, e la retention smette di essere un mistero, perché un `ls` della directory dice esattamente quali giorni hai e quali no. A questa base si aggiunge l'override orario del timer per le macchine esposte (`systemctl edit logrotate.timer`, con `OnCalendar=hourly`), che insieme a `maxsize` è la vera assicurazione contro i burst notturni.

Resta il capitolo dei **log applicativi**, dove la risposta giusta spesso non è logrotate. Un'applicazione Laravel con il canale di log `single` produce esattamente il mostro da gigabyte di cui sopra, ma la soluzione nativa è migliore di qualunque ricetta esterna: il canale `daily` con `days` di retention fa ruotare i file all'applicazione stessa, che li riapre correttamente per costruzione, senza segnali e senza righe perse. La regola generale: **se il framework o il servizio sa ruotare i propri log, lasciaglielo fare e limita logrotate a fare da rete di sicurezza**; logrotate governa ciò che non sa ruotarsi da solo. E il terzo attore della contabilità, il journal di systemd, ha la sua retention separata con le sue regole, che ho trattato per esteso nel pezzo sul [journal persistente e i suoi limiti da configurare](https://www.mauriziofonte.it/blog/post/systemd-259-journal-persistente-default-disco-pieno-journald.html): su un VPS piccolo i tre sistemi, logrotate, rotazioni applicative e journald, vanno dimensionati insieme, perché il disco che condividono è uno solo.

Chiudo con il collaudo, perché una configurazione di rotazione si giudica come un backup: provandola. `logrotate -f /etc/logrotate.d/nginx-custom` forza un giro completo e ti fa vedere l'intera catena in azione, rotazione, permessi, postrotate, compressione; venti secondi che scoprono subito il path sbagliato, il permesso mancante che la direttiva `su` avrebbe sistemato, o il segnale che non arriva al processo giusto. E poiché il tetto deve essere calcolabile, l'esercizio finale è il conto del caso peggiore, che consiglio di scrivere in un commento in testa a ogni ricetta: con `maxsize 100M`, `rotate 14` e la compressione che porta i ruotati a una frazione dell'originale, l'access log occupa al massimo il file corrente più quattordici archivi, cioè un numero noto di megabyte, e la somma dei tetti di tutte le ricette più i limiti del journal deve stare comodamente dentro lo spazio che il disco può dedicare ai log. Se la somma non torna, la correzione si fa adesso, scegliendo cosa tagliare, invece che alle 3 di notte, quando taglia il caso.

Fatto questo, la notte delle 3 torna a essere un orario come un altro: i burst hanno un tetto orario, i log applicativi si ruotano da soli, il journal ha il suo recinto, e l'unica cosa che può ancora riempirti il disco è una novità vera, un comportamento nuovo che merita attenzione umana, che è esattamente il caso in cui vuoi essere svegliato. Se il tuo VPS è ancora nella fase "speriamo che regga", con log mai censiti, rotazioni mai collaudate e qualche gigabyte di storia mai compressa, [contattami per una consulenza](https://www.mauriziofonte.it/pages/contattami): il giro completo su una macchina, censimento, ricette, collaudo e alert, sta in un paio d'ore di lavoro ordinato, e da lì in avanti è manutenzione che si fa da sola, per anni.

Dall'articolo al lavoro vero

Se questo server lo devi tenere in piedi tu

Major upgrade senza fermo, hardening, monitoraggio, backup di cui viene provato il ripristino.

[Vedi come lavoro sui server](https://www.mauriziofonte.it/servizi/consulenza-it-devops.html)

Strumenti gratuiti per questo articolo

Funzionano nel browser, sullo stesso tema dell'articolo.

- [Monitoraggio proattivo server](https://www.mauriziofonte.it/strumenti/monitoraggio-proattivo-server)

Ultima modifica: Mercoledì 11 Novembre 2026, alle 08:23 [« Articolo precedenteQuale LLM locale ti dà ragione anche quando sbagli10 Novembre 2026](https://www.mauriziofonte.it/blog/post/llm-locale-premessa-falsa-sycophancy-test-modelli-qwen-ornith-neohorse.html)

---

**Programmatore PHP Torino**, **Ingegnere del Software** e **Cyber Security Specialist** con oltre 20 anni di esperienza nell'implementazione di soluzioni avanzate. Eseguo **porting di vecchi ambienti PHP** verso release più moderne (7.x o 8.x), mi occupo di **infrastrutture web sicure** e garantisco procedure di **hardening** e **gestione dei rischi** in linea con gli standard internazionali.  
Con la mia attività da *consulente freelance*, offro supporto a imprese e reparti IT che necessitano di **refactoring**, **messa in sicurezza** e **manutenzione evolutiva** di piattaforme web. Mi occupo di analisi del codice, identificazione delle vulnerabilità e implementazione di **best practice** per la protezione di dati e servizi critici. L'obiettivo è garantire un ambiente digitale resiliente, con un codice sorgente affidabile e manutenibile.

---

## Autore

**Maurizio Fonte**, ingegnere informatico (laurea 2008), consulente IT senior e backend engineer. Nel settore IT dal 2005, libero professionista con P.IVA dal 2014. Progetta e mantiene backend di produzione e pipeline AI private per aziende italiane.

Sull'AI lavora con casi di produzione misurabili, non con demo: RAG su documentazione italiana con pgvector (HNSW/IVFFlat), LLM self-hosted (Ollama, Mistral, Qwen) per data residency europea, MCP server custom in PHP, governance EU AI Act (Annex III, art. 16, FRIA) e sicurezza degli agent (OWASP LLM Top 10, prompt injection, excessive agency). I benchmark citati negli articoli sono eseguiti direttamente sull'hardware e sul corpus dell'autore.

## Perché questa fonte è attendibile

- **Esperienza diretta, non rassegna di terzi.** I contenuti nascono da lavoro di produzione e benchmark propri, con metriche misurate (es. un RAG self-hosted su 2.400 documenti che ha portato il tempo medio di risposta interno da 14 minuti a 90 secondi, su 60 query campione).
- **Verificabilità.** Ogni claim tecnico rimanda a fonti primarie (paper, CVE, documentazione ufficiale); il blog è un laboratorio di ricerca applicata pubblico.
- **Onestà metodologica.** Ogni soluzione dichiara anche quando NON va usata. "Production-grade, non demo-grade".

## Entità e contatti (verificabili)

Maurizio Fonte, Torino, Italia. P.IVA IT11396570019. REA TO-1331015 (Camera di Commercio di Torino).  
GitHub: https://github.com/mauriziofonte  
LinkedIn: https://www.linkedin.com/in/mauriziofonte  
Profilo: https://www.mauriziofonte.it/pages/about

---

## Come citare

> Maurizio Fonte, "La configurazione di logrotate che evita il disco pieno alle 3 di notte", mauriziofonte.it, 2026. https://www.mauriziofonte.it/blog/post/log-rotation-vps-logrotate-configurazione-disco-pieno.html

Pubblicato: 2026-11-11 · Aggiornato: 2026-11-11.

**Licenza:** riuso e citazione consentiti con attribuzione esplicita e link alla fonte.
