Questa è la guida all'installazione, alla configurazione e alla manutenzione di Arcivéo Security 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 Security 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.
Due ritmi di lavoro. Le pagine del pannello interrogano gli strumenti nel momento in cui vengono aperte: vede sempre lo stato attuale. Accanto a questo, alcune attività di fondo girano secondo una pianificazione (cron):
L’elenco completo delle attività si trova nella sezione «Tutti i cron job in un unico posto».
Il punteggio parte dal massimo e diminuisce per ogni problema rilevato:
PermitRootLogin yes) — −20PasswordAuthentication yes) — −10X11Forwarding attivo, MaxAuthTries superiore a 3 o sshd_config leggibile da tutti gli account — −5TRACE è attivo oppure manca l’intestazione Strict-Transport-Security o X-Frame-Options — −5Risultato: 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.
I canali sono quattro: Telegram, Email, webhook e push nel browser. Sono indipendenti: ne attivi quanti vuole, anche tutti e quattro. Sugli stessi canali viaggiano il rapporto di sicurezza quotidiano, gli avvisi di carico e i rilevamenti del sensore degli eventi; si configurano una volta sola qui, in «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.Webhook. Un unico indirizzo che accetta una POST copre Slack, Discord, Mattermost, n8n e un gestore proprio. «Impostazioni» → Webhook: incolli l’indirizzo e attivi l’interruttore.
{"text": …}, a Discord {"content": …} (Discord rifiuta i messaggi più lunghi di 2000 caratteri, quindi il testo viene troncato);text, event, severity, source, count, host, ts — non serve analizzare di nuovo il testo del messaggio.Notifiche push. Il messaggio arriva direttamente nel browser e, se il pannello è aggiunto alla schermata iniziale del telefono, come una normale notifica di applicazione: senza bot e senza server di posta in mezzo. «Impostazioni» → Notifiche push: attivi l’interruttore e prema «Collegare questo dispositivo» su ogni dispositivo che deve ricevere le notifiche. Il contatore «Dispositivi collegati» indica quanti sono.
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.
Il pannello è protetto dall’accesso con password e, se attivato, dal filtro IP. A un programma non serve né l’uno né l’altro, perciò i sistemi esterni hanno un ingresso proprio: due indirizzi in sola lettura protetti da un token. Il token non cambia nulla sul server: permette soltanto di ottenere degli indicatori.
Attivazione — «Impostazioni» → «API in sola lettura»: l’interruttore «Attivare l’API»; il token viene creato automaticamente al primo salvataggio. Il pulsante «Nuovo token» ne rilascia un altro e nello stesso istante esclude tutti quelli che usavano il precedente.
/api/status.php — JSON: punteggio di sicurezza, stato dei moduli, l’ultima misurazione del carico con i processi principali e gli eventi di sicurezza delle ultime 24 ore;/api/metrics.php — gli stessi numeri nel formato testuale di Prometheus (metriche arciveo_*: arciveo_security_score, arciveo_fail2ban_banned, arciveo_cpu_busy_pct e così via).Se il suo client non sa impostare un’intestazione, il token è accettato anche come parametro: ?token=…. Tenga presente che in questa forma finisce nel registro degli accessi del server web, perciò l’intestazione è preferibile.
Prometheus. Un blocco pronto per scrape_configs:
api disabled — l’API è disattivata nelle impostazioni. Le richieste respinte vengono scritte nel log dell’applicazione insieme all’IP del mittente, quindi un tentativo di indovinare il token è visibile nella pagina «Log dell’applicazione».
Il pannello si installa su ogni server separatamente e risponde bene alla domanda «come sta questa macchina». Alla domanda «come stanno tutte le mie macchine» non risponde: per questo ogni pannello può inviare un breve riepilogo all’area personale, dove i server compaiono in un unico elenco.
Che cosa prendere nell’area personale my.arciveo.com → sezione «I miei server»: lì viene rilasciato un token (nella forma fk_…) ed è indicato l’indirizzo del destinatario https://my.arciveo.com/api/fleet.php. Il token è uno per account: lo stesso per tutti i suoi server.
Che cosa impostare nel pannello — «Impostazioni» → «Riepilogo dei server»: indirizzo del destinatario, token, nome del server (come sarà indicato nell’elenco; se lo lascia vuoto viene preso il dominio del pannello) e l’interruttore «Inviare il riepilogo». Il pulsante «Invia ora» verifica subito il collegamento, senza aspettare la pianificazione.
Poi il riepilogo parte con cron, ogni 15 minuti:
Che cosa viene inviato esattamente: nome e dominio del server, sistema operativo, tempo di attività, versione di PHP; il punteggio di sicurezza; lo stato dei moduli (UFW, numero di jail di Fail2ban, ban di oggi, se CrowdSec, Suricata e Falco sono in esecuzione, minacce ClamAV, modifiche AIDE, indice Lynis, aggiornamenti in attesa, se serve un riavvio, giorni alla scadenza del certificato, numero di porte aperte pericolose); l’ultima misurazione del carico (load, CPU, RAM, disco, inode); i contatori degli eventi delle ultime 24 ore e l’ultimo evento critico. Nel riepilogo non ci sono registri, password né contenuti di file.
sudo crontab -l) e che cosa risponde il pulsante «Invia ora». Gli errori di invio vengono scritti nel log dell’applicazione con la sigla FLEET: lì si vede se il token è stato respinto (HTTP 401) o se il collegamento non è proprio andato a buon fine.
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. La finestra di 24 ore è quella predefinita: i pulsanti in alto la portano a 7 giorni o 30 giorni.
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.
Due profondità di conservazione. Le istantanee «grezze» da cinque minuti vivono un giorno (più un’ora di margine, perché il punto più vecchio del grafico abbia ancora un predecessore su cui basare il calcolo). Ogni ora conclusa viene ripiegata in una sola riga; questa serie oraria si conserva 30 giorni ed è proprio quella che leggono le viste «7 giorni» e «30 giorni». Un mese di storico costa così circa 720 righe invece di circa 8600.
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.
Processi principali. Sotto i grafici ci sono due tabelle con i cinque processi più esigenti in CPU:
Entrambe le tabelle descrivono sempre le ultime 24 ore, anche quando i grafici mostrano un mese: l’istantanea dei processi ce l’hanno solo le righe da cinque minuti, che non si conservano più di un giorno.
ps, lo script PHP di raccolta e la catena cron/sudo sopra di esso) vengono esclusi dall’elenco, altrimenti occuperebbero le prime righe di ogni istantanea: ps, nell’istante in cui parte, mostra quasi il 100 % di CPU. Gli altri cron job avviati nello stesso minuto invece compaiono, ed è proprio a questo che serve la tabella.
Avvisi di carico (sezione «Impostazioni» → «Avvisi di carico») — al superamento della soglia di CPU/RAM/disco/inode il pannello invia una notifica su tutti i canali attivati (Telegram, Email, webhook, push — gli stessi del rapporto quotidiano; per gli avvisi non serve attivare nulla a parte) e un’altra quando la metrica torna nella norma. Finché la soglia resta superata non ripete l’avviso: la notifica successiva arriva solo dopo un ciclo «rientrata nella norma → superata di nuovo».
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.
Il rapporto quotidiano risponde alla domanda «come sta il server». Il sensore ne risponde un’altra: «che cosa è appena successo». Ogni 5 minuti interroga le fonti veloci e registra soltanto ciò che è cambiato dal controllo precedente; la pagina «Eventi di sicurezza» nel menu mostra l’elenco dei rilevamenti.
I controlli lenti — Lynis, debsums, aggiornamenti dei pacchetti, scadenza del certificato SSL — il sensore non li tocca: i loro numeri cambiano comunque una volta al giorno e restano di competenza del rapporto quotidiano.
Che cosa nota: nove fonti.
[Priority: 1] porta il rilevamento a livello critico;FOUND nel registro della scansione;root (critico) e un accesso da un indirizzo mai visto prima (avviso);Uno strumento non installato, o il cui registro il pannello non riesce a leggere, semplicemente tace: non è né un errore né un evento.
data/secwatch_state.json) e la prima passata scrive soltanto quel segno. Altrimenti, all’attivazione del monitoraggio arriverebbe una notifica su tutto ciò che i registri hanno accumulato in mesi.
Configurazione — «Impostazioni» → «Monitoraggio degli eventi»:
23-7 durante la quale gli avvisi non vengono inviati.Le notifiche viaggiano sugli stessi canali del rapporto quotidiano (Telegram, Email, webhook, push): non serve attivare nulla a parte. Tutti i rilevamenti vengono scritti nell’elenco indipendentemente dal fatto che una notifica sia partita o no, e vi restano 90 giorni.
L’elenco eventi. Filtri: periodo (24 ore, 7, 30 o 90 giorni), importanza e fonte; vengono mostrate le ultime 500 voci. Il pulsante «Controlla ora» avvia esattamente la stessa passata di cron — comodo subito dopo la configurazione, per non aspettare cinque minuti; indica anche il motivo quando nessuna notifica è partita («sotto la soglia di importanza», «ore di silenzio», «nessun canale di notifica configurato»). Il contatore rosso accanto alla voce di menu è il numero di eventi critici delle ultime 24 ore.
La scheda dell'indirizzo. Un clic su una riga dell'elenco eventi o del blocco Indirizzi correlati apre tutto ciò che si sa di un indirizzo: la cronologia dei suoi eventi, il paese e, già nella prima riga, una conclusione. La riga dell'elenco apre la scheda quando l'evento riguarda esattamente un indirizzo; se ne cita più d'uno, i collegamenti sono gli indirizzi all'interno della riga. Le conclusioni sono quattro:
Sotto la cronologia c'è il blocco Che cosa succedeva sul server nello stesso momento: eventi che non hanno alcun indirizzo. AIDE non sa chi ha modificato il file, ClamAV non sa chi ha portato quello infetto. Sono mostrati quelli che ricadono nell'attività dell'indirizzo e nelle sei ore successive. È proprio l'accesso insieme a ciò che è seguito a distinguere un tentativo da un accesso reale.
Pianificazione. L’attività va nel crontab di root (sudo crontab -e), sfalsata di 2 minuti rispetto alla raccolta delle metriche, perché le due non partano insieme:
php cron/security_watch.php. Il wrapper trova tutte le installazioni del pannello sul server e avvia il controllo per conto del proprietario del sito, con gli stessi diritti sudo che il pannello usa dal web. Una chiamata diretta dal crontab di root creerebbe il file di stato data/secwatch_state.json di proprietà di root e il pulsante «Controlla ora» smetterebbe di funzionare.
La pagina «Server web» analizza il registro degli accessi e mostra quante richieste ci sono state, quale parte si è conclusa con un errore e chi le ha fatte. ModSecurity risponde alla domanda «che cosa è stato bloccato», questa pagina alla domanda «che cosa è arrivato al sito».
Che cosa si vede: numero di richieste, RPS, percentuale di errori, un contatore separato per i 5xx e il volume servito; un grafico delle richieste per ora; la ripartizione dei codici 2xx/3xx/4xx/5xx; indirizzi frequenti, IP frequenti, errori frequenti (codice più percorso) e client (User-Agent). Periodo: 24 ore o 7 giorni.
La fonte è il registro degli accessi in formato combined, quindi vanno bene sia Nginx sia Apache e non serve alcun modulo aggiuntivo. Il pannello cerca il registro tra i file standard:
/var/log/nginx/access.log/var/log/apache2/access.log/var/log/apache2/other_vhosts_access.log/var/log/httpd/access_logOltre a questi, il pannello controlla i file *access*.log e *requests*.log in /var/log/nginx/, /var/log/apache2/ e /var/log/httpd/. Così trova anche il registro che un sito scrive in un file proprio con la direttiva CustomLog, ad esempio arciveo-monitor_requests.log, creato dall’installer di Arcivéo.
Viene letto un solo registro: se Nginx sta davanti ad Apache, sommare due registri conterebbe ogni richiesta due volte. Viene preso il primo registro dell’elenco qui sopra in cui si è scritto nelle ultime 24 ore (quelli trovati tramite schema del nome vengono provati dopo, dal più recente); se in nessuno si è scritto da un giorno, viene preso il più recente non vuoto. Così un registro svuotato da logrotate o lasciato da un server web fermo non nasconde più quello attivo. Viene letto l’ultimo frammento del registro (3 MB) e il risultato è messo in cache per 5 minuti: su un sito molto visitato il periodo scelto può quindi non essere coperto per intero; la copertura effettivamente raggiunta è indicata sopra il grafico.
adm e l’utente web non ne fa parte. L’installer di Arcivéo lo aggiunge a questo gruppo; dopo un’installazione manuale, risolve un piccolo wrapper di root a cui è permessa una cosa sola, mostrare il registro (la pagina di ModSecurity funziona allo stesso modo). Il wrapper sceglie il registro con le stesse regole del pannello. Il comando è riportato sulla pagina stessa; eccolo anche qui. Lo incolli per intero: è un unico comando:
L’utente web può essere diverso da www-data: verifichi con quale utente gira il pool PHP-FPM del sito (ps -o user= -C php-fpm) e lo inserisca nella riga di sudoers. Se il nome del registro non contiene né access né requests, aggiunga il suo percorso all’inizio della riga L=… all’interno del wrapper.
Tentativi di exploit noti. Il pannello confronta le richieste del log con le firme di una ventina di exploit diffusi: PHP-CGI, attraversamento di directory in Apache, PHPUnit, Log4Shell, vulnerabilità di router, telecamere e gateway VPN. Per ogni tentativo indica se può funzionare su questo server basandosi su fatti: le versioni installate di Apache e PHP, la presenza di Java, il codice con cui il server ha risposto alla richiesta del file. In rosso è segnato solo ciò che può davvero funzionare.
Protezione del server web. Il pannello richiede ogni sito del server tramite 127.0.0.1 e verifica ciò che riceve un visitatore: se le versioni del server web e di PHP sono visibili, se il metodo TRACE è attivo e se sono presenti le intestazioni di protezione Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy e Content-Security-Policy. I siti vengono presi dall’indirizzo con cui è aperto il pannello e dai file degli host virtuali, se il pannello può leggerli. Il risultato si aggiorna ogni 10 minuti.
Se manca qualcosa, sotto la tabella compare un solo comando. Crea un file separato, zz-arciveo-hardening.conf, e ricarica il server web solo dopo un test di configurazione riuscito; le intestazioni già inviate dal sito non vengono duplicate. La CSP non viene proposta in una riga: la policy va costruita per il singolo sito, altrimenti smette di caricare i propri script, stili e font. Per annullare la modifica su Apache:
ServerSignature) non viene segnalata se la versione del server web è già nascosta: senza versione mostra solo il nome del server e il nome host.
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.Il pannello è già in funzione e sullo stesso server serve un altro sito, con un proprio dominio accanto al monitor. Dopo la configurazione automatica il server è un normale Apache + PHP-FPM, quindi al sito servono tre cose: la propria cartella, il proprio vhost e il proprio certificato. Il pannello non va toccato: sorveglia l'intero server, una seconda istanza per il secondo dominio non serve.
site2.example.com è l'indirizzo del nuovo sito. Può essere sia un dominio a sé (mycompany.com) sia un sottodominio (shop.mycompany.com): per Apache non cambia nulla, differiscono solo il record DNS (passo 1) e l'emissione del certificato (passo 5). site2 è soltanto un nome breve del sito: così si chiamano la cartella /var/www/site2 e il file di configurazione site2.conf. Con il dominio non ha alcun legame, Apache prende l'indirizzo solo da ServerName; il nome può essere qualsiasi — per shop.mycompany.com, ad esempio, conviene shop: cartella /var/www/shop, configurazione shop.conf.
1. DNS. Nel pannello DNS del suo registrar crei un record A verso l'IP di questo server:
Dopo qualche minuto verifichi: dig +short site2.example.com deve restituire l'IP del server.
2. Cartella del sito.
3. Il vhost. Il blocco va incollato nel terminale per intero: il percorso del socket PHP-FPM viene rilevato da solo:
4. Attivi il sito e verifichi la configurazione prima di ricaricare:
5. SSL. certbot è già installato dalla configurazione automatica; a questo punto il DNS deve puntare al server:
Il terzo dominio e i successivi si aggiungono allo stesso modo: ripeta i passi 1–5 cambiando dominio e cartella.
Host non corrisponde a nessun ServerName (accesso tramite IP oppure un dominio altrui puntato sul suo server), Apache serve il primo sito attivo in ordine alfabetico da /etc/apache2/sites-enabled/. La configurazione automatica disattiva il 000-default standard, quindi quel ruolo «di turno» resta al vhost del pannello (arciveo-monitor.conf) e non influisce sui siti raggiunti con il proprio nome. Se vuole che tramite IP si apra un altro sito, dia al suo file un nome che venga prima in ordine alfabetico (per esempio 000-site2.conf).
site2_error.log e site2_access.log in /var/log/apache2/.
.htaccess (front controller) e un sito annidato restituirebbe qualcosa di diverso da quanto si aspetta. Tenga i siti affiancati: /var/www/monitor, /var/www/site2.
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;security-watch-all.sh → /usr/local/bin/ (chmod +x) — avvia cron/security_watch.php del pannello per conto del proprietario del sito (pagina «Eventi di sicurezza», riga 2-57/5 nel crontab sopra); security_watch.php fa già parte del pannello e non va installato a parte;fleet-push-all.sh → /usr/local/bin/ (chmod +x) — invia il riepilogo del server all’area personale tramite cron/fleet_push.php del pannello (riga 3,18,33,48 sopra);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.