GuideGuide

Sicurezza VPS per hosting siti: guida Ubuntu 24.04 passo passo

Un VPS appena acceso è esposto a Internet con impostazioni pensate per funzionare, non per resistere agli attacchi. Per mettere in sicurezza un VPS Ubuntu 24.04 che ospita siti bastano pochi interventi mirati: accesso SSH solo con chiavi, firewall con le sole porte necessarie, fail2ban, aggiornamenti di sicurezza automatici, un utente Linux e un pool PHP-FPM separati per ogni sito, scansioni antimalware e backup fuori dal server. In questa guida trovi i comandi per farlo a mano; in fondo vediamo cosa fa già Koapanel appena installato.

Da dove arrivano davvero gli attacchi

Su un server di hosting i problemi nascono quasi sempre da tre cause:

  • password deboli su SSH, sul pannello o su wp-admin, provate a raffica da bot automatici;
  • plugin e temi vulnerabili (soprattutto WordPress) che permettono di caricare una web shell;
  • siti non isolati: se tutti i siti girano con lo stesso utente, un sito compromesso legge e modifica tutti gli altri.

Ogni passo che segue chiude una di queste porte. L'ordine conta: prima l'accesso, poi la rete, poi i siti.

1. SSH: chiavi, niente password, niente root con password

Sul tuo computer genera una chiave (se non ne hai già una) e copiala sul server:

ssh-keygen -t ed25519 -C "tuo-nome@portatile"
ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@IP-DEL-SERVER

Crea un utente amministrativo se lavori ancora come root:

sudo adduser deploy
sudo usermod -aG sudo deploy

Poi scrivi le impostazioni in un file separato. Su Ubuntu 24.04 /etc/ssh/sshd_config include per prima cosa /etc/ssh/sshd_config.d/*.conf, e in SSH vince il primo valore letto: un file che inizia con 00- ha la precedenza anche su 50-cloud-init.conf, che su molti VPS riattiva le password.

sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no

Controlla la sintassi e riavvia il servizio (su Ubuntu si chiama ssh, non sshd):

sudo sshd -t && sudo systemctl restart ssh

Tieni aperta la sessione attuale e prova ad entrare da un secondo terminale prima di chiudere la prima. Se vuoi cambiare anche la porta, ricorda che Ubuntu 24.04 usa l'attivazione tramite socket: dopo la modifica servono sudo systemctl daemon-reload e sudo systemctl restart ssh.socket.

2. Firewall con ufw

ufw è già presente su Ubuntu. Apri solo quello che serve: SSH, web e, se c'è, il pannello.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status verbose

limit blocca temporaneamente un indirizzo che apre 6 o più connessioni in 30 secondi: un primo filtro contro i tentativi a raffica. MariaDB non va mai aperto verso Internet: su Ubuntu ascolta già solo su 127.0.0.1 (bind-address in /etc/mysql/mariadb.conf.d/50-server.cnf). Verifica cosa è in ascolto con:

sudo ss -tulpn

Attenzione se usi Docker: le porte pubblicate dai container scavalcano le regole di ufw, quindi vanno controllate a parte.

3. fail2ban contro i tentativi ripetuti

sudo apt update && sudo apt upgrade
sudo apt install fail2ban

Aggiorna i pacchetti prima: la versione di fail2ban uscita con Ubuntu 24.04 aveva un problema con Python 3.12, corretto negli aggiornamenti. Non modificare jail.conf: crea /etc/fail2ban/jail.local.

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
bantime.increment = true
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
[sshd]
enabled = true

Sostituisci 203.0.113.10 con l'IP del tuo ufficio. Poi:

sudo systemctl enable --now fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Per sbloccare un indirizzo: sudo fail2ban-client set sshd unbanip 198.51.100.7.

4. Aggiornamenti di sicurezza automatici

Su Ubuntu Server unattended-upgrades è di solito già installato. Verifica che sia attivo:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
sudo unattended-upgrade --dry-run --debug

Il comportamento si regola in /etc/apt/apt.conf.d/50unattended-upgrades. La scelta più prudente per un server di hosting è installare da soli i soli aggiornamenti di sicurezza e riavviare a mano in un momento tranquillo (Unattended-Upgrade::Automatic-Reboot "false";). Per sapere se serve un riavvio:

cat /var/run/reboot-required 2>/dev/null || echo "Nessun riavvio richiesto"

5. Un utente Linux e un pool PHP-FPM per ogni sito

È il punto che fa la differenza tra "un sito bucato" e "tutto il server bucato". Crea un utente di sistema senza shell per il sito:

sudo useradd --system --user-group --home-dir /var/www/esempio.it --shell /usr/sbin/nologin sito_esempio
sudo mkdir -p /var/www/esempio.it/{public_html,tmp,logs}

Poi un pool dedicato in /etc/php/8.3/fpm/pool.d/esempio.it.conf (8.3 è la versione PHP di Ubuntu 24.04):

[esempio.it]
user = sito_esempio
group = sito_esempio
listen = /run/php/php8.3-fpm-esempio.it.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 30s
php_admin_value[open_basedir] = /var/www/esempio.it/:/tmp/
php_admin_value[upload_tmp_dir] = /var/www/esempio.it/tmp
php_admin_value[session.save_path] = /var/www/esempio.it/tmp
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen
php_admin_flag[expose_php] = off

disable_functions può rompere qualche plugin che lancia comandi: provalo sito per sito. Verifica e ricarica:

sudo php-fpm8.3 -t && sudo systemctl reload php8.3-fpm

Nel blocco server di nginx, fastcgi_pass punta al socket del sito (unix:/run/php/php8.3-fpm-esempio.it.sock), e ogni sito ha il suo.

6. Permessi dei file

PHP gira con l'utente del sito, nginx (www-data) deve solo leggere. Uno schema semplice: proprietario il sito, gruppo www-data, cartelle con il bit setgid così i file nuovi ereditano il gruppo.

sudo chown -R sito_esempio:www-data /var/www/esempio.it
sudo find /var/www/esempio.it -type d -exec chmod 2750 {} +
sudo find /var/www/esempio.it -type f -exec chmod 640 {} +
sudo chmod 600 /var/www/esempio.it/public_html/wp-config.php

Niente 777, mai: se un plugin lo chiede, il problema è l'utente con cui gira PHP, non i permessi.

7. WordPress: le protezioni che contano

WordPress è il bersaglio più frequente perché è il più diffuso. Le misure più utili:

  • niente PHP nella cartella uploads e XML-RPC chiuso, direttamente in nginx:
location ~* ^/wp-content/uploads/.*\.php$ { deny all; }
location = /xmlrpc.php { deny all; }
  • login limitato: nel blocco http di nginx limit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m; e nella location = /wp-login.php limit_req zone=wplogin burst=5 nodelay; (insieme alle solite direttive FastCGI);
  • editor dei file disattivato in wp-config.php: define('DISALLOW_FILE_EDIT', true);
  • controllo dell'integrità con WP-CLI, eseguito come utente del sito:
sudo -u sito_esempio wp core verify-checksums --path=/var/www/esempio.it/public_html
sudo -u sito_esempio wp plugin verify-checksums --all --path=/var/www/esempio.it/public_html
  • aggiornamenti costanti di core, plugin e temi, e rimozione di quelli inutilizzati.

Per l'impostazione completa di un server WordPress vedi anche la guida hosting WordPress su VPS.

8. Scansione antimalware

ClamAV riconosce i malware noti; per le web shell PHP servono anche controlli euristici.

sudo apt install clamav clamav-daemon
sudo systemctl enable --now clamav-freshclam
sudo clamscan -r -i --max-filesize=20M /var/www

Il demone clamd tiene in memoria le firme (oltre un gigabyte di RAM): su un VPS da 2 GB conviene usare solo clamscan di notte. Due controlli rapidi che trovano molte infezioni:

sudo find /var/www -path '*/wp-content/uploads/*' -name '*.php'
sudo find /var/www -type f -name '*.php' -mtime -2

Il primo elenca file PHP negli upload (quasi sempre sospetti), il secondo i PHP modificati negli ultimi due giorni.

9. Backup fuori dal server

Nessuna di queste misure sostituisce un backup. Copia file e database su uno storage esterno, cifrati, con più versioni conservate. Lo spieghiamo passo passo in backup dei siti su S3 con restic.

10. Monitoraggio minimo

Non serve uno stack complesso per accorgersi dei problemi:

systemctl --failed
last -a | head -20
sudo journalctl -u ssh --since today | grep -i accepted
df -h

Aggiungi un controllo esterno di disponibilità (qualsiasi servizio di uptime che ti avvisa via email) e un avviso quando il disco supera il 90%: un disco pieno ferma database e posta.

Cosa fa Koapanel appena installato

Se non vuoi mantenere tutto questo a mano, Koapanel applica gran parte di queste misure da solo su Ubuntu 24.04. Secondo il manuale:

Misura In Koapanel
Firewall ufw gestito dalla pagina Sicurezza: regole consenti, rifiuta o limita, anche per singolo IP; le regole di SSH e del pannello non si possono eliminare, così non ti chiudi fuori
fail2ban indirizzi bloccati visibili, sblocco e blocco manuale, tentativi, durata, finestra e IP mai bloccati configurabili
Aggiornamenti di Ubuntu aggiornamenti di sicurezza automatici attivi dopo l'installazione, riavvio automatico facoltativo, elenco dei pacchetti in attesa (aggiornamenti)
Isolamento per ogni sito utente Linux, pool PHP-FPM, open_basedir, tmp e sessioni private
Accesso ai file solo SFTP (niente FTP), chiuso nella cartella del sito e senza comandi; chiavi SSH al posto della password
WordPress login limitato a 10 tentativi al minuto, fail2ban su login e XML-RPC, XML-RPC chiuso, PHP bloccato negli upload, editor disattivato, file sensibili non scaricabili, integrità controllata ogni notte (WordPress)
Antimalware scanner euristico integrato + ClamAV, con modalità scelta in base alla RAM (demone da 4 GB, su richiesta sui server più piccoli), scansioni notturne incrementali a bassa priorità (antimalware)
Tempo reale ogni file PHP, JS, HTML, SVG, .htaccess o .user.ini scritto in un sito viene controllato pochi secondi dopo; solo i rilevamenti certi vanno subito in quarantena (protezione in tempo reale)
Quarantena reversibile: ripristino, falso positivo, riparazione del core WordPress senza toccare wp-content
Registro e avvisi registro di chi ha fatto cosa, email per disco oltre il 90%, backup non riuscito, password cambiata
Backup restic cifrato su S3 o disco (backup e ripristino)

Anche le chiavi S3 e i token DNS sono salvati cifrati sul server, e gli aggiornamenti del pannello sono firmati: il pannello controlla la firma prima di installarli.

Cosa resta a te

  • La configurazione di SSH per il tuo accesso amministrativo (sezione 1). Attenzione: se dai ai clienti l'accesso SFTP con password generata dal pannello, non disattivare le password per tutti. Metti in fondo a /etc/ssh/sshd_config un blocco Match User root,deploy con PasswordAuthentication no, oppure usa solo chiavi anche per SFTP.
  • Un backup esterno configurato davvero, con la password del repository conservata lontano dal server.
  • Il monitoraggio esterno della disponibilità dei siti.

Per onestà: Koapanel non include un web application firewall. Se ti serve un WAF con regole commerciali, soluzioni come Imunify360 sull'ecosistema cPanel/CloudLinux coprono di più, a un costo maggiore. Koapanel inoltre gira solo su Ubuntu 24.04 con nginx: niente Apache e niente .htaccess come meccanismo di configurazione.

Domande frequenti

Cambiare la porta SSH serve?

Riduce i tentativi automatici nei log, ma non protegge da chi ti cerca davvero. La protezione vera è l'accesso solo con chiavi più fail2ban.

Basta ClamAV per trovare le web shell?

No. ClamAV riconosce soprattutto malware già noti; molte web shell PHP sono offuscate e cambiano spesso. Servono anche controlli euristici e il confronto con i checksum ufficiali di WordPress.

Devo attivare il riavvio automatico dopo gli aggiornamenti?

Su un server con siti in produzione è meglio di no: installa da solo gli aggiornamenti di sicurezza e scegli tu quando riavviare, controllando /var/run/reboot-required.

Un utente per sito rallenta il server?

No in modo apprezzabile. Con pm = ondemand i processi PHP di un sito partono solo quando arrivano richieste, quindi anche molti pool su un VPS piccolo occupano poca memoria.

Koapanel funziona su Debian o Ubuntu 22.04?

No, solo su Ubuntu 24.04 LTS, installato da zero.

Prova su un server nuovo

Puoi seguire questa guida a mano oppure installare Koapanel su un Ubuntu 24.04 appena creato e trovare firewall, fail2ban, isolamento dei siti e antimalware già attivi. È gratuito fino a 3 siti per uso personale:

curl -fsSL https://get.koapanel.app | sudo bash

Vuoi vederlo prima? Apri la demo pubblica oppure leggi la guida all'installazione e i prezzi.

Prova Koapanel sul tuo server

Un comando su Ubuntu 24.04, gratuito fino a 3 siti. Sei un provider o un'agenzia? Parliamo di prezzi all'ingrosso e migrazioni.

Altre guide