Installare Nginx, PHP-FPM 8.5 e MariaDB su Ubuntu 26.04: lo stack LEMP completo

Lo stack LEMP (Linux, Nginx, MariaDB, PHP) è la base di WordPress, Nextcloud senza container e di gran parte delle applicazioni PHP. Ubuntu 26.04 LTS lo offre tutto nei repository con versioni aggiornate: Nginx 1.28, PHP 8.5 e MariaDB 11.8 LTS. Le guide italiane che si trovano in rete sono quasi tutte ferme a PHP 8.1–8.3 e a percorsi che non esistono più; qui ogni riga di configurazione è spiegata, con un controllo dopo ogni passo.

In breve

  • Tempo: 30–45 minuti.
  • Difficoltà: media.
  • Cosa serve: un server Ubuntu 26.04 LTS (o Debian 13) con utente sudo e UFW attivo, un dominio che punta all’IP del server (facoltativo per i test, necessario per l’HTTPS).

Versioni di riferimento: Ubuntu 26.04 LTS con nginx 1.28.3, php8.5-fpm 8.5.4, mariadb-server 11.8.6; Debian 13 con nginx 1.26.3, php8.4-fpm 8.4.27, mariadb-server 11.8.6 (versioni dei pacchetti al 4 novembre 2026). Procedura verificata sulla documentazione ufficiale al 4 novembre 2026.

Prerequisiti e scelte iniziali

Partite da un server già messo in sicurezza (utente non root, chiavi SSH, firewall): se manca qualcosa, seguite prima https://hardwarfare.it/ai-software/linux/primo-setup-vps-ubuntu-ssh-firewall/. Se state lavorando su un server con siti già attivi, fate uno snapshot o un backup di /etc/nginx, /etc/php e dei database prima di cominciare.

Nginx dai repository di Ubuntu o da nginx.org? Ubuntu 26.04 distribuisce nginx 1.28.3, cioè un ramo che nginx.org ormai classifica come “legacy”; il ramo stabile corrente è 1.30.6, il mainline 1.31.8. Canonical pubblica comunque le correzioni di sicurezza per il pacchetto della LTS. Per un server di uso comune il pacchetto di Ubuntu va benissimo ed è quello che usiamo qui. Chi vuole lo stabile più recente può usare il repository ufficiale di nginx.org (istruzioni su nginx.org/en/linux_packages.html), sapendo che quei pacchetti hanno una struttura diversa: niente sites-available e sites-enabled, configurazioni in /etc/nginx/conf.d/, nessuno snippet fastcgi-php.conf.

Passo 1: installare Nginx e aprire il firewall

sudo apt update
sudo apt install nginx
sudo ufw allow 'Nginx Full'

Il profilo UFW Nginx Full, installato dal pacchetto, apre le porte 80 e 443 TCP. Esistono anche Nginx HTTP (solo 80) e Nginx HTTPS (solo 443).

Verifica: systemctl status nginx deve risultare active (running) e aprendo http://IP_SERVER dal browser deve comparire la pagina “Welcome to nginx!”. Con curl -I http://localhost dal server vedete l’intestazione Server: nginx.

Passo 2: installare PHP-FPM 8.5 e le estensioni comuni

Con Nginx PHP non gira dentro il web server ma in un servizio separato, PHP-FPM, che riceve le richieste attraverso un socket. Installiamo FPM, il client da riga di comando e le estensioni richieste dalla maggior parte delle applicazioni (le stesse raccomandate dal manuale di hosting di WordPress):

sudo apt install php8.5-fpm php8.5-cli php8.5-mysql php8.5-curl php8.5-xml php8.5-mbstring php8.5-intl php8.5-zip php8.5-gd

Su Debian 13 la versione è la 8.4: sostituite 8.5 con 8.4 in tutti i nomi di pacchetto, nei percorsi e nel nome del socket di questa guida.

Verifica: php -v deve riportare PHP 8.5; systemctl status php8.5-fpm deve essere attivo; ls -l /run/php/ deve mostrare il socket php8.5-fpm.sock con proprietario www-data. È questo il percorso da indicare a Nginx.

Passo 3: installare e mettere in sicurezza MariaDB

sudo apt install mariadb-server
sudo mariadb-secure-installation

Lo script rimuove gli utenti anonimi, il database test e l’accesso remoto di root. Su Debian e Ubuntu l’utente root@localhost di MariaDB usa per impostazione predefinita il plugin unix_socket: si autentica con l’utente di sistema, quindi chi esegue sudo mariadb entra senza password e nessuno può entrare come root da remoto. Per questo non è necessario impostare una password di root: rispondete sì alle domande di pulizia.

Ora create un database e un utente dedicato per l’applicazione (mai usare root nelle applicazioni):

sudo mariadb
CREATE DATABASE NOME_DB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'UTENTE_DB'@'localhost' IDENTIFIED BY 'PASSWORD_ROBUSTA';
GRANT ALL PRIVILEGES ON NOME_DB.* TO 'UTENTE_DB'@'localhost';
EXIT;

Verifica: mariadb -u UTENTE_DB -p NOME_DB deve chiedere la password ed entrare; SELECT VERSION(); riporta la serie 11.8. Con sudo ss -tlnp | grep 3306 controllate che MariaDB ascolti solo su 127.0.0.1: è il default dei pacchetti, e così deve restare.

Passo 4: il server block, commentato riga per riga

Ogni sito ha la sua cartella e il suo file di configurazione. Creiamo la radice del sito (sostituite TUO_DOMINIO):

sudo mkdir -p /var/www/TUO_DOMINIO/public
sudo chown -R $USER:www-data /var/www/TUO_DOMINIO
sudo nano /etc/nginx/sites-available/TUO_DOMINIO
server {
    # ascolta sulla porta 80, IPv4 e IPv6
    listen 80;
    listen [::]:80;

    # i nomi a cui risponde questo blocco
    server_name TUO_DOMINIO www.TUO_DOMINIO;

    # cartella dei file del sito
    root /var/www/TUO_DOMINIO/public;
    # file da cercare quando si chiede una cartella
    index index.php index.html;

    # log separati per sito: molto più facili da leggere
    access_log /var/log/nginx/TUO_DOMINIO.access.log;
    error_log /var/log/nginx/TUO_DOMINIO.error.log;

    location / {
        # prima il file, poi la cartella, altrimenti errore 404
        try_files $uri $uri/ =404;
    }

    location ~ .php$ {
        # snippet di Ubuntu: divide il percorso e controlla che lo script esista
        include snippets/fastcgi-php.conf;
        # passa la richiesta a PHP-FPM tramite il socket
        fastcgi_pass unix:/run/php/php8.5-fpm.sock;
    }

    # blocca file nascosti come .htaccess o .git
    location ~ /.(?!well-known) {
        deny all;
    }
}

Lo snippet snippets/fastcgi-php.conf di Ubuntu contiene già try_files $fastcgi_script_name =404;, che impedisce di far eseguire a PHP file inesistenti, e include fastcgi.conf con i parametri standard. L’eccezione .well-known nell’ultimo blocco lascia passare le verifiche di Let’s Encrypt.

Attivate il sito, disattivate quello di esempio, controllate e ricaricate:

sudo ln -s /etc/nginx/sites-available/TUO_DOMINIO /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

Verifica: sudo nginx -t deve stampare due righe: the configuration file /etc/nginx/nginx.conf syntax is ok e configuration file /etc/nginx/nginx.conf test is successful. Se compare test failed, Nginx indica file e riga dell’errore: non ricaricate finché il test non passa.

Un ritocco consigliato: controllate la direttiva server_tokens nel blocco http di /etc/nginx/nginx.conf (nel pacchetto Debian è già off, accompagnata dal commento che lo raccomanda). Se trovate un valore diverso, impostate server_tokens off; per non pubblicare la versione di Nginx nelle pagine di errore e nelle intestazioni, poi sudo nginx -t e sudo systemctl reload nginx.

Passo 5: la pagina di test PHP (da cancellare subito dopo)

echo '<?php phpinfo();' > /var/www/TUO_DOMINIO/public/info.php

Verifica: aprendo http://TUO_DOMINIO/info.php deve comparire la tabella di PHP con “Server API: FPM/FastCGI” e la versione 8.5. Se il browser scarica il file invece di mostrarlo, il blocco location ~ .php$ non viene applicato.

Attenzione: phpinfo() espone percorsi, moduli e configurazione del server. Cancellate il file appena finito il controllo: rm /var/www/TUO_DOMINIO/public/info.php.

Passo 6: tuning dei processi PHP per un VPS da 1–2 GB

Il pool predefinito /etc/php/8.5/fpm/pool.d/www.conf usa pm = dynamic con pm.max_children = 5, pm.start_servers = 2, pm.min_spare_servers = 1 e pm.max_spare_servers = 3. Il valore che conta è pm.max_children: il numero massimo di processi PHP contemporanei. Troppo basso, e sotto carico le richieste si mettono in coda; troppo alto, e la RAM finisce.

Il calcolo si fa con dati reali. Dopo qualche ora di traffico normale misurate quanta memoria occupa ogni processo:

ps -C php-fpm8.5 -o rss= | awk '{sum+=$1; n++} END {print sum/n/1024 " MB medi su " n " processi"}'

Poi applicate la regola: RAM disponibile per PHP diviso memoria media di un processo. Su un VPS da 2 GB, togliendo circa 500–700 MB per sistema, Nginx e MariaDB, restano grosso modo 1,3 GB; con processi da 60–80 MB si arriva a 15–20 figli. Su un VPS da 1 GB conviene stare tra 5 e 8.

ImpostazioneVPS 1 GBVPS 2 GBNote
pmondemanddynamicondemand crea processi solo quando servono: utile se la RAM è poca e il traffico basso
pm.max_children5–815–20da ricalcolare con la misura reale
pm.process_idle_timeout10snon usatosolo con ondemand
pm.max_requests500500ricicla i processi e contiene eventuali perdite di memoria

Dopo ogni modifica: sudo php-fpm8.5 -t per il test della configurazione, poi sudo systemctl reload php8.5-fpm. Se nel log /var/log/php8.5-fpm.log compare l’avviso che il pool ha raggiunto pm.max_children, è il segnale che il valore è troppo basso per il vostro traffico.

Se qualcosa va storto

  • 502 Bad Gateway: Nginx non riesce a parlare con PHP-FPM. Nel log del sito trovate una riga con connect() to unix:/run/php/... failed. Le cause tipiche: il servizio php8.5-fpm è fermo, oppure il percorso del socket è sbagliato (classico dopo aver copiato una configurazione con php8.3-fpm.sock o, su Debian, scrivendo 8.5 invece di 8.4).
  • Il browser scarica i file .php: manca il blocco location ~ .php$ o il sito non è attivo in sites-enabled. Controllate con sudo nginx -T | grep server_name quali blocchi sono caricati.
  • bind() to 0.0.0.0:80 failed all’avvio di Nginx: un altro servizio (spesso Apache) occupa la porta 80. Verificate con sudo ss -tlnp | grep ':80'.
  • ERROR 1045 (28000): Access denied for user in MariaDB: password sbagliata o utente creato con un host diverso da localhost. Rientrate con sudo mariadb e ricreate l’utente.
  • 404 su tutte le pagine: la direttiva root non corrisponde alla cartella reale, oppure i permessi impediscono a www-data di leggere i file.

Come tornare indietro

Per spegnere un sito senza cancellarlo basta togliere il collegamento: sudo rm /etc/nginx/sites-enabled/TUO_DOMINIO, poi sudo nginx -t e sudo systemctl reload nginx. Per rimuovere l’intero stack: sudo apt purge nginx nginx-common php8.5-fpm mariadb-server seguito da sudo apt autoremove.

Attenzione: prima di rimuovere MariaDB esportate i database con sudo mariadb-dump --all-databases > backup-completo.sql. Durante il purge apt può chiedere se cancellare anche i dati in /var/lib/mysql: rispondendo sì sono persi definitivamente.

La nostra lettura

Con i pacchetti di Ubuntu 26.04 lo stack LEMP si installa in pochi minuti; il tempo va speso su tre cose che fanno la differenza in produzione: il percorso giusto del socket, pm.max_children calcolato sulla RAM reale e nessun file di test dimenticato online. Il passo successivo è l’HTTPS con https://hardwarfare.it/ai-software/linux/certificato-https-lets-encrypt-certbot/, poi l’applicazione: per WordPress trovate la procedura completa in https://hardwarfare.it/ai-software/linux/installare-wordpress-vps-nginx-wp-cli/. Se preferite Apache, il confronto onesto è in https://hardwarfare.it/ai-software/linux/installare-lamp-apache-php-mariadb-ubuntu/.

Articolo redatto con il supporto di strumenti di intelligenza artificiale e verificato dalla redazione. Come usiamo l'AI · Come lavoriamo

Redazione HardWarfare
Redazione HardWarfarehttps://hardwarfare.it/chi-siamo/
La redazione di HardWarfare segue hardware PC, gaming, smartphone, sicurezza informatica e mercato tech. Ogni articolo parte da fonti primarie linkate in calce, viene verificato da un revisore diverso da chi lo scrive e si aggiorna quando i fatti cambiano. Scriveteci da Contatti per segnalazioni e correzioni.

Da non perdere

Articoli correlati

LASCIA UN COMMENTO

Scrivi il tuo commento!
Inserisci il tuo nome