Questa è la guida all'installazione, alla configurazione e alla manutenzione di Arcivéo Monitor. Le sezioni sono raggruppate: panoramica generale, distribuzione del pannello, integrazione degli strumenti di sicurezza, moduli integrati e diagnostica. I comandi possono essere copiati con il pulsante a destra.
L'installazione del pannello è descritta in pagine passo-passo dedicate. Scelga il metodo:
Arcivéo Monitor è il pannello di sicurezza del server. Raccoglie i dati dagli strumenti installati (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco e altri) e li mostra in un'interfaccia unica con dashboard, mappa degli attacchi e pagine dettagliate per ogni strumento.
Il monitor non è uno strumento di protezione attivo: non blocca gli attacchi da solo. Il suo compito è aggregare le informazioni dagli strumenti già in funzione e presentarle in modo chiaro.
Il monitor funziona solo in locale: deve essere installato sullo stesso server che monitora. Non usa né SSH né API remote.
Tutti i comandi (fail2ban-client, ufw status, ipset list ecc.) vengono eseguiti dalla dashboard con l'utente del web server (di solito www-data, sui pannelli di hosting l'account del sito) con un set ristretto di permessi sudo, limitati a specifiche utility, senza accesso root generale. I risultati vengono analizzati e mostrati nel browser.
Il punteggio parte dal massimo e diminuisce per ogni problema rilevato:
PermitRootLogin yes) — −20Risultato: 80+ = Protetto, 60–79 = Attenzione, <60 = A rischio.
WebAuthn — standard di autenticazione senza password tramite chiave hardware. Supporta YubiKey, Touch ID, Face ID, Windows Hello, Passkey.
Dopo l'accesso con password, il sistema richiede una conferma tramite la chiave registrata. Anche se la password viene compromessa, senza la chiave fisica o la biometria non è possibile accedere.
Per la configurazione apra Chiavi WebAuthn nel menu laterale e prema «Registra chiave». Registri subito due chiavi: se l'unica chiave va persa o si rompe, l'accesso al pannello con essa non sarà possibile.
Il pannello può inviare il report di sicurezza su Telegram e via email (con un pulsante o pianificato). Si configura nella sezione «Impostazioni».
Telegram. Servono un token del bot e un chat id:
@BotFather → /newbot → riceverà un token del tipo 123456:ABC....@userinfobot, oppure apra https://api.telegram.org/bot<TOKEN>/getUpdates e trovi "chat":{"id":...}.Email. Due metodi a scelta in «Impostazioni» → Email:
re_...) e un dominio mittente verificato.Stato del report: «ATTENZIONE» o «OK». L'intestazione diventa «ATTENZIONE» solo in caso di un problema reale o di un'azione in sospeso: minaccia rilevata da ClamAV, modifiche ai file in AIDE, eventi critici di Falco (Emergency/Alert/Critical nelle ultime 24 h), servizio caduto in Monit, riavvio richiesto, SSL in scadenza (≤14 giorni) o aggiornamenti di sicurezza in attesa. Il rumore di fondo — tentativi SSH dei bot, IP bannati da fail2ban, avvisi Suricata, avvertimenti Lynis e richieste già respinte da ModSecurity — non alza lo stato, quindi questi numeri nel report non significano di per sé «ATTENZIONE».
I moduli dettagliati di monitoraggio (Lynis, UFW, ModSecurity, mappa degli attacchi, AIDE, ClamAV e altri) si sbloccano con una licenza valida. Senza di essa la dashboard, le impostazioni e l'account funzionano, mentre i moduli mostrano la scheda «Licenza richiesta».
Dopo l'acquisto, nell'area personale trova un codice di attivazione del tipo ARCIVEO-XXXX-XXXX-XXXX-XXXX. Deve «attivarlo» sul dominio del suo pannello: questo trasforma il codice in un file di licenza firmato (blocco [license]) che Lei incolla nel pannello.
Come attivare (3 passaggi):
my.arciveo.com → sezione «Licenze» / «Attivazione licenza» — copi il codice ARCIVEO-….monitor.example.com). Prema attiva: il sistema genererà un file di licenza associato a questo dominio e lo mostrerà in un campo con il pulsante «Copia».Il pannello verifica la chiave a livello crittografico: firma, associazione al dominio e validità.
APP_URL in config.php e inserisca solo il nome host — senza https:// e senza prefisso www. L'attivazione è irripetibile: il codice diventa una licenza per il dominio inserito e non si riattiva — in caso di errore nel dominio la chiave non sarà valida per il suo pannello e il codice risulterà consumato. Inserisca quindi il dominio con attenzione.
Tutti i parametri principali del pannello sono definiti in un unico file config.php nella radice (accanto alla cartella public/) tramite normali costanti define(). Il file viene creato durante l'installazione; raramente serve modificarlo a mano — principalmente al cambio di dominio, al trasferimento o alla connessione a un altro database. Dopo ogni modifica riavvii PHP-FPM (altrimenti, a causa di OPcache, le modifiche non verranno applicate).
Inserisca i suoi valori nei punti evidenziati; lasci il resto invariato:
Database. Credenziali di connessione a MySQL/MariaDB:
DB_HOST — host del DBMS, quasi sempre localhost;DB_NAME — nome del database del pannello;DB_USER — utente del DB (accesso solo al proprio database);DB_PASS — password di questo utente;DB_CHARSET — codifica della connessione, lasci utf8mb4.Applicazione.
APP_URL — indirizzo completo del pannello (es. https://monitor.example.com). Deve coincidere con il dominio su cui è attivata la licenza — altrimenti la chiave verrà rifiutata (veda la sezione «Licenza»);TIMEZONE — fuso orario di PHP: influisce solo su come il pannello mostra date e ora. Sul momento di avvio delle attività cron non influisce — lì vale il fuso del sistema (veda «Tutte le attività cron»).Durata della sessione. SESSION_LIFETIME — timeout di inattività della sessione in secondi (scorrevole: si aggiorna con l'attività). Per impostazione predefinita 28800 = 8 ore; dopo questo tempo di inattività il pannello chiederà di accedere di nuovo. Ad esempio, 3600 = 1 ora, 86400 = un giorno.
Registrazione degli errori. Gli errori non vengono mai mostrati ai visitatori, ma scritti in logs/php_errors.log — sono visibili nella pagina «Log dell'applicazione». Queste righe (display_errors=0, log_errors=1, percorso error_log) di solito non vanno modificate — le impostazioni sono definite direttamente nel file e non dipendono da php.ini.
public/), e per questo pannello la radice web (DocumentRoot) è proprio la radice del pannello, non public/. Di per sé il file non «trapela»: nel .htaccess della radice c'è per esso un divieto esplicito (Require all denied) — il server restituisce 403. Anche senza questa regola il sorgente non trapelerebbe: è PHP — il server lo esegue, non lo restituisce come testo. A ogni buon conto: non lo pubblichi in repository pubblici e non lo invii al supporto con la password reale. Permessi del file — 640.
UFW (Uncomplicated Firewall) è una semplice interfaccia per nftables/iptables. Chiude tutte le porte in ingresso tranne quelle esplicitamente consentite. La pagina «Firewall UFW» mostra lo stato e le regole.
ufw enable consenta assolutamente SSH (ufw allow OpenSSH), altrimenti perderà l'accesso al server.
deny non è considerata accessibile dall'esterno.
Skipping adding existing rule non è un errore. È il modo in cui UFW segnala che una regola identica esiste già e non la aggiunge di nuovo. Alla riesecuzione della configurazione automatica (che è idempotente) questo è un messaggio normale: non serve intervenire.
Blocca automaticamente gli IP dopo il superamento del numero di tentativi di accesso falliti. Analizza i log di SSH, nginx, Apache e altri servizi.
L'installazione di base è sopra. Qui trova la configurazione operativa che dà decine di jail attive e migliaia di ban: impostazioni generali, jail chiave e ban automatico degli IP dannosi dalla lista ipsum.
Il file /etc/fail2ban/jail.local — impostazioni generali e le jail più importanti:
ignoreip inserisca tassativamente il suo IP e le reti fidate, altrimenti rischia di bannare se stesso. Dopo le modifiche: sudo fail2ban-client reload.
Caricamento automatico della blocklist ipsum — nel cron di root (sudo crontab -e): il level 1 (100.000+ IP) viene caricato nel set ipsum, che viene tagliato sul firewall (maggiori dettagli nella sezione «Blocklist IPset»):
ipsum — è esattamente quello che legge la dashboard (scheda «IPset ipsum»). Livelli: levels/1.txt — copertura massima, levels/3.txt — più preciso (3+ fonti).
Perché il «Monitor di sicurezza» è diviso in due zone. La protezione lavora su due livelli, e la dashboard non li mescola:
sshd, apache-*, nginx-* ecc.) e recidivi ostinati (jail recidive — quelli già bannati più volte). Sono gli IP che si sono davvero introdotti da lei — sono sulla mappa degli attacchi e sulla «Linea temporale».ipset ipsum, tagliata sul firewall con la regola DROP. Questi indirizzi nella maggior parte dei casi non hanno nemmeno toccato il suo server — vengono tagliati in anticipo; il contatore «IPset ipsum» mostra quanti sono stati bloccati preventivamente.La differenza è semplice: reattivo — «questi hanno attaccato e sono stati bannati», preventivo — «questi sono stati bloccati prima del tentativo». Prima nel recidive veniva forzata artificialmente la list-3 ipsum (da qui la vecchia divisione «recidive da lista»); ora recidive contiene solo i veri recidivi, mentre il preventivo è interamente sul firewall.
ipsum — elenco pubblico di IP dannosi, aggiornato quotidianamente. Il monitor mostra il numero di indirizzi caricati sulla dashboard e sulla mappa degli attacchi e lo considera nel Punteggio di sicurezza (−10 se il set non è caricato).
Variante minima senza fail2ban — un set ipsum separato con blocco tramite iptables:
@reboot. Allo stesso tempo il comando create … -exist imposta il limite maxelem 300000 (il valore predefinito 65536 — il level 1 non ci sta, si otterrà «Hash is full»):
ipsum e, se il firewall è gestito dall'installer (VPS nuovo — profili «Completa»/«Alleggerita»), collega il set a UFW con una regola DROP — il traffico da questi IP viene effettivamente bloccato. La regola sta dopo ESTABLISHED,RELATED, quindi le connessioni correnti (incluso il Suo SSH) non si interrompono — vengono bloccate solo le nuove connessioni dall'elenco. Il set viene ripristinato all'avvio del servizio ipsum-load.service prima del firewall (altrimenti UFW non si avvierebbe) e aggiornato dal cron alle 04:00. Su un server già configurato (pannello, firewall proprio) l'installer non tocca il firewall — lì ipsum resta un elenco per la dashboard e la mappa degli attacchi, mentre la regola DROP si aggiunge manualmente se lo si desidera (la variante minima con iptables … --match-set ipsum … -j DROP è sopra). Con l'installazione automatica non serve fare nulla manualmente.
Sostituto moderno di Fail2ban con threat intelligence collaborativa: blocchi dalla community più regole proprie. Richiede un bouncer separato per applicare i blocchi al firewall.
systemctl is-active crowdsec). Per avviarlo: sudo systemctl enable --now crowdsec; in caso di crash consultare sudo journalctl -u crowdsec -n 30. La stessa regola vale per qualsiasi servizio in stato «Non in esecuzione» (Suricata, Falco, Monit, MySQL).
stream halted / i blocchi non vengono applicati. È una api-key orfana: il bouncer è stato rimosso da cscli bouncers list, ma la sua vecchia chiave è rimasta in /etc/crowdsec/bouncers/*.yaml. Riregistri il bouncer e inserisca la chiave aggiornata:
AIDE (Advanced Intrusion Detection Environment) crea un'istantanea del file system e a ogni controllo segnala le modifiche in /etc, /bin, /usr. Dopo l'installazione è obbligatoria l'inizializzazione del database (aideinit).
aideinit il terminale resta 5–15 minuti sulla riga Running aide --init... — è normale (hashing dell'intero file system, carico sul disco). Non interrompa con Ctrl+C. Se il processo sembra «bloccato» ma non scrive nulla, potrebbe attendere una risposta a una richiesta nascosta Overwrite existing aide.db.new [Yn]? (prema Y). Per verificare l'attività da un'altra sessione: pgrep -af aide.
aideinit: «21_aide_spamassassin … printf: invalid number» (return code 20) — un bug noto dello snippet di configurazione di AIDE su Ubuntu 22.04. Il database non viene creato. Rimuova lo snippet difettoso e riprova:
aideinit non è stato eseguito, oppure (Ubuntu 24.04) la cartella /var/lib/aide è stata creata in modalità 700 ed è inaccessibile a www-data — si risolve con sudo chmod 755 /var/lib/aide (vedere il blocco sopra). «Nessun controllo eseguito» = il database esiste, ma il controllo non è ancora stato eseguito — non è un errore. I risultati vengono letti dal monitor in /var/log/aide/aide.log.
/etc/cron.daily/aide sulle Ubuntu/Debian recenti potrebbe non scrivere /var/log/aide/aide.log nel formato richiesto (e in esse aide.wrapper non esiste più). È più affidabile aggiungere un proprio cron con --config esplicito — scrive il log come root in modalità 644, e il monitor lo legge senza gruppi aggiuntivi:
chmod 755 /var/lib/aide e il cron di controllo alle 02:00 — manualmente non serve nulla.
sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.
Scanner antivirus per Linux. Particolarmente utile per controllare /var/www alla ricerca di shell PHP e codice dannoso.
enable --now? Tre cause tipiche:
1. Nella configurazione è rimasta la riga Example — clamd rifiuta di avviarsi finché è presente:
2. Il database delle firme non è stato scaricato — clamd non si avvia senza di esso:
3. Si sta semplicemente caricando — clamd carica in memoria ~8 milioni di firme in 30–60 sec. Attenda e verifichi: systemctl is-active clamav-daemon (stato activating → sta ancora caricando).
sudo journalctl -u clamav-daemon -n 30 --no-pager.
clamd tiene solo le firme in memoria, di per sé non scansiona nulla in modo pianificato. Il pannello mostra i risultati di una scansione pianificata, quindi serve un cron che scansiona e scrive un log. L'installazione automatica configura il wrapper /usr/local/bin/clamav-scan.sh e un cron alle 01:30 — dopo la prima esecuzione si popoleranno «File controllati» e «Ultima scansione». Per avviarla subito, senza attendere la pianificazione: sudo /usr/local/bin/clamav-scan.sh.
Linux Malware Detect (LMD) — scanner di malware per le minacce web: shell PHP, backdoor web, downloader. Usa il motore di ClamAV e lo integra con le proprie firme.
maldet --report.
update-rc.d: error: unable to read /etc/init.d/maldet — è innocua. maldet non usa init.d, l'aggiornamento delle firme e le scansioni vengono avviati tramite /etc/cron.daily/maldet. Se sotto compare installation completed — tutto è installato correttamente.
apt, ma in /usr/local/maldetect, e con open_basedir attivo la sua presenza viene verificata tramite shell — vedere la sezione «La pagina è vuota anche se i dati sono presenti sul server».
Sistema di rilevamento delle intrusioni di rete: analizza il traffico a livello di pacchetti e conosce migliaia di firme di attacco. Completa ModSecurity (che opera a livello HTTP, mentre Suricata a livello TCP/IP).
/var/log/suricata/eve.json come root con la directory in modalità 750, e il server web (www-data) non riesce a leggerlo. Apra la directory in attraversamento — i file al suo interno restano protetti:
Intercetta le chiamate di sistema tramite eBPF/kernel module e rileva anomalie in tempo reale: shell da nginx, lettura di /etc/passwd da parte di un processo web, scrittura in /bin ecc.
journalctl -u falco (senza sudo — tramite il gruppo systemd-journal). Verifichi che www-data sia in questo gruppo — veda «Configurazione di sudo» (punto 2) nella pagina di installazione manuale.
/etc/passwd, scrittura nelle directory di sistema). Zero eventi critici in un giorno su un server tranquillo è uno stato sano.
journalctl richiede i permessi sul registro; affinché il pannello veda gli eventi in modo stabile, l'installazione automatica attiva in Falco file_output → /var/log/falco/falco.log e imposta al servizio UMask=0022 (il log è leggibile dal server web). Su una nuova installazione non è necessario configurarlo manualmente.
ModSecurity — web firewall (WAF) per Apache o Nginx. Blocca gli attacchi a livello applicativo: SQL injection, XSS, path traversal, scanner.
IncludeOptional /etc/modsecurity/*.conf, ma il pacchetto installa solo modsecurity.conf-recommended — che non rientra nella maschera *.conf. Se non lo si copia in modsecurity.conf, SecRuleEngine resta Off: il modulo è caricato, le regole CRS sono caricate, ma il traffico non viene controllato e il log di audit non viene creato. La modalità intermedia DetectionOnly si limita a registrare gli eventi nel log senza bloccare le richieste — il pannello la mostra in giallo.
Accesso del pannello al log di audit. Il log /var/log/apache2/modsec_audit.log appartiene a root (permessi 640), l'utente web non può leggerlo. Il pannello ottiene i dati tramite un wrapper — lo crei:
SecRuleEngine senza rientro: le righe con rientro si trovano all'interno dei blocchi <LocationMatch>/<Directory> (ad esempio, la disattivazione del WAF per phpMyAdmin) e non definiscono la modalità globale.www-data, in HestiaCP il pool del sito gira con il proprietario del sito (ad esempio, admin) — verifichi con grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.X-Forwarded-For. Nelle statistiche rientrano solo le transazioni con una regola attivata: la direttiva SecAuditLogRelevantStatus scrive nel log di audit qualsiasi risposta 4xx/5xx, quindi vi rientrano anche i normali 403/500 — che il pannello non conta come eventi WAF.---RULES--- serve alla sezione «Tutte le regole attive» — il pannello mostra non solo le regole attivate, ma tutte le regole CRS caricate + quelle personalizzate. I tre percorsi nel ciclo for f in … sono le posizioni tipiche per le regole CRS e le aggiunte locali; se ha una disposizione diversa (il pacchetto installa i file in una propria directory, oppure le regole personalizzate non si trovano in /etc/modsecurity/custom-rules.conf), individui i percorsi reali con il comando sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null e li inserisca nell'elenco. Se il wrapper è vecchio (senza questa sezione) — la sezione mostrerà semplicemente l'avviso «non disponibile», il resto della pagina funziona come prima.
Auditd (Linux Audit Daemon) registra le chiamate di sistema a livello di kernel: accessi e disconnessioni, comandi sudo, tentativi di autenticazione falliti, modifiche ai file. Il monitor mostra gli accessi, i tentativi falliti e i comandi sudo di oggi.
ausearch (/usr/sbin/ausearch) e, se necessario, da /var/log/audit/audit.log con il comando tail. Entrambi devono essere nel sudoers.
Sorveglia i servizi (nginx, php-fpm, mysql, ecc.) e li riavvia in caso di caduta. Può inviare avvisi via email.
monit status. In /etc/monit/monitrc deve essere abilitata l'interfaccia HTTP (blocco set httpd con allow localhost), altrimenti monit status restituirà un errore.
monitrc la riga set httpd è commentata (di default appare come # set httpd port 2812 …). Decommenti il blocco e consenta localhost. (2) Un httpd abilitato di per sé non monitora nulla — Monit considera solo ciò che è descritto dagli stanza check; senza di essi l'elenco è vuoto anche con l'interfaccia attiva. Configurazione minima funzionante:
conf.d pronto con httpd sulla 2812 e una serie di controlli — su una nuova installazione non serve configurare nulla manualmente.
PSAD analizza il registro di iptables e rileva le scansioni delle porte e gli attacchi di rete, assegnando a ciascuna sorgente un livello di minaccia (1–5). Integra fail2ban e Suricata.
psad --Status (necessario nei sudoers). Senza il logging di iptables la pagina sarà vuota — è normale finché non ci sono state scansioni.
Mandatory Access Control limita a quali file e risorse può accedere un programma, anche se viene compromesso. Su Ubuntu/Debian per impostazione predefinita si usa AppArmor (di solito già installato e attivo).
aa-status (necessario in sudoers). Mostra il numero di profili in modalità enforce/complain e i processi senza profilo.
«Profili caricati» in numero maggiore di enforce + complain è normale. In AppArmor 4.x (Ubuntu 24.04 e successivi) è comparsa la modalità unconfined: il profilo è caricato nel kernel, ma non limita nulla. Ubuntu contrassegna così decine di profili per programmi che usano user namespaces (browser, client torrent e simili). Quando esistono profili di questo tipo, la scheda «Profili caricati» diventa ambrata e ne mostra il numero — per esempio unconfined: 90 con 120 caricati e 26 in enforce. Proteggono realmente solo i profili in enforce; su Ubuntu 22.04 (AppArmor 3.x) questa modalità non esiste e i numeri coincidono sempre.
unconfined va fatto solo in modo consapevole: sono disattivati non per errore, ma perché altrimenti si comprometterebbe il funzionamento dei programmi stessi. I profili in complain sono un'altra cosa: lì le regole sono già scritte e semplicemente non vengono applicate.
debsums verifica che i file dei pacchetti installati corrispondano ai checksum del repository — individua i binari di sistema alterati (completa AIDE). La verifica completa richiede 1–2 minuti, per questo viene avviata via cron, mentre il pannello legge il risultato da data/debsums/debsums.log e lo suddivide automaticamente per categoria (contano solo binari e librerie).
L'attività va nel cron di root (sudo crontab -e). Il wrapper pronto debsums-scan.sh va messo in /usr/local/bin/ (chmod +x; vedere il riepilogo delle attività cron) e scrive automaticamente il report in data/debsums/ del pannello.
Il wrapper debsums-scan.sh trova da solo la cartella data/ del pannello — non serve indicare il percorso.
/etc/ (configurazioni) e /usr/share/ (risorse) sul server sono di solito normali — il pannello le evidenzia con un colore distinto. Sono preoccupanti le modifiche a binari e librerie (/bin, /sbin, /usr/lib ecc.) — la scheda «Binari / librerie» mostra proprio queste.
Lynis si avvia manualmente o tramite cron. Il report deve essere salvato nella cartella data/lynis/ del progetto: il monitor legge il file lynis-report.dat.
lynis-scan.sh in background direttamente dal pannello (senza attendere il cron): mostra «Scansione…» e al termine aggiorna da solo il report. Per questo l'utente web ha bisogno di una riga sudoers per eseguire lo script: il programma d'installazione la aggiunge automaticamente in /etc/sudoers.d/monitor. Se il pannello è stato installato manualmente/in precedenza, la aggiunga con lo stesso utente già indicato nel file:
Logwatch deve salvare i report giornalieri nella cartella data/logwatch/ del progetto in formato .txt. Il monitor mostra l'ultimo report e l'archivio.
Il monitor di rete non richiede installazione: è una pagina integrata nel pannello. Mostra lo stato di rete del server dalle sorgenti locali:
/proc/net/dev;ip;ss;journalctl -k.Le prime tre sorgenti funzionano senza sudo, perciò interfacce, traffico, connessioni e porte sono subito visibili. Il blocco «Eventi del kernel» usa journalctl -k, letto tramite il gruppo systemd-journal («Configurazione di sudo», p.2), sudo non serve. Per verificare che tutto sia accessibile all'utente web:
UFW BLOCK non compaiono qui: sono nelle pagine «Firewall UFW» e «Mappa degli attacchi». Un blocco vuoto con spunta verde = nessun problema di rete nelle ultime 24 ore.
La pagina integrata mostra tre cose:
df); la barra diventa rossa a ≥90%;lsblk), solo quelli reali (loop/snap nascosti);smartctl).Lo spazio e l'elenco dei dispositivi funzionano subito, senza configurazione. Per SMART serve il pacchetto smartmontools. Il processo web non ha accesso diretto ai dispositivi disco, perciò SMART viene rilevato tramite cron nel file data/disk/smart.txt, e il pannello lo legge.
L'attività va nel cron di root (sudo crontab -e). Il wrapper pronto smart-scan.sh va messo in /usr/local/bin/ (chmod +x; vedi il riepilogo delle attività cron) e scrive da solo in data/disk/ del pannello.
Il wrapper smart-scan.sh trova da solo la data/ del pannello — non serve indicare il percorso. Al suo interno lsblk -e7,11 esclude loop/cdrom.
La pagina mostra lo storico del carico del server nelle ultime 24 ore — Load Average, utilizzo CPU e attesa I/O, RAM/Swap, traffico di rete (ricezione/trasmissione), I/O del disco (lettura/scrittura), riempimento del disco e degli inode, descrittori di file aperti e connessioni MySQL, oltre al numero corrente di connessioni TCP e processi.
I dati vengono raccolti da cron/collect_metrics.php — una volta ogni 5 minuti scrive un'istantanea «grezza» dei contatori (/proc/loadavg, /proc/meminfo, /proc/stat, /proc/net/dev, /proc/diskstats, df/df -i, /proc/sys/fs/file-nr, SHOW GLOBAL STATUS LIKE 'Threads_connected') nella tabella del database system_metrics; le percentuali e le velocità le calcola la pagina stessa dalla differenza tra istantanee adiacenti (riempimento disco/inode/descrittori/connessioni MySQL sono valori istantanei, senza ricalcolo). Non serve sudo — le fonti vengono lette senza privilegi di root. I punti più vecchi di 24 ore vengono eliminati automaticamente a ogni scrittura.
Il wrapper collect-metrics-all.sh (vedere il riepilogo delle attività cron) individua da solo tutte le istanze del pannello installate sul server ed esegue cron/collect_metrics.php di ciascuna a nome del proprietario del sito.
Avvisi di carico (sezione «Impostazioni» → «Avvisi di carico») — al superamento della soglia di CPU/RAM/disco/inode il pannello invia una notifica su Telegram/Email (gli stessi canali del report giornaliero — non è necessario attivarli separatamente per gli avvisi), e un'altra — quando la metrica torna nella norma. Non invia spam ripetuto mentre la soglia rimane superata: la notifica successiva arriva solo dopo un ciclo «ripristinato → di nuovo superato».
collect_metrics.php a ogni esecuzione (una volta ogni 5 minuti) — non serve un cron separato. Lo stato «già notificato / non ancora» è memorizzato in data/alerts_state.json, le soglie nelle impostazioni del pannello.
La pagina «Mappa degli attacchi» determina il paese in base all'IP con il comando geoiplookup. Senza il pacchetto GeoIP i paesi non vengono rilevati e i punti sulla mappa non compaiono:
/usr/share/GeoIP/GeoIP.dat è leggibile da tutti, i risultati vengono memorizzati nella cache in tmp/geoip_cache.json. La mappa stessa (Leaflet + tile di OpenStreetMap) viene caricata nel browser: serve una connessione a internet sul computer da cui è aperto il pannello.
Due schede integrate della dashboard che mostrano non lo stato «on/off» di uno strumento, ma la reale sicurezza del server. Non richiedono installazione, vengono lette localmente senza sudo.
Esposizione esterna — quanti servizi ascoltano su tutte le interfacce (0.0.0.0/[::]) e sono raggiungibili dall'esterno. Evidenzia in rosso se all'esterno sono esposti DBMS o cache (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — è una falla diretta (−10 al Punteggio di sicurezza). Fonte: ss -tuln.
127.0.0.1 (bind-address nella configurazione MySQL/PostgreSQL, bind 127.0.0.1 in Redis) oppure chiuda la porta in UFW.
127.0.0.1 (loopback) è visibile solo al server stesso — dall'esterno non è raggiungibile, anche se la porta è «aperta». Per questo Postfix sulla porta 25, associato al loopback, è sicuro: la configurazione automatica imposta inet_interfaces = loopback-only (più un smtpd_banner neutro — che risolve il rilievo Lynis MAIL-8818 sulla divulgazione della versione). La scheda «Esposizione esterna» conta come esterno solo ciò che ascolta su 0.0.0.0/[::]; i servizi loopback non vi rientrano.
/etc/postfix/main.cf imposti smtpd_banner = $myhostname ESMTP (senza versione né sistema operativo) e inet_interfaces = loopback-only, poi sudo systemctl restart postfix.
Aggiornamenti di sicurezza — quante patch di sicurezza attendono l'installazione e se è necessario un riavvio dopo l'aggiornamento del kernel (−5 al Punteggio di sicurezza in presenza di patch). Fonte: /usr/lib/update-notifier/apt-check, file /var/run/reboot-required. L'elenco dettagliato è nella pagina «Aggiornamenti di sicurezza».
update-notifier-common). Se apt-check è assente, il monitor conta le patch tramite apt-get -s upgrade.
Aggiornamenti di sicurezza automatici (unattended-upgrades) — nella pagina «Aggiornamenti di sicurezza» una scheda dedicata mostra se l'installazione automatica delle patch di sicurezza è attiva e quando è stata eseguita l'ultima volta. Non serve sudo — lo stato viene letto tramite apt-config dump.
Il backup è l'assicurazione principale: la perdita di dati è peggiore di qualsiasi attacco. Servono due cose — un backup del server/dei siti e separatamente un backup del DB del pannello (contiene utenti, chiavi WebAuthn, impostazioni, licenza).
Opzione A — HestiaCP: scheda Backup dell'utente → pulsante di creazione del backup (o pianificato nelle impostazioni del server). Il backup include i siti e i loro DB.
Opzione B — manuale (cron): dump del DB + archivio della cartella data/ del pannello:
Aggiornamento a una nuova versione. Per prima cosa esegua un backup. Poi ricarichi i file del codice, conservando i suoi dati:
public/, includes/, assets/, cron/, database/, oltre ai file .htaccess nella radice (front controller — il routing non può essere lasciato dalla versione precedente), manifest.json, sw.js;config.php (dati del DB), data/ (report), logs/, tmp/ (sessioni e cache).SSH_FX_PERMISSION_DENIED — Permission denied. I file del pannello appartengono a www-data (così sono stati impostati durante l'installazione), mentre il client SFTP si collega con il suo utente, che non ha il permesso di scrittura. Assegnare l'intero pannello a www-data «perché funzioni» è proprio ciò che porta a questo errore; qui sotto tre metodi, ognuno risolve il problema.
data/ (report), tmp/ (sessioni e cache), logs/; restano di proprietà di www-data. Il resto è codice, e al web server serve solo in lettura, garantita dal gruppo www-data con permessi 644. Vantaggio secondario: con una falla in PHP i file del pannello non sono più sovrascrivibili. Sui pannelli di hosting (HestiaCP e simili) la variante A non serve: lì i file del sito appartengono già all'account con cui accede via SFTP, e il web server li legge tramite il gruppo.
chmod successivo sui file azzera la maschera ACL e l'accesso sparisce silenziosamente. Se dopo aver «rimesso ordine nei permessi» il caricamento si scontra di nuovo con Permission denied, ripeta entrambi i comandi setfacl.
2 della variante C è setgid: i file caricati via SFTP restano nel gruppo www-data, altrimenti il pannello non potrà sovrascriverli. Dopo la variante C si ricolleghi in FileZilla: il nuovo gruppo ha effetto solo a un nuovo accesso. Verifica: id deploy (deve comparire il gruppo www-data) e ls -ld /path/to/monitor (drwxrwsr-x: la lettera s indica che setgid è attivo).
Migrazione su un altro server:
config.php, data/.mysqldump sul vecchio → importazione sul nuovo; corregga i dati del DB in config.php.adm, attività cron.Se non riesce ad accedere, tutto si risolve direttamente nel DB dal server. Apra il DB (il nome è in config.php):
Chiave WebAuthn persa (il secondo fattore non funziona): disattivi la 2FA, acceda con la password e registri una nuova chiave:
Password dimenticata: imposti un nuovo hash (lo generi sul server e lo inserisca):
Si è bloccato da solo con il filtro IP: disattivi la limitazione:
sudo mysql sul server, oppure phpMyAdmin / la sezione DB nel pannello dell'hosting. Dopo il ripristino, riattivi WebAuthn e il filtro IP.
Il riepilogo dei job è nel crontab di root del server (si aggiungono con sudo crontab -e). Lasci solo le righe degli strumenti che utilizza; adatti i percorsi al suo server.
sudo crontab -l e che il servizio cron sia attivo.
TIMEZONE di config.php. La costante TIMEZONE influisce solo su PHP (su come il pannello mostra le date), ma il demone cron esegue i job secondo l'ora di sistema del SO. Se il fuso del server non coincide con il suo, il report delle «08:00» arriverà a un orario sbagliato. Esempio: il server è in un altro fuso (Europe/London, UTC+1) e Lei è a Roma (UTC+2) → il report delle «08:00» arriverà alle 09:00 ora sua. Verifichi e, se necessario, allinei il fuso del sistema al suo:
0 8 * * * scatterà alle 08:00 ora locale. Altrimenti bisognerebbe spostare cron stesso, ma con il passaggio ora solare/legale lo scostamento tornerebbe a disallinearsi — perciò è più corretto configurare il fuso del sistema.
crontab.txt) si trovano nella cartella system/ accanto al progetto, fuori da public_html. Non fanno parte del sito — non serve caricarli nella web root; li collochi sul server nei percorsi di sistema (come nel crontab sopra):
lynis-scan.sh → /usr/local/bin/ (chmod +x) — esegue lynis audit system, durante la scansione imposta il flag /tmp/lynis-running e copia lynis-report.dat in data/lynis/ del pannello;logwatch_daily.sh → /usr/local/bin/ (chmod +x) — genera il report giornaliero Logwatch (sshd, fail2ban, sudo, postfix) in data/logwatch/;smart-scan.sh → /usr/local/bin/ (chmod +x) — rileva lo stato dei dischi (smartctl) in data/disk/;debsums-scan.sh → /usr/local/bin/ (chmod +x) — verifica l'integrità dei pacchetti (debsums) in data/debsums/;clamav-scan.sh → /usr/local/bin/ (chmod +x) — scansione antivirus ClamAV sui percorsi a rischio (web, home, temp); scrive il riepilogo in /var/log/clamav/scan.log, da dove lo legge la pagina ClamAV (riga 01:30 nel crontab sopra);load-ipsum.sh → /usr/local/bin/ (chmod +x) — aggiorna il set ipset ipsum (level 1) sul posto, senza rompere le regole attive del firewall (riga 04:00 nel crontab qui sopra);daily-report-all.sh → /usr/local/bin/ (chmod +x) — avvia il report cron/daily_report.php del pannello (riga 08:00 nel crontab sopra);daily_report.php — è già incluso nel pannello (cron/daily_report.php), viene eseguito da daily-report-all.sh, non serve installarlo a parte;collect-metrics-all.sh → /usr/local/bin/ (chmod +x) — avvia cron/collect_metrics.php del pannello (pagina «Prestazioni», riga */5 nel crontab sopra); collect_metrics.php è già incluso nel pannello, non serve installarlo a parte;crontab.txt (system/cron/) — esempio di job; inserisca le righe necessarie con sudo crontab -e./usr/local/bin/. Direttamente da FileZilla non è possibile scriverci — la cartella appartiene a root e il client SFTP riceverà SSH_FX_PERMISSION_DENIED. La procedura è questa: prima caricare il file in /tmp (dove tutti possono scrivere), poi spostarlo al suo posto con un solo comando:
/tmp nella radice del server — non /var/tmp e non tmp/ all'interno del pannello stesso (quest'ultimo appartiene a www-data ed è inaccessibile al suo utente). Nell'albero di FileZilla /tmp è un ramo di livello superiore, accanto a var, non al suo interno.
/usr/local/bin/, log — /var/log/arciveo-cron.log) — non serve fare nulla manualmente.
/home/*/web/*/public_html e /var/www/*, e collocano i report nei rispettivi data/. Se il pannello si trova in un altro percorso, lo aggiunga alla riga for app in … all'interno degli script, altrimenti i report Lynis/SMART/debsums/Logwatch non arriveranno al pannello.
logs/cron.log viene creato per primo dal crontab di root — apparterrà a root, e la scheda «Registro cron» nel pannello non potrà né leggerlo né svuotarlo. Crei il file in anticipo come utente web (proprietario della cartella del sito; su HestiaCP è l'account, ad es. admin) — così il crontab di root si limiterà ad accodare, senza cambiare il proprietario:
stat -c %U /path/to/monitor.
sudo crontab -e), altrimenti verrà eseguito due volte.
sudo crontab (sarebbe un'escalation diretta a root per chiunque acceda alla sessione del pannello), ma uno script ristretto con due comandi (list/set) che tocca solo il proprio blocco tra i commenti di servizio. Lo installi una volta sola:
www-data — verifichi con quale utente gira il pool PHP-FPM del sito (ps -o user= -C php-fpm) e lo sostituisca nella riga sudoers.
public/crontab_monitor.php è stato caricato via FTP/SFTP con un utente di sistema diverso (ad esempio root) rispetto agli altri file del sito, il web server non potrà leggerlo. Confronti proprietario e permessi con un file vicino e li allinei:
Il monitor rileva la presenza degli strumenti tramite dpkg-query, il database dei pacchetti APT. Se lo strumento non è stato installato con apt (manualmente, da snap o dai sorgenti), dpkg non lo rileva.
Errore 500 — controlli i log di PHP, nginx e del monitor stesso:
www-data, ma come account dell'utente (ad esempio admin — proprietario della directory del sito). Tutte le regole sudo e le appartenenze ai gruppi (adm, systemd-journal) vanno impostate su questo utente, altrimenti i moduli mostreranno «Inattivo / 0» pur con i servizi in esecuzione. Per individuare l'utente reale di PHP: ps -o user= -C php-fpm | sort -u oppure il proprietario della directory del sito stat -c '%U' /path/to/monitor. Poi, in tutti i comandi qui sotto, lo sostituisca a www-data. L'installazione automatica rileva da sé l'utente web e vi imposta i sudoers.
I dati non vengono visualizzati — quasi sempre sono permessi sudo non impostati. Controlli il comando specifico come utente web (sostituisca www-data con il suo). Il flag -n = senza password, come PHP — se chiede la password, significa che la regola nei sudoers non c'è:
sudo aa-status nel terminale mostra i profili, ma la pagina «AppArmor» mostra «Inattivo»). Motivo: l'utente web non ha il permesso sudo per il comando di quel modulo. Lo verifichi dall'elenco qui sopra: se chiede la password, aggiunga la riga mancante a /etc/sudoers.d/monitor («Configurazione di sudo»). Comandi «nuovi» frequenti: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
apache2ctl, ausearch, aa-status o ss, oppure l'utente web non è nei gruppi adm/systemd-journal (da lì si leggono i log di fail2ban/auth/modsec e journalctl — Falco ed eventi del kernel).
Sintomo: sul server i dati sono presenti (visibili via shell), ma la pagina mostra «nessun dato» o uno stato errato — ad esempio AIDE riporta «Non inizializzata», anche se il database è stato creato.
La causa è open_basedir: molte pannelli e hosting limitano il pool PHP-FPM alla directory del dominio, perciò le funzioni PHP file_exists(), file_get_contents(), filemtime() sui percorsi di sistema (/var/lib/aide, /var/log, /proc…) vengono bloccate. Il monitor lo aggira leggendo tali percorsi con i comandi di sistema nativi (cat, test, stat).
open_basedir. La soluzione corretta è la lettura tramite comandi di sistema (già fatta per AIDE e il Monitor di rete). Estendere open_basedir a /var, /proc non è necessario ed è meno sicuro.
Il monitor verifica i certificati collegandosi ai domini direttamente sulla porta 443. Se il dominio non è raggiungibile dal server stesso o la porta è chiusa dal firewall, il controllo non andrà a buon fine.
/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) e Apache (/etc/apache2/sites-enabled/), oltre all'host corrente da HTTP_HOST.
Il monitor si connette a MySQL con l'utente definito in config.php, che ha accesso solo al proprio database. MySQL mostra in information_schema solo i database su cui l'utente ha privilegi — perciò gli altri non sono visibili.
Affinché il monitor veda tutti i database, conceda a questo utente il permesso di sola lettura (una volta sola come root; sostituisca il nome utente da config.php):
sudo mysql: l'elenco dei database viene ottenuto tramite la sua stessa connessione PDO.
PostgreSQL richiede l'accesso a livello dell'utente postgres, di cui l'utente web del pannello non dispone. Esporre da PHP un ampio sudo psql non è sicuro: il pannello richiama invece un wrapper ristretto senza parametri, che stampa soltanto la versione, il numero di connessioni e l'elenco dei database con le relative dimensioni. Crealo:
monitor-pgstat da sudoers (passo 13 dell'installazione manuale) e non crei lo script: la scheda PostgreSQL resterà semplicemente inattiva.
Il pannello mostra cosa sta accadendo; qui sotto — cosa fare nelle situazioni tipiche. Principio generale: niente panico, verificare con l'attività legittima (le sue azioni, gli aggiornamenti, i backup) e reagire in base alla gravità.
ignoreip./etc, fuori da /usr/share) — potenziale manomissione. Verifichi il pacchetto: debsums PACKAGE_NAME, in caso di dubbio lo reinstalli (apt install --reinstall).127.0.0.1 oppure chiuda la porta in UFW. È una falla reale.certbot renew o le impostazioni nel pannello).sudo apt update && sudo apt upgrade; dopo l'aggiornamento del kernel, riavvii il server.