---
title: "Errori PHP critici su VPS gestiti senza supporto tecnico: guida operativa per il ripristino"
description: "Diagnosi e fix di errori PHP critici su VPS: memory exhausted, segfault OPcache, PHP-FPM in crash loop, permessi rotti. Caso reale su Hetzner con Laravel."
canonical: "https://www.mauriziofonte.it/blog/post/errori-php-critici-vps-gestiti-senza-supporto.html"
author: "Maurizio Fonte"
date: "2025-07-10T07:49:52+02:00"
modified: "2026-04-14T17:48:55+02:00"
section: "Incident Response"
tags: ["Incident Response", "VPS & Hosting"]
license: "Riuso e citazione consentiti con attribuzione e link alla fonte"
---

[Incident Response](https://www.mauriziofonte.it/blog/cat/incident_response.html) [VPS & Hosting](https://www.mauriziofonte.it/blog/cat/vps.html)

# [Errori PHP critici su VPS gestiti senza supporto tecnico: guida operativa per il ripristino](https://www.mauriziofonte.it/blog/post/errori-php-critici-vps-gestiti-senza-supporto.html)

Giovedì 10 Luglio 2025, alle 07:49 ![Errori PHP critici su VPS gestiti senza supporto tecnico: guida operativa per il ripristino](https://www.mauriziofonte.it/image/002060200-errori-php-critici-vps-gestiti-senza-supporto.jpg)

Il 14 aprile 2025, un martedì mattina alle 9:15, mi ha chiamato il titolare di una PMI toscana che vende arredamento contract tramite un e-commerce Laravel 10 su un Hetzner CPX21 - 3 vCPU AMD, 4 GB di RAM, 80 GB NVMe - con Debian 12, Nginx 1.22, PHP-FPM 8.2 e MySQL 8.0. Il sito mostrava una schermata bianca: nessun messaggio di errore, nessuna pagina 500, solo un body HTML completamente vuoto. Il pannello Hetzner Cloud mostrava il VPS online con risorse normali (CPU al 5%, RAM al 60%), Nginx rispondeva con HTTP 200 ma il body era vuoto, e MySQL funzionava perfettamente. Il log di Nginx non mostrava errori. Il log di PHP-FPM non mostrava errori. Il `laravel.log` non mostrava errori. Era come se PHP avesse semplicemente smesso di produrre output.

Quel tipo di schermata bianca - HTTP 200, nessun log, nessun errore visibile - è il sintomo più insidioso che un sysadmin possa incontrare su un VPS con PHP, perché non lascia tracce nei posti dove normalmente si guarda. In venti minuti di diagnosi ho identificato il problema: un segfault in OPcache che uccideva il processo PHP-FPM prima che potesse scrivere qualsiasi cosa nel log. L'aggiornamento automatico di sicurezza applicato la notte precedente aveva portato PHP da `8.2.18` a `8.2.21`, e la nuova versione di OPcache aveva un [bug noto nel file cache](https://github.com/php/php-src/issues/19125) che causava crash intermittenti sotto carico. In questo articolo ti racconto la diagnosi completa e il protocollo che uso per ogni emergenza PHP su VPS, perché la schermata bianca è solo il sintomo più comune di una classe di problemi che ha almeno cinque cause radice diverse.

> Stai cercando un **Consulente Informatico** esperto per risolvere emergenze PHP sulla tua infrastruttura? Nel mio [profilo professionale](https://www.mauriziofonte.it/pages/about) trovi l'esperienza concreta su stack LEMP, PHP-FPM e ottimizzazione di applicazioni Laravel e Symfony. [Contattami per una consulenza diretta](https://www.mauriziofonte.it/pages/contattami).

## Come si diagnostica una schermata bianca PHP quando i log non mostrano nulla?

La schermata bianca (WSOD - White Screen of Death) con HTTP 200 e log vuoti è quasi sempre un crash del processo PHP a livello di sistema operativo, non un errore PHP gestito. Quando PHP incontra un errore gestito (syntax error, memory exhausted, exception non catturata), produce un messaggio nel log e restituisce un HTTP 500. Quando il processo crasha - segfault, signal 11, OOM killer - muore prima di poter scrivere qualsiasi cosa, e Nginx riceve una risposta vuota dal socket FPM che viene servita come 200 con body vuoto.

La diagnosi parte dal kernel, non da PHP:

```bash
# 1. Cercare segfault nel kernel log (IL PRIMO POSTO DOVE GUARDARE)
dmesg -T | grep -i "segfault\|killed\|oom\|signal 11"

# 2. Cercare nel journal di systemd
journalctl -u php8.2-fpm --since "1 hour ago" --no-pager | tail -30

# 3. Se dmesg non mostra nulla, attivare il core dump di PHP-FPM
# In /etc/php/8.2/fpm/php-fpm.conf:
# rlimit_core = unlimited
# In /etc/sysctl.conf:
# kernel.core_pattern = /tmp/core-%e-%p-%t
# Poi: sysctl -p && systemctl restart php8.2-fpm
```

Nel caso toscano, `dmesg` ha rivelato immediatamente il problema:

```text
[Tue Apr 14 08:47:12 2025] php-fpm8.2[14523]: segfault at 7f3a2c001020 ip 00007f3a4b2e8a31 sp 00007fff5c8e3b90 error 4 in opcache.so[7f3a4b2b0000+68000]
[Tue Apr 14 08:47:12 2025] php-fpm8.2[14523]: code: 0f 0b 0f 0b 48 8b 45 c8 48 85 c0 0f 84 a7 00 00
```

La riga `in opcache.so` è la firma inconfondibile: il crash avviene dentro il modulo OPcache, non nel codice applicativo. Il passo successivo è stato verificare quando PHP era stato aggiornato:

```bash
# Quando è stato aggiornato PHP?
grep "php8.2" /var/log/apt/history.log | tail -5
# Output: 2025-04-14 03:45:12 upgrade php8.2-fpm:amd64 8.2.18-1+deb12u1 -> 8.2.21-1+deb12u1
```

L'aggiornamento era avvenuto alle 03:45, sei ore prima della chiamata. Il sito aveva funzionato per qualche ora con la nuova versione - i segfault di OPcache spesso sono intermittenti e si manifestano sotto carico, quando il file cache tenta di scrivere script precompilati in modo concorrente tra i worker FPM.

## I cinque errori PHP critici più frequenti su VPS e come risolverli

Nella mia esperienza su VPS di PMI, gli errori PHP critici ricadono in cinque categorie. Li elenco in ordine di frequenza, dal più comune al più raro.

### Memory exhausted: il classico `Allowed memory size`

L'errore `PHP Fatal error: Allowed memory size of X bytes exhausted` è il più comune in assoluto. Significa che uno script PHP ha tentato di allocare più memoria di quanto consentito dal parametro `memory_limit` in `php.ini`. La soluzione immediata è aumentare il limite, ma la soluzione corretta è capire perché lo script consuma così tanta memoria.

```bash
# Trovare il memory_limit attuale
php -i | grep memory_limit

# Trovare QUALE file php.ini sta usando PHP-FPM
php-fpm8.2 -i | grep "Loaded Configuration File"

# Aumentare temporaneamente (fix immediato)
sed -i 's/^memory_limit = .*/memory_limit = 512M/' /etc/php/8.2/fpm/php.ini
systemctl restart php8.2-fpm
```

Il `memory_limit` di default su Debian 12 è 128M, che per un e-commerce Laravel con catalogo di migliaia di prodotti è insufficiente. Il mio standard per applicazioni Laravel in produzione è 256M per le richieste web e 512M per i processi CLI (artisan, queue worker). Se uno script ha bisogno di più di 512M, il problema non è il limite - è il codice che fa qualcosa di sbagliato (tipicamente carica in memoria un'intera tabella del database con `Model::all()` invece di usare chunk o cursor).

### PHP-FPM in crash loop: worker che muoiono e rinascono

Quando PHP-FPM mostra nel log `WARNING: [pool www] child XXXX exited on signal 11 (SIGSEGV)` e subito dopo `NOTICE: [pool www] child YYYY started`, i worker stanno crashando e venendo riavviati ciclicamente. Il sito funziona a singhiozzo - alcune richieste passano, altre restituiscono schermata bianca - perché dipende da quale worker le gestisce e se crasha prima di completare la risposta.

```bash
# Contare quanti segfault ci sono stati nell'ultima ora
journalctl -u php8.2-fpm --since "1 hour ago" | grep -c "SIGSEGV"

# Se il colpevole è OPcache (come nel caso toscano), disabilitare il JIT
# Il JIT (Just-In-Time compiler) è la causa più frequente di segfault su PHP 8.x
sed -i 's/^opcache.jit=.*/opcache.jit=disable/' /etc/php/8.2/fpm/conf.d/10-opcache.ini
systemctl restart php8.2-fpm

# Se i segfault persistono, disabilitare anche il file cache di OPcache
sed -i 's/^opcache.file_cache=.*/;opcache.file_cache=/' /etc/php/8.2/fpm/conf.d/10-opcache.ini
systemctl restart php8.2-fpm
```

Il JIT di PHP 8.x è una feature potente ma ancora instabile su certi carichi di lavoro - la [documentazione PHP](https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit) stessa avverte che è sperimentale su alcune architetture. Il mio approccio è: JIT disabilitato di default su VPS di produzione, abilitato solo dopo test specifici che confermino un vantaggio misurabile senza crash.

### Permessi rotti: il `Permission denied` silenzioso

Gli errori di permessi sono subdoli perché possono manifestarsi come schermata bianca (se `display_errors` è off) o come funzionalità parzialmente rotte (un upload che fallisce, una cache che non si scrive, un log che non registra). La causa è quasi sempre un deploy fatto come `root` che ha cambiato l'ownership dei file da `www-data` a `root`:

```bash
# Fix permessi standard per applicazione Laravel
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

# Directory che devono essere scrivibili
chmod -R 775 /var/www/html/storage
chmod -R 775 /var/www/html/bootstrap/cache
```

### Max execution time: script che impiegano troppo

L'errore `Maximum execution time of 30 seconds exceeded` significa che uno script PHP ha superato il tempo massimo consentito. Il fix immediato è aumentare `max_execution_time`, ma attenzione: aumentarlo troppo (600 secondi, 900 secondi) è un anti-pattern che nasconde problemi di performance. Se uno script impiega più di 60 secondi per una richiesta web, probabilmente dovrebbe essere spostato in una coda asincrona (Laravel queue) invece di essere eseguito inline.

### OOM kill: il kernel uccide PHP-FPM

Quando la RAM è esaurita, il kernel Linux attiva l'OOM killer e termina il processo che consuma più memoria - che su un VPS LEMP è quasi sempre PHP-FPM o MySQL. Il sintomo è un'interruzione improvvisa del servizio senza errori PHP visibili, con la riga `Out of memory: Killed process` in `dmesg`.

```bash
# Verificare se PHP-FPM è stato killato per OOM
dmesg -T | grep -i "out of memory"

# Calcolare quanta RAM usa PHP-FPM (per worker)
ps aux | grep php-fpm | awk '{sum += $6} END {print sum/1024 " MB totali, " NR " processi"}'

# Ridurre il numero di worker se la RAM è insufficiente
# In /etc/php/8.2/fpm/pool.d/www.conf:
# pm = dynamic
# pm.max_children = 5    (su VPS con 4GB, non di più)
# pm.start_servers = 2
# pm.min_spare_servers = 1
# pm.max_spare_servers = 3
```

La formula che uso per calcolare `pm.max_children` è: (RAM totale - RAM MySQL - RAM sistema) / RAM media per worker PHP. Su un VPS con 4 GB, MySQL tipicamente usa 1-1.5 GB, il sistema 500 MB, e ogni worker PHP-FPM usa 40-80 MB. Il calcolo: (4096 - 1200 - 500) / 60 ≈ 40 worker massimi in teoria, ma in pratica ne imposto 5-8 per lasciare margine a picchi di utilizzo. Ho descritto in dettaglio il tuning di PHP-FPM nell'articolo sull'[ottimizzazione performance PHP su Hetzner e OVH](https://www.mauriziofonte.it/blog/post/ottimizzazione-performance-php-server-hetzner-ovh-digital-ocean.html).

## Il protocollo completo che uso per ogni emergenza PHP

Quando ricevo una chiamata per un "sito che non funziona" su un VPS con PHP, seguo sempre questa sequenza - senza eccezioni, senza scorciatoie:

1. `dmesg -T | tail -30` - cercare segfault, OOM, errori hardware

1. `systemctl status php8.2-fpm` - il servizio è attivo? quanti worker?

3. `journalctl -u php8.2-fpm --since "1 hour ago" | tail -30` - errori FPM

1. `tail -30 /var/log/nginx/error.log` - errori dal reverse proxy
2. `tail -30 /var/www/html/storage/logs/laravel.log` - errori applicativi
3. `df -h` - disco pieno?
4. `free -h` - RAM esaurita?
5. `php -v` - versione PHP cambiata?

Otto comandi, meno di un minuto, e nel 95% dei casi ho già identificato la causa radice. L'ordine non è casuale: parto dal livello più basso (kernel) e salgo fino all'applicazione, perché gli errori a livello di kernel sono invisibili a tutti i livelli superiori e se non li cerchi per primi perdi ore a guardare nel posto sbagliato.

Per un'analisi più profonda dell'[osservabilità delle applicazioni PHP](https://www.mauriziofonte.it/blog/post/osservabilita-minima-applicazioni-php-legacy-logging-metriche-alert.html), inclusa la configurazione di logging strutturato e metriche che rendono queste diagnosi molto più rapide, ho scritto un articolo dedicato.

## Prevenzione: come evitare che un aggiornamento PHP rompa la produzione

Il caso toscano è stato causato da un aggiornamento automatico - `unattended-upgrades` ha installato la nuova versione di PHP alle 3 di notte e nessuno ha verificato che tutto funzionasse. Questo pattern è estremamente comune su VPS di PMI: gli aggiornamenti di sicurezza sono attivi (giustamente), ma nessuno controlla il risultato.

Il mio approccio per i pacchetti critici - PHP, MySQL, Nginx - è un modello a tre livelli. Primo: pinnare la versione corrente con `apt-mark hold` per impedire aggiornamenti non controllati:

```bash
# Bloccare gli aggiornamenti automatici di PHP
apt-mark hold php8.2-fpm php8.2-cli php8.2-common php8.2-mysql php8.2-redis

# Verificare quali pacchetti sono bloccati
apt-mark showhold

# Quando vuoi aggiornare manualmente
apt-mark unhold php8.2-fpm php8.2-cli php8.2-common
apt update && apt upgrade -y
# TEST IMMEDIATO: verificare che il sito funzioni
curl -s -o /dev/null -w "%{http_code}" https://www.esempio.it/health-check
apt-mark hold php8.2-fpm php8.2-cli php8.2-common
```

Secondo: un health check automatico post-aggiornamento. Anche quando gli aggiornamenti sono bloccati, i pacchetti di sistema (librerie, kernel) possono influire indirettamente su PHP. Il mio script di health check gira ogni 5 minuti e verifica che PHP-FPM risponda correttamente:

```bash
# Cron: health check PHP ogni 5 minuti
*/5 * * * * curl -sf -o /dev/null --max-time 5 http://127.0.0.1/health-check || \
    (systemctl restart php8.2-fpm && echo "PHP-FPM restarted $(date)" >> /var/log/php-health.log)
```

Terzo: quando effettuo l'aggiornamento manuale, lo faccio in una finestra di manutenzione con rollback pronto. Su Debian, `apt` mantiene i vecchi pacchetti in cache, quindi il downgrade è possibile con `apt install php8.2-fpm=8.2.18-1+deb12u1` - a patto di conoscere la versione precedente. Lo annoto sempre nel runbook del server.

Per una visione completa sulla gestione dei [rischi del codice PHP obsoleto e i vantaggi degli aggiornamenti controllati](https://www.mauriziofonte.it/blog/post/rischi-codice-obsoleto-php8-vantaggi-sicurezza-performance.html), ho scritto un articolo dedicato che copre anche il lato applicativo della questione.

Il caso toscano si è risolto in venti minuti: disabilitato il JIT di OPcache, riavviato PHP-FPM, verificato che il sito funzionasse, e pinnato la versione PHP in `apt` per impedire aggiornamenti automatici non controllati (`apt-mark hold php8.2-fpm php8.2-cli php8.2-common`). La lezione - che vale per ogni VPS in produzione - è che gli aggiornamenti automatici di sicurezza sono fondamentali ma devono essere monitorati. Un `unattended-upgrades` senza un test post-aggiornamento è una scommessa che il nuovo pacchetto non rompa nulla. Per pacchetti critici come PHP, il mio approccio è: aggiornamento manuale con test, non automatico con preghiera. Se gestisci un VPS con applicazioni PHP in produzione e vuoi prevenire questo tipo di incidenti, o se stai affrontando un'emergenza adesso, [contattami](https://www.mauriziofonte.it/pages/contattami).

Dall'articolo al lavoro vero

Questo problema di sicurezza, sul tuo sistema

Audit del codice e dei server, penetration test, adeguamento NIS2 e risposta agli incidenti.

[Vedi come lavoro sulla sicurezza](https://www.mauriziofonte.it/servizi/consulenza-cybersecurity-nis2.html) Ultima modifica: Martedì 14 Aprile 2026, alle 17:48 [« Articolo precedenteOttimizzare cron job su VPS unmanaged: tecniche avanzate per prevenire colli di bottiglia e downtime10 Luglio 2025](https://www.mauriziofonte.it/blog/post/ottimizzare-cron-job-vps-unmanaged.html)[Articolo successivo »Configurare firewall avanzati con nftables su VPS gestite senza personale tecnico qualificato: guida operativa Debian e Ubuntu11 Luglio 2025](https://www.mauriziofonte.it/blog/post/configurare-firewall-nftables-vps-senza-personale-tecnico.html)

### Articoli correlati a Errori PHP critici su VPS gestiti senza supporto tecnico: guida operativa per il ripristino

- [PHP-FPM che crasha sotto carico su VPS: come ho diagnosticato un OOM killer silenzioso su un portale Laravel con 200 utenti concorrenti](https://www.mauriziofonte.it/blog/post/ripristino-crash-php-fpm-laravel-vps.html)

  Un portale B2B Laravel su VPS OVH andava in 502 Bad Gateway ogni giorno tra le 10 e le 11 del mattino l'ora di punta degli ordini. PHP FPM veniva · 3 Luglio 2025

  ![PHP-FPM che crasha sotto carico su VPS: come ho diagnosticato un OOM killer silenzioso su un portale Laravel con 200 utenti concorrenti](https://www.mauriziofonte.it/image/001960070-ripristino-crash-php-fpm-laravel-vps.jpg)
- [Server Debian e Ubuntu in emergenza: checklist operativa rapida per VPS](https://www.mauriziofonte.it/blog/post/checklist-emergenza-debian-ubuntu-vps-unmanaged.html)

  La checklist operativa in 7 fasi che uso quando un VPS Debian o Ubuntu va in crisi: triage in 60 secondi con lo USE method, diagnosi disco pieno, · 9 Luglio 2025

  ![Server Debian e Ubuntu in emergenza: checklist operativa rapida per VPS](https://www.mauriziofonte.it/image/002030070-checklist-emergenza-debian-ubuntu-vps-unmanaged.jpg)
- [PHP OPcache: configurazione ottimale per Laravel e Symfony in produzione](https://www.mauriziofonte.it/blog/post/php-opcache-configurazione-ottimale-laravel-symfony-produzione.html)

  OPcache è la singola ottimizzazione PHP con il maggiore impatto sulle prestazioni: su una applicazione Laravel media, la configurazione corretta · 24 Marzo 2026

  ![PHP OPcache: configurazione ottimale per Laravel e Symfony in produzione](https://www.mauriziofonte.it/image/002720070-php-opcache-configurazione-ottimale-laravel-symfony-produzione.jpg)
- [Configurare swap file per risolvere saturazioni RAM su VPS gestite senza supporto tecnico: guida pratica per Debian e Ubuntu](https://www.mauriziofonte.it/blog/post/configurare-swap-file-vps-debian-ubuntu.html)

  Un VPS con 4 GB di RAM e zero swap: MySQL killato dall'OOM killer ogni notte durante l'import listini, con perdita di transazioni InnoDB. Come · 18 Luglio 2025

  ![Configurare swap file per risolvere saturazioni RAM su VPS gestite senza supporto tecnico: guida pratica per Debian e Ubuntu](https://www.mauriziofonte.it/image/002130070-configurare-swap-file-vps-debian-ubuntu.jpg)
- [Ottimizzare PHP-FPM per carichi elevati: pool, worker e tuning avanzato](https://www.mauriziofonte.it/blog/post/ottimizzare-php-fpm-carichi-elevati-pool-worker-tuning.html)

  Durante un Black Friday, l'applicazione e commerce di un cliente ha saturato i worker PHP FPM in 90 secondi: 502 Bad Gateway per tutti. Il problema · 29 Dicembre 2025

  ![Ottimizzare PHP-FPM per carichi elevati: pool, worker e tuning avanzato](https://www.mauriziofonte.it/image/002620070-ottimizzare-php-fpm-carichi-elevati-pool-worker-tuning.jpg)

---

**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, "Errori PHP critici su VPS gestiti senza supporto tecnico: guida operativa per il ripristino", mauriziofonte.it, 2025. https://www.mauriziofonte.it/blog/post/errori-php-critici-vps-gestiti-senza-supporto.html

Pubblicato: 2025-07-10 · Aggiornato: 2026-04-14.

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