Monitorare un VPS unmanaged senza agent e senza SaaS
Il conto del monitoraggio commerciale su un parco piccolo ha una proprietà curiosa: spesso la voce di spesa supera il costo delle macchine monitorate. Un VPS da 8 euro al mese sorvegliato da un servizio da 15 euro per host è un'infrastruttura in cui il termometro costa più del malato, e il prezzo non è nemmeno l'obiezione principale. Un agent di monitoraggio è un processo che gira con privilegi ampi su ogni macchina, si aggiorna da solo da un repository di un vendor terzo, e spedisce fuori perimetro il ritratto operativo completo dei tuoi sistemi: processi, connessioni, versioni, a volte log. Sono tre proprietà che nel 2026, dopo un anno di lezioni sulla catena di fornitura del software, meritano di essere scelte consapevolmente, non accettate come default. La buona notizia è che per la classe di infrastruttura di cui parla questo blog, il parco da uno a dieci VPS di una PMI, esiste una terza via che i tutorial saltano perché non vende niente: gli strumenti che il sistema operativo ha già. In questo articolo costruisco la checklist completa dei sette controlli che un monitoraggio deve coprire, e per ciascuno mostro l'implementazione con soli componenti di sistema: systemd, i suoi timer, sysstat, vnstat e una mail che parte solo quando c'è qualcosa da dire. Zero canoni, zero agent, zero dati fuori.
Cosa deve fare davvero un monitoraggio, prima di scegliere gli strumenti?
La risposta, spogliata del marketing: rispondere a tre domande. La macchina è viva? (e se non lo è, qualcuno deve saperlo da fuori, perché la macchina morta non può denunciarsi da sola). Sta per rompersi? (disco, memoria, certificati: i guasti annunciati, che sono la maggioranza). Cosa è successo? (quando qualcosa si rompe comunque, servono i dati storici per capire). Tutto il resto, dashboard, grafici animati, intelligenza artificiale che "prevede le anomalie", è contorno: utile su cento macchine, decorativo su cinque. La checklist che segue copre le tre domande con sette controlli, in ordine di importanza, e la regola di progetto è una sola: ogni controllo tace finché va tutto bene e parla quando serve, perché il monitoraggio che manda una mail al giorno "tutto ok" addestra solo a ignorare le mail.
Questa impostazione essenziale è la stessa che applico sui parchi VPS delle PMI che seguo, dove il monitoraggio deve sopravvivere ai cambi di fornitore e ai budget rivisti: nel mio profilo professionale trovi come lavoro su infrastrutture pensate per durare, dove ogni componente in più è un componente che qualcuno dovrà capire fra tre anni.
Prima di tutto serve il canale di notifica, che è il prerequisito di ogni voce successiva: la capacità della macchina di mandarti una mail affidabile. Non serve un mail server completo, serve un inoltro autenticato verso una casella che leggi, e l'ho documentato passo per passo nella guida alla configurazione delle notifiche email con Postfix su VPS: dieci minuti di setup che trasformano ogni script della macchina in un potenziale sistema d'allarme.
Una scelta di fondo prima della lista: per le esecuzioni periodiche uso i timer di systemd, non il cron, e non per moda. Un timer registra ogni esecuzione nel journal (quindi il controllo è a sua volta controllato), con Persistent=true recupera le esecuzioni saltate se la macchina era spenta all'orario previsto, e con RandomizedDelaySec evita che dieci macchine facciano tutte lo stesso check nello stesso secondo. La coppia di file per il controllo del disco, per fissare il pattern una volta per tutte:
# /etc/systemd/system/check-disk.timer
[Timer]
OnCalendar=hourly
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.targetpiù una service oneshot gemella che lancia lo script. Un systemctl enable --now check-disk.timer e il pattern è vivo; systemctl list-timers mostra l'intera flotta di controlli con la prossima esecuzione di ciascuno, che è già di suo una piccola dashboard gratuita.
I sette controlli, uno per uno
1. Liveness esterno: il controllo che non può vivere sulla macchina. Ogni check installato sul VPS condivide il destino del VPS: se la macchina muore, muore anche il suo grido d'aiuto. Il controllo di vita deve stare altrove, e "altrove" non significa per forza un SaaS: se hai due VPS, ognuno può sorvegliare l'altro; se ne hai uno solo, qualunque macchina accesa in ufficio o in casa può fare da sentinella con un cron di quattro righe:
#!/usr/bin/env bash
# /usr/local/bin/watch-vps.sh - sulla macchina sentinella, ogni 2 minuti
set -euo pipefail
URL="https://www.tuosito.it/health"
if ! curl -fsS --max-time 10 "$URL" >/dev/null 2>&1; then
sleep 30 # tolleranza per i blip di rete
curl -fsS --max-time 10 "$URL" >/dev/null 2>&1 || \
echo "DOWN: $URL non risponde ($(date))" | mail -s "ALLARME: sito giu" [email protected]
fiL'endpoint /health merita mezz'ora di cura: non la homepage (che può essere in cache ovunque), ma una rotta che tocca davvero database e componenti critici e risponde 200 solo se il sistema è sano. Il doppio tentativo con pausa elimina la quasi totalità dei falsi allarmi da micro-interruzioni di rete.
2. Disco: il guasto più annunciato del mondo. Un timer systemd che controlla le soglie di spazio e inode e scrive solo quando una è superata. Le partizioni da includere sono tutte quelle montate, perché i guasti veri arrivano sempre da quella dimenticata: la root, /var, e la /boot di cui ho raccontato il modo puntuale in cui rovina gli upgrade.
#!/usr/bin/env bash
# /usr/local/bin/check-disk.sh - via systemd timer, ogni ora
set -euo pipefail
soglia=85
df -P -x tmpfs -x devtmpfs | awk -v s="$soglia" 'NR>1 && $5+0 >= s {print}' | \
{ read -r righe || exit 0; { echo "$righe"; cat; } | \
mail -s "DISCO oltre ${soglia}% su $(hostname)" [email protected]; }3. Servizi: il pattern OnFailure, il segreto meglio documentato di systemd. Non serve un processo che interroga i servizi ogni minuto: systemd sa già quando un'unità fallisce, e la direttiva OnFailure= gli dice cosa fare in quel momento. Si crea una unit template che manda la mail, e la si aggancia ai servizi che contano:
# /etc/systemd/system/[email protected]
[Unit]
Description=Notifica via mail il fallimento di %i
[Service]
Type=oneshot
ExecStart=/usr/local/bin/mail-guasto.sh %i# aggancio al servizio, senza toccare la unit originale:
systemctl edit nginx
# [Unit]
# OnFailure=notifica-guasto@%n.serviceLo script mail-guasto.sh allega le ultime righe di systemctl status e del journal dell'unità: la mail che arriva non dice solo "nginx è caduto", dice perché, ed è la differenza fra un allarme e una diagnosi già iniziata. Il pattern è documentato nella manpage di systemd.unit e vale per qualunque servizio, backup notturni compresi: un job di backup con OnFailure è un backup che non fallisce mai in silenzio.
4. Memoria e OOM: l'assassino lascia sempre la firma. L'esaurimento di memoria su un VPS piccolo si manifesta come servizi che "spariscono" senza spiegazione, e la spiegazione sta sempre nel journal del kernel. Un timer giornaliero che cerca gli interventi dell'OOM killer nelle ultime ventiquattro ore chiude il caso: journalctl -k --since "24 hours ago" | grep -i "killed process", e mail solo se il grep trova qualcosa. Se trova qualcosa spesso, il problema non è di monitoraggio ma di dimensionamento, e la guida a swap e memoria su VPS è il passo successivo.
5. Certificati TLS: la scadenza che si controlla da sola. Il rinnovo automatico va benissimo finché funziona, e il controllo serve per quando smette: un timer settimanale che interroga la scadenza reale del certificato servito (non quella del file sul disco, che può differire) e avvisa sotto i 15 giorni:
giorni=$(( ($(date -d "$(echo | openssl s_client -servername tuosito.it \
-connect tuosito.it:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)" +%s) \
- $(date +%s)) / 86400 ))
[ "$giorni" -lt 15 ] && echo "TLS: $giorni giorni residui" | mail -s "Certificato in scadenza" [email protected]6. Storia delle metriche: sysstat e vnstat, i registratori di bordo. Quando l'incidente arriva, la domanda è sempre "com'era la macchina alle 3:47?", e la risposta la danno due pacchetti che pesano niente: sysstat registra CPU, memoria, I/O e code a intervalli regolari, vnstat tiene la contabilità del traffico di rete per giorno e per mese, preziosa anche per accorgersi di anomalie di banda che possono indicare compromissioni o costi in arrivo. L'interrogazione retrospettiva di sysstat è il suo superpotere: sar -r -f /var/log/sysstat/saNN mostra la memoria di un giorno passato campione per campione, sar -q le code di run, sar -b l'I/O, e la sequenza dei campioni attorno all'ora dell'incidente racconta quasi sempre la storia intera, il carico che sale, la memoria che si esaurisce, l'I/O che satura, con la precisione di un registratore di volo. Attivarli costa un apt install sysstat vnstat e un flag in /etc/default/sysstat; da lì in avanti la macchina tiene il diario da sola, in locale, senza spedire niente a nessuno.
7. Log di sistema: il riassunto quotidiano che si legge in trenta secondi. L'ultimo controllo è un timer che ogni mattina estrae dal journal gli errori del giorno prima, journalctl -p err --since yesterday --until today, e li manda solo se esistono. È il controllo più umile della lista e quello che più spesso intercetta i problemi in incubazione: il disco che inizia a dare errori I/O sporadici, il servizio che si riavvia da solo ogni notte, il cron che fallisce da una settimana senza che nessuno se ne sia mai accorto, i tentativi di accesso anomali che meritano uno sguardo prima di diventare un incidente.
Il monitoraggio non è un prodotto: è la disciplina di farsi trovare informati. Sette controlli silenziosi che parlano solo quando serve battono qualunque dashboard guardata due volte al mese, e il fatto che costino zero euro al mese è la conseguenza, non l'obiettivo.
Cosa questa architettura non copre, detto onestamente
La correttezza intellettuale impone il perimetro. Questa impostazione copre bene il parco piccolo e i guasti che contano; non sostituisce le piattaforme complete quando le esigenze crescono davvero. Se hai decine di macchine, il pattern "ogni VPS si gestisce i suoi controlli" smette di scalare e serve aggregazione centrale. Se ti serve l'analisi applicativa fine, tempi di risposta per endpoint, tracce distribuite, percentili, quella è osservabilità applicativa, un mestiere diverso di cui ho scritto nella guida all'osservabilità minima per applicazioni PHP. E se nessuno legge le mail, nessuna architettura ti salva: il monitoraggio presuppone un umano che risponde, e su questo i SaaS con le loro escalation e i loro turni hanno un valore vero per chi quel processo non può presidiarlo. La scelta giusta, come sempre, dipende dal punto in cui sei: quello che contesto è il riflesso di partire dal prodotto commerciale per un parco di tre macchine, pagando con soldi, superficie d'attacco e sovranità dei dati un problema che systemd risolve con quattro unit.
Due regole di manutenzione completano l'impianto e lo tengono onesto nel tempo. La prima: gli script e le unit vivono in un repository git, e sulla macchina arrivano per deploy, non per editing estemporaneo; così ogni taratura di soglia ha una storia, e montare il monitoraggio sulla prossima macchina è un checkout. La seconda, che quasi nessuno fa: gli allarmi si collaudano rompendo le cose apposta, una volta a trimestre. Si ferma un servizio e si cronometra la mail di OnFailure, si riempie una partizione di prova, si punta il check dei certificati su un dominio sacrificabile con la scadenza vicina. Un allarme mai scattato è un'ipotesi, non una protezione, e la differenza si scopre sempre nel momento peggiore, esattamente come per i backup.
C'è un ultimo beneficio di questa via, ed è quello che la rende la mia scelta di default sui parchi che seguo: ogni pezzo è ispezionabile. Quando un allarme arriva, lo script che l'ha generato è sotto /usr/local/bin, leggibile in trenta secondi, modificabile con un editor; quando un controllo va tarato, la modifica è un commit nel repository di configurazione, non un ticket al vendor. Su macchine che devono durare anni, gestite da persone che cambiano, questa trasparenza vale più di qualunque funzione premium. Se vuoi mettere in piedi questa architettura sul tuo parco e preferisci partire da una base collaudata invece che da zero, timer, soglie e template di notifica già rodati su macchine reali, contattami per una consulenza: l'impianto completo su un VPS si monta in mezza giornata, e da lì replicarlo sulle altre macchine è questione di minuti l'una.