51 06/04/2026 07/04/2026 10 min

Stack LOMP su Debian 12: scelta, prerequisiti e flusso di installazione

LOMP qui significa Linux, Nginx, MariaDB, PHP-FPM. Su Debian 12 la combinazione è solida per siti PHP moderni, pannelli hosting leggeri e applicazioni che beneficiano di Nginx come web server front-end e PHP-FPM per l’esecuzione del codice. La scelta è sensata se vuoi un profilo più snello rispetto ad Apache, con buona gestione di concorrenza, cache statiche e reverse proxy.

Prima di toccare i pacchetti, conviene fissare il perimetro: hostname corretto, IP statico o DHCP riservato, accesso SSH amministrativo e DNS già puntato verso il server se il sito deve essere pubblicato subito. Se il nodo è in produzione o vicino alla produzione, fai anche un backup dello stato attuale e verifica di avere un accesso console o out-of-band nel caso un errore di configurazione ti tagli fuori dal servizio.

Questa procedura installa i componenti base, li avvia, esegue una verifica minima e prepara una pagina di test PHP. Non entra nel tuning avanzato, nel virtual hosting multi-dominio o nella hardening completa: quelli sono passi successivi, da fare dopo aver confermato che il layer base è sano.

Prerequisiti e controllo iniziale del sistema

Su Debian 12 assumo shell con privilegi sudo. Prima di installare, aggiorna gli indici e verifica spazio disco, rete e release. Questi controlli riducono il rischio di scoprire a metà installazione che manca spazio in /var o che i repository non sono raggiungibili.

sudo apt update
lsb_release -a || cat /etc/debian_version
df -h /
ip a
getent hosts deb.debian.org

Se il sistema non risolve i nomi, non ha senso andare avanti: correggi DNS o gateway prima. Se il disco di root è sotto stress, considera subito i log e i pacchetti già presenti, perché MariaDB e Nginx scrivono in percorsi diversi ma entrambi possono fallire se la partizione è piena.

Se vuoi una baseline pulita, puoi anche verificare che non ci siano servizi in conflitto sulla porta 80 o 443:

sudo ss -ltnp | egrep ':(80|443)\s'

Se trovi Apache o un altro reverse proxy già attivo, decidi prima chi deve terminare TLS e chi deve ascoltare in front-end. Evita di installare “a caso” più web server sulla stessa porta: è il modo più rapido per generare conflitti e diagnosi ambigue.

Installazione dei pacchetti LOMP

Su Debian 12 i pacchetti principali sono nei repository standard. Installa Nginx, MariaDB Server, PHP-FPM e le estensioni PHP più comuni per applicazioni web. L’elenco va adattato al tuo software, ma per una base generica è ragionevole partire da questo set.

sudo apt update
sudo apt install -y nginx mariadb-server php-fpm php-mysql php-cli php-curl php-xml php-mbstring php-zip php-gd php-intl

Dopo l’installazione, controlla che i servizi siano presenti e attivi. Debian 12 usa systemd, quindi la verifica standard è semplice e affidabile:

systemctl status nginx --no-pager
systemctl status mariadb --no-pager
systemctl status php8.2-fpm --no-pager

Il nome del servizio PHP dipende dalla versione installata. Su Debian 12 la versione predefinita è in genere PHP 8.2, quindi php8.2-fpm. Se hai repository aggiuntivi o versioni alternative, adatta il nome del servizio in base a systemctl list-units | grep fpm.

A questo punto non toccare ancora la configurazione: prima verifica che i demoni partano senza errori. Se un servizio non si avvia, il log del journal è il primo posto da guardare.

journalctl -u nginx -n 50 --no-pager
journalctl -u mariadb -n 50 --no-pager
journalctl -u php8.2-fpm -n 50 --no-pager

Hardening minimo dei servizi e stato di base

Prima di esporre il server, applica almeno il livello minimo di sicurezza operativa. Per MariaDB significa eseguire la procedura di inizializzazione sicura; per PHP-FPM e Nginx significa verificare che non siano esposti endpoint inutili e che i permessi dei file siano coerenti.

Per MariaDB, esegui:

sudo mysql_secure_installation

Le domande tipiche riguardano la password di root MariaDB, la rimozione di utenti anonimi, il divieto di login remoto per root e la rimozione del database di test. In un ambiente standard, le risposte conservative sono in genere appropriate. Se invece hai un flusso automatizzato o un’architettura con account amministrativi separati, documenta la scelta prima di applicarla.

Verifica poi che MariaDB ascolti solo dove serve. Su un server web classico, il database dovrebbe restare locale o raggiungibile solo da indirizzi interni espliciti:

sudo ss -ltnp | grep 3306

Se vedi 0.0.0.0:3306 o un bind su interfacce pubbliche senza motivo, correggi la configurazione prima di andare in produzione. Il file tipico è /etc/mysql/mariadb.conf.d/50-server.cnf, dove il parametro bind-address va valutato con attenzione.

Per Nginx, il controllo iniziale è più semplice: il servizio deve essere attivo e la pagina di default deve rispondere localmente. Non è ancora il tuo sito, ma è un test utile del layer HTTP.

curl -I http://127.0.0.1

Atteso: HTTP/1.1 200 OK o comunque una risposta coerente con la configurazione di default. Se ottieni connection refused, il servizio non è in ascolto; se ottieni 5xx, il problema è già nel layer applicativo o nella configurazione del server.

Configurazione di Nginx per PHP-FPM

Il punto chiave dello stack LOMP è il passaggio corretto delle richieste PHP a PHP-FPM. Su Debian 12 il socket di default di PHP-FPM è spesso sotto /run/php/. Prima di modificare, identifica il socket reale.

ls -l /run/php/

Di solito vedrai qualcosa come php8.2-fpm.sock. Poi crea o modifica il virtual host di Nginx. Se stai lavorando sul sito di default, il file tipico è /etc/nginx/sites-available/default; in alternativa crea un blocco server dedicato per il tuo dominio.

Un esempio minimo, da adattare al tuo dominio e alla tua document root:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example.com/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }

    location ~ /\. {
        deny all;
    }
}

Se usi un socket diverso, sostituiscilo in fastcgi_pass. Dopo ogni modifica, verifica la sintassi prima di ricaricare il servizio:

sudo nginx -t

Atteso: syntax is ok e test is successful. Solo dopo procedi con il reload:

sudo systemctl reload nginx

Questo approccio è reversibile: se qualcosa va storto, puoi ripristinare il file precedente e fare un nuovo nginx -t prima del reload. Tieni sempre una copia del file originale o usa un versionamento minimo del template.

Preparazione della directory web e test PHP

Per una base pulita, crea una document root dedicata e assegna proprietà coerenti. Evita permessi eccessivi: l’utente del web server deve leggere i file, non necessariamente possederli tutti.

sudo mkdir -p /var/www/example.com/public
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com

Se l’applicazione richiede upload o cache scrivibili, restringi i permessi solo alle directory necessarie, non all’intero albero. Questo è un punto importante di sicurezza: meno scrivibilità globale significa meno superficie d’attacco in caso di compromissione di un processo PHP.

Crea una pagina di test PHP per confermare che Nginx parli davvero con PHP-FPM e che l’estensione PHP venga eseguita, non servita come testo.

cat <<'PHP' | sudo tee /var/www/example.com/public/info.php > /dev/null
<?php
phpinfo();
PHP

Apri poi il file dal browser o con curl:

curl -I http://127.0.0.1/info.php
curl http://127.0.0.1/info.php | head

Se vedi l’HTML di phpinfo(), la catena Nginx → PHP-FPM funziona. Se scarichi il sorgente PHP o ottieni un errore 404, il blocco server non punta alla document root giusta. Se ottieni 502, il problema è nel socket o nel servizio PHP-FPM.

Dopo il test, rimuovi il file di diagnostica o limitane l’accesso. phpinfo() è utile in fase di setup ma non va lasciato esposto su un sito pubblico.

MariaDB: verifica servizio, accesso e database applicativo

Una volta che il servizio è attivo, verifica l’accesso locale e crea il database applicativo. Su Debian 12 puoi usare il client mysql o mariadb. Il login come root locale spesso usa l’autenticazione via socket, quindi potrebbe non richiedere password se sei sul server con privilegi adeguati.

sudo mariadb -e "SELECT VERSION();"

Se il comando risponde con la versione, il motore è operativo. Poi crea database e utente applicativo con privilegi limitati sul solo database necessario. Usa una password robusta e non inserirla in chiaro nei documenti operativi condivisi.

sudo mariadb <<'SQL'
CREATE DATABASE exampledb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'exampleuser'@'localhost' IDENTIFIED BY 'PASSWORD_FORTE_DA_SOSTITUIRE';
GRANT ALL PRIVILEGES ON exampledb.* TO 'exampleuser'@'localhost';
FLUSH PRIVILEGES;
SQL

In un contesto serio, la password va gestita in un secret manager o in un file protetto, non incollata nei ticket. Se devi ruotarla, aggiorna prima l’applicazione e poi il database, con finestra di manutenzione e rollback previsto.

Controlla infine che il database sia raggiungibile solo localmente se l’app è sullo stesso host:

sudo ss -ltnp | grep 3306

Se devi collegarti da un host remoto, limita l’esposizione con firewall e bind address. Non aprire MariaDB su Internet senza un requisito preciso e senza cifratura, autenticazione forte e regole di accesso strette.

Verifiche finali del servizio e lettura dei log

Prima di considerare chiusa l’installazione, esegui una verifica incrociata dei tre livelli: web server, PHP-FPM e database. L’obiettivo è vedere un percorso completo senza errori 4xx/5xx e senza warning nei log.

systemctl is-active nginx mariadb php8.2-fpm
curl -I http://127.0.0.1/
journalctl -u nginx -n 20 --no-pager
journalctl -u php8.2-fpm -n 20 --no-pager
journalctl -u mariadb -n 20 --no-pager

Atteso: tutti i servizi active, la home page risponde con codice 200 o con la tua applicazione, e nei log non compaiono errori ripetuti. Un warning occasionale all’avvio può essere accettabile se non si ripete e non impatta il traffico; un errore costante no.

Se hai un firewall locale, apri solo ciò che serve. Con UFW, per esempio, in una configurazione base web server puoi consentire SSH e HTTP/HTTPS:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status verbose

Se usi nftables o regole gestite da un pannello, mantieni la stessa logica: esposizione minima, porte esplicite, niente servizi amministrativi pubblici senza necessità.

Risoluzione rapida dei problemi più comuni

Se il sito restituisce 502 Bad Gateway, il sospetto principale è PHP-FPM non raggiungibile o socket errato. Verifica il socket in /run/php/, lo stato del servizio e il blocco fastcgi_pass nel virtual host.

systemctl status php8.2-fpm --no-pager
ls -l /run/php/
grep -R "fastcgi_pass" /etc/nginx/sites-available /etc/nginx/sites-enabled

Se ottieni 404 sui file PHP, controlla la root del server block e la presenza del file fisico nella document root. Se la pagina PHP viene scaricata invece di essere eseguita, il blocco per location ~ \.php$ manca o è errato.

Se MariaDB non parte, cerca prima nel journal e poi nel filesystem. I casi più frequenti sono spazio disco insufficiente, permessi sbagliati nella directory dati o configurazioni residue di versioni precedenti.

journalctl -u mariadb -n 50 --no-pager
df -h
sudo ls -ld /var/lib/mysql

Se Nginx non si avvia dopo una modifica, la prima verifica è sempre nginx -t. Non fare reload ciechi: un file di configurazione errato può bloccare il servizio o caricare un blocco virtuale sbagliato.

Passi successivi consigliati dopo il setup base

Quando lo stack base è stabile, i passi successivi sensati sono: TLS con Let’s Encrypt o certificato enterprise, virtual host separati, logging centralizzato, backup di database e file, e tuning di PHP-FPM in base al carico reale. Non fare tuning alla cieca: prima misura tempi di risposta, utilizzo RAM, numero di processi PHP attivi e saturazione del disco.

Per il TLS, la strada più semplice su Debian 12 è usare certbot con il plugin Nginx, ma solo dopo aver confermato che il dominio risolve verso il server e che la porta 80 è raggiungibile da Internet. Se il sito è dietro CDN o proxy, la procedura cambia e va adattata al flusso di validazione.

Per il backup, separa almeno tre elementi: dump MariaDB, directory web e configurazione Nginx/PHP. Senza backup testato, una reinstallazione o una migrazione diventano più rischiose del necessario.

In sintesi operativa: installa, verifica i servizi, testa il passaggio PHP-FPM, crea il database con privilegi minimi, chiudi l’esposizione inutile e solo dopo passa a TLS e hardening avanzato. Su Debian 12 questo ordine riduce gli errori e ti lascia sempre un punto di rollback chiaro.