Dies ist die Anleitung zur Installation, Konfiguration und Wartung von Arcivéo Monitor. Die Abschnitte sind gruppiert: allgemeine Übersicht, Bereitstellung des Dashboards, Anbindung von Sicherheitswerkzeugen, integrierte Module und Diagnose. Befehle lassen sich per Schaltfläche rechts kopieren.
Die Installation des Panels ist auf eigene Schritt-für-Schritt-Seiten ausgelagert. Wählen Sie eine Methode:
Arcivéo Monitor — Sicherheits-Dashboard für Ihren Server. Sammelt Daten der installierten Tools (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco u. a.) und zeigt sie in einer einheitlichen Oberfläche mit Dashboard, Angriffskarte und Detailseiten zu jedem Tool.
Der Monitor ist kein aktives Schutzmittel — er blockiert Angriffe nicht selbst. Seine Aufgabe ist es, Informationen der bereits laufenden Tools zu bündeln und übersichtlich darzustellen.
Der Monitor arbeitet ausschließlich lokal — er muss auf demselben Server installiert sein, den er überwacht. Es gibt kein SSH und keine Remote-API.
Alle Befehle (fail2ban-client, ufw status, ipset list usw.) führt das Dashboard unter dem Benutzer des Webservers aus (in der Regel www-data, bei Hosting-Panels das Website-Konto) mit einem eng begrenzten Satz an sudo-Rechten — nur für bestimmte Werkzeuge, ohne allgemeinen Root-Zugriff. Die Ergebnisse werden geparst und im Browser angezeigt.
Der Wert beginnt beim Maximum und sinkt für jedes erkannte Problem:
PermitRootLogin yes) — −20Ergebnis: 80+ = Geschützt, 60–79 = Achtung, <60 = Gefährdet.
WebAuthn ist ein Standard für die passwortlose Authentifizierung über einen Hardware-Schlüssel. Unterstützt werden YubiKey, Touch ID, Face ID, Windows Hello und Passkey.
Nach der Anmeldung mit Passwort fordert das System eine Bestätigung über den registrierten Schlüssel an. Selbst bei einem Passwortleck ist eine Anmeldung ohne physischen Schlüssel oder Biometrie unmöglich.
Zum Einrichten öffnen Sie WebAuthn-Schlüssel im Seitenmenü und klicken auf „Schlüssel registrieren“. Registrieren Sie gleich zwei Schlüssel: Geht der einzige Schlüssel verloren oder wird er beschädigt, ist die Anmeldung im Dashboard darüber nicht mehr möglich.
Das Dashboard kann den Sicherheitsbericht an Telegram und per E-Mail senden (per Schaltfläche und nach Zeitplan). Einstellbar im Bereich „Einstellungen“.
Telegram. Erforderlich sind Bot-Token und chat id:
@BotFather → /newbot → Sie erhalten ein Token der Form 123456:ABC....@userinfobot oder öffnen Sie https://api.telegram.org/bot<TOKEN>/getUpdates und suchen Sie "chat":{"id":...}.E-Mail. Zwei Möglichkeiten zur Auswahl unter „Einstellungen“ → E-Mail:
re_...) und die bestätigte Absender-Domain an.Berichtsstatus: „ACHTUNG“ oder „OK“. Der Titel wird nur bei einem echten Problem oder einer ausstehenden Aktion zu „ACHTUNG“: ClamAV hat eine Bedrohung gefunden, Dateiänderungen in AIDE, kritische Falco-Ereignisse (Emergency/Alert/Critical in den letzten 24 h), ein ausgefallener Dienst in Monit, ein Neustart ist erforderlich, ein SSL-Zertifikat läuft ab (≤14 Tage) oder Sicherheitsupdates stehen an. Hintergrundrauschen — SSH-Bruteforce durch Bots, von fail2ban gebannte IP-Adressen, Suricata-Alerts, Lynis-Warnungen und bereits abgewehrte ModSecurity-Anfragen — hebt den Status nicht an, daher bedeuten solche Zahlen im Bericht für sich allein noch kein „ACHTUNG“.
Die detaillierten Monitoring-Module (Lynis, UFW, ModSecurity, Angriffskarte, AIDE, ClamAV usw.) werden mit einer gültigen Lizenz freigeschaltet. Ohne sie funktionieren Dashboard, Einstellungen und Konto, während die Module die Karte „Lizenz erforderlich“ anzeigen.
Nach dem Kauf im Benutzerkonto liegt Ihnen ein Aktivierungscode der Form ARCIVEO-XXXX-XXXX-XXXX-XXXX vor. Er muss auf die Domain Ihres Panels „aktiviert“ werden – dadurch wird der Code in eine signierte Lizenzdatei (Block [license]) umgewandelt, die Sie in das Panel einfügen.
So aktivieren Sie (3 Schritte):
my.arciveo.com → Bereich „Lizenzen“ / „Lizenzaktivierung“ – kopieren Sie den Code ARCIVEO-….monitor.example.com). Klicken Sie auf Aktivieren – das System erzeugt eine an diese Domain gebundene Lizenzdatei und zeigt sie im Feld mit der Schaltfläche „Kopieren“ an.Das Panel prüft den Schlüssel kryptografisch: Signatur, Domain-Bindung und Gültigkeitsdauer.
APP_URL in config.php und geben Sie nur den Hostnamen ein – ohne https:// und ohne Präfix www. Die Aktivierung ist einmalig: Der Code wird zur Lizenz für die eingegebene Domain und lässt sich nicht erneut aktivieren – bei einem Fehler in der Domain passt der Schlüssel nicht zu Ihrem Panel, und der Code ist verbraucht. Geben Sie die Domain daher sorgfältig ein.
Alle wesentlichen Parameter des Dashboards stehen in einer einzigen Datei config.php im Stammverzeichnis (neben dem Ordner public/) als gewöhnliche Konstanten via define(). Die Datei wird bei der Installation erstellt; ein manuelles Bearbeiten ist selten nötig — meist beim Wechsel der Domain, beim Umzug oder bei der Anbindung an eine andere Datenbank. Nach jeder Änderung starten Sie PHP-FPM neu (sonst greifen die Änderungen wegen OPcache nicht).
Tragen Sie Ihre Werte an den hervorgehobenen Stellen ein; den Rest lassen Sie unverändert:
Datenbank. Verbindungsdaten zu MySQL/MariaDB:
DB_HOST — Host des DBMS, fast immer localhost;DB_NAME — Name der Datenbank des Dashboards;DB_USER — DB-Benutzer (Zugriff nur auf die eigene Datenbank);DB_PASS — Passwort dieses Benutzers;DB_CHARSET — Zeichensatz der Verbindung, belassen Sie utf8mb4.Anwendung.
APP_URL — vollständige Adresse des Dashboards (z. B. https://monitor.example.com). Muss mit der Domain übereinstimmen, für die die Lizenz aktiviert wurde — sonst wird der Schlüssel abgelehnt (siehe Abschnitt „Lizenz“);TIMEZONE — Zeitzone von PHP: wirkt sich nur darauf aus, wie das Dashboard Datum und Uhrzeit anzeigt. Auf die Startzeit der Cron-Aufträge hat sie keinen Einfluss — dort gilt die Systemzeitzone (siehe „Alle Cron-Aufträge“).Sitzungsdauer. SESSION_LIFETIME — Leerlauf-Timeout der Sitzung in Sekunden (gleitend: wird bei Aktivität erneuert). Standard ist 28800 = 8 Stunden; nach dieser Zeit ohne Aktivität verlangt das Dashboard eine erneute Anmeldung. Beispiel: 3600 = 1 Stunde, 86400 = ein Tag.
Fehlerprotokollierung. Fehler werden Besuchern nie angezeigt, sondern in logs/php_errors.log geschrieben — sie sind auf der Seite „Anwendungsprotokolle“ sichtbar. Diese Zeilen (display_errors=0, log_errors=1, Pfad error_log) müssen in der Regel nicht geändert werden — die Einstellungen stehen direkt in der Datei und hängen nicht von php.ini ab.
public/), und bei diesem Dashboard ist der Web-Stamm (DocumentRoot) genau dieses Stammverzeichnis, nicht public/. Für sich genommen „leckt“ die Datei nicht: In der .htaccess im Stammverzeichnis gilt für sie ein explizites Verbot (Require all denied) — der Server liefert 403. Auch ohne diese Regel würde der Quelltext nicht austreten: Es ist PHP — der Server führt es aus und gibt es nicht als Text zurück. Sicherheitshalber: Legen Sie sie nicht in öffentliche Repositorys und geben Sie sie nicht mit dem echten Passwort an den Support weiter. Dateirechte — 640.
UFW (Uncomplicated Firewall) — eine einfache Schnittstelle zu nftables/iptables. Sie sperrt alle eingehenden Ports außer den ausdrücklich erlaubten. Die Seite „UFW-Firewall“ zeigt Status und Regeln an.
ufw enable unbedingt SSH frei (ufw allow OpenSSH), sonst verlieren Sie den Zugriff auf den Server.
deny-Regel gesperrter Port gilt nicht als von außen erreichbar.
Skipping adding existing rule ist kein Fehler. UFW meldet damit, dass genau diese Regel bereits existiert und nicht erneut hinzugefügt wird. Beim erneuten Ausführen der automatischen Einrichtung (sie ist idempotent) ist das eine normale Meldung — es ist keine Reaktion nötig.
Sperrt IP-Adressen automatisch nach zu vielen fehlgeschlagenen Anmeldeversuchen. Analysiert die Logs von SSH, nginx, Apache und anderen Diensten.
Die Basisinstallation steht oben. Hier folgt eine funktionierende Konfiguration mit Dutzenden aktiver jails und Tausenden Sperren: allgemeine Einstellungen, zentrale jails und Auto-Bann bösartiger IPs aus der Liste ipsum.
Datei /etc/fail2ban/jail.local — allgemeine Einstellungen und wichtigste jails:
ignoreip unbedingt Ihre eigene IP und vertrauenswürdige Netze ein, sonst sperren Sie sich womöglich selbst aus. Nach Änderungen: sudo fail2ban-client reload.
Automatisches Laden der Blockliste ipsum per Root-Cron (sudo crontab -e): Level 1 (100.000+ IPs) wird in das Set ipsum geladen, das auf der Firewall abgeblockt wird (mehr dazu im Abschnitt „IPset-Blockliste“):
ipsum heißen — genau dieses liest das Dashboard (Karte „IPset ipsum“). Level: levels/1.txt — maximale Abdeckung, levels/3.txt — genauer (3+ Quellen).
Warum der „Sicherheitsmonitor“ in zwei Zonen unterteilt ist. Der Schutz arbeitet auf zwei Ebenen, und das Dashboard vermischt sie nicht:
sshd, apache-*, nginx-* usw.) und hartnäckige Wiederholungstäter (jail recidive — jene, die schon mehrfach gesperrt wurden). Das sind IPs, die tatsächlich bei Ihnen einzubrechen versuchten — sie erscheinen auf der Angriffskarte und in der „Zeitleiste“.ipset ipsum, die auf der Firewall per DROP-Regel abgeblockt wird. Diese Adressen haben Ihren Server meist nie berührt — sie werden vorab abgeschnitten; der Zähler „IPset ipsum“ zeigt, wie viele präventiv abgeblockt wurden.Der Unterschied ist einfach: reaktiv — „diese haben angegriffen und wurden gesperrt“, präventiv — „diese wurden schon vor dem Versuch blockiert“. Früher wurde in recidive künstlich list-3 ipsum eingespeist (daher die alte Trennung „gelistete recidive“); jetzt sind in recidive nur echte Wiederholungstäter, und die Prävention läuft vollständig auf der Firewall.
ipsum — eine öffentliche, täglich aktualisierte Liste bösartiger IP-Adressen. Der Monitor zeigt die Anzahl der geladenen Adressen im Dashboard und auf der Angriffskarte und berücksichtigt sie in der Sicherheitsbewertung (−10, wenn das Set nicht geladen ist).
Die Minimalvariante ohne fail2ban — ein eigenes Set ipsum mit Sperrung über iptables:
@reboot. Zugleich setzt der Befehl create … -exist das Limit maxelem 300000 (Standard ist 65536 — Level 1 passt nicht hinein, es kommt „Hash is full“):
ipsum und bindet, falls die Firewall vom Installer verwaltet wird (frisches VPS — Profile „Vollständig“/„Reduziert“), das Set über die UFW-Regel DROP ein — Traffic von diesen IP-Adressen wird tatsächlich blockiert. Die Regel steht nach ESTABLISHED,RELATED, sodass bestehende Verbindungen (auch Ihr SSH) nicht abreißen — es werden nur neue Verbindungen aus der Liste gekappt. Das Set wird beim Start des Dienstes ipsum-load.service vor der Firewall wiederhergestellt (sonst würde UFW nicht hochkommen) und per Cron um 04:00 aktualisiert. Auf einem bereits eingerichteten Server (Panel, eigene Firewall) greift der Installer nicht in die Firewall ein — dort bleibt ipsum eine Liste für Dashboard und Angriffskarte, und die Regel DROP wird bei Bedarf manuell hinzugefügt (die Minimalvariante mit iptables … --match-set ipsum … -j DROP — oben). Bei der Autoinstallation ist manuell nichts zu tun.
Moderner Ersatz für Fail2ban mit kollektiver Threat Intelligence: Sperren aus der Community plus eigene Regeln. Benötigt einen separaten bouncer, um Sperren auf die Firewall anzuwenden.
systemctl is-active crowdsec). Starten: sudo systemctl enable --now crowdsec; bei Absturz siehe sudo journalctl -u crowdsec -n 30. Dieselbe Regel gilt für jeden Dienst im Status „Nicht gestartet“ (Suricata, Falco, Monit, MySQL).
stream halted / Sperren werden nicht angewendet. Das ist ein verwaister API-Schlüssel: Der bouncer wurde aus cscli bouncers list entfernt, aber sein alter Schlüssel blieb in /etc/crowdsec/bouncers/*.yaml. Registrieren Sie den bouncer neu und tragen Sie den frischen Schlüssel ein:
AIDE (Advanced Intrusion Detection Environment) erstellt einen Snapshot des Dateisystems und meldet bei jeder Prüfung Änderungen in /etc, /bin, /usr. Nach der Installation ist die Initialisierung der Datenbank zwingend (aideinit).
aideinit bleibt das Terminal 5–15 Minuten bei der Zeile Running aide --init... stehen — das ist normal (Hashing des gesamten Dateisystems, Festplattenlast). Nicht mit Ctrl+C abbrechen. Wenn der Prozess „hängt“, aber nichts ausgibt — möglicherweise wartet er auf eine Antwort zu einer versteckten Abfrage Overwrite existing aide.db.new [Yn]? (drücken Sie Y). Aktivität aus einer anderen Sitzung prüfen: pgrep -af aide.
aideinit: „21_aide_spamassassin … printf: invalid number“ (return code 20) — ein bekannter Bug des AIDE-Konfig-Snippets in Ubuntu 22.04. Die Datenbank wird nicht erstellt. Verschieben Sie das defekte Snippet und wiederholen Sie:
aideinit nicht ausgeführt, oder (Ubuntu 24.04) das Verzeichnis /var/lib/aide wurde mit Modus 700 angelegt und ist für www-data nicht zugänglich — behoben mit sudo chmod 755 /var/lib/aide (siehe Block oben). „Keine Prüfungen“ = die Datenbank ist vorhanden, aber es wurde noch keine Prüfung ausgeführt — das ist kein Fehler. Die Ergebnisse liest der Monitor aus /var/log/aide/aide.log.
/etc/cron.daily/aide auf neueren Ubuntu/Debian schreibt /var/log/aide/aide.log möglicherweise nicht im benötigten Format (und aide.wrapper gibt es dort nicht mehr). Zuverlässiger ist ein eigener Cron mit explizitem --config — er schreibt das Log als root im Modus 644, und der Monitor liest es ohne zusätzliche Gruppen:
chmod 755 /var/lib/aide und den Prüf-Cron um 02:00 — manuell ist nichts nötig.
sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.
Antivirus-Scanner für Linux. Besonders nützlich, um /var/www auf PHP-Shells und Schadcode zu prüfen.
enable --now „Inaktiv“? Drei typische Ursachen:
1. In der Konfiguration steht noch die Zeile Example — clamd startet nicht, solange sie vorhanden ist:
2. Die Signaturdatenbank ist nicht heruntergeladen — clamd startet ohne sie nicht:
3. Es lädt einfach noch — clamd lädt ~8 Mio. Signaturen 30–60 Sek. in den Speicher. Warten und prüfen: systemctl is-active clamav-daemon (Status activating → lädt noch).
sudo journalctl -u clamav-daemon -n 30 --no-pager.
clamd hält nur die Signaturen im Speicher, er scannt selbst nichts nach Zeitplan. Das Dashboard zeigt Ergebnisse des geplanten Scans, daher ist ein Cronjob nötig, der scannt und ins Log schreibt. Die automatische Installation richtet den Wrapper /usr/local/bin/clamav-scan.sh und einen Cronjob um 01:30 ein — nach dem ersten Lauf werden „Geprüfte Dateien“ und „Letzter Scan“ befüllt. Sofort starten, ohne auf den Zeitplan zu warten: sudo /usr/local/bin/clamav-scan.sh.
Linux Malware Detect (LMD) — Malware-Scanner für Web-Bedrohungen: PHP-Shells, Web-Backdoors, Downloader. Nutzt die ClamAV-Engine und ergänzt sie um eigene Signaturen.
maldet --report.
update-rc.d: error: unable to read /etc/init.d/maldet erscheinen — sie ist harmlos. maldet nutzt kein init.d, Signatur-Updates und Scans laufen über /etc/cron.daily/maldet. Erscheint darunter installation completed, ist alles installiert.
apt installiert, sondern nach /usr/local/maldetect, und bei aktivem open_basedir wird seine Präsenz über die Shell geprüft — siehe Abschnitt „Seite leer, obwohl Daten auf dem Server vorhanden sind“.
Netzwerkbasiertes Angriffserkennungssystem: analysiert den Datenverkehr auf Paketebene und kennt Tausende von Angriffssignaturen. Ergänzt ModSecurity (das auf HTTP-Ebene arbeitet, Suricata auf TCP/IP-Ebene).
/var/log/suricata/eve.json als root mit Modus 750 auf das Verzeichnis, und der Webserver (www-data) kann es nicht lesen. Geben Sie das Verzeichnis für den Durchgang frei – die Dateien darin bleiben geschützt:
Fängt Systemaufrufe über eBPF/Kernel-Modul ab und erkennt Anomalien in Echtzeit: Shell aus nginx, Lesen von /etc/passwd durch einen Webprozess, Schreiben nach /bin usw.
journalctl -u falco (ohne sudo — über die Gruppe systemd-journal). Stellen Sie sicher, dass www-data in dieser Gruppe ist — siehe „sudo einrichten“ (Punkt 2) auf der Seite zur manuellen Installation.
/etc/passwd, Schreiben in Systemverzeichnisse). Null kritische Ereignisse an einem Tag auf einem ruhigen Server sind ein gesunder Zustand.
journalctl erfordert Rechte am Journal; damit das Dashboard Ereignisse zuverlässig sieht, aktiviert die automatische Installation bei Falco file_output → /var/log/falco/falco.log und setzt für den Dienst UMask=0022 (das Log ist für den Webserver lesbar). Bei einer Neuinstallation muss dies nicht manuell eingerichtet werden.
ModSecurity — eine Web-Firewall (WAF) für Apache oder Nginx. Blockiert Angriffe auf Anwendungsebene: SQL-Injektionen, XSS, Path Traversal, Scanner.
IncludeOptional /etc/modsecurity/*.conf ein, das Paket legt aber nur modsecurity.conf-recommended ab — diese fällt nicht unter die Maske *.conf. Wird sie nicht nach modsecurity.conf kopiert, bleibt SecRuleEngine auf Off: Das Modul ist geladen, die CRS-Regeln sind geladen, aber der Verkehr wird nicht geprüft und kein Audit-Log erstellt. Der Zwischenmodus DetectionOnly schreibt Ereignisse nur ins Log, ohne Anfragen zu blockieren — das Dashboard zeigt ihn gelb an.
Zugriff des Dashboards auf das Audit-Log. Das Log /var/log/apache2/modsec_audit.log gehört root (Rechte 640), der Webbenutzer kann es nicht lesen. Das Dashboard bezieht die Daten über einen Wrapper — legen Sie ihn an:
SecRuleEngine ohne Einrückung: eingerückte Zeilen stehen innerhalb von Blöcken <LocationMatch>/<Directory> (z. B. Deaktivierung der WAF für phpMyAdmin) und legen den globalen Modus nicht fest.www-data, in HestiaCP läuft der Site-Pool unter dem Site-Eigentümer (z. B. admin) — prüfen Sie grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.X-Forwarded-For. In die Statistik gelangen nur Transaktionen mit ausgelöster Regel: die Direktive SecAuditLogRelevantStatus schreibt alle 4xx/5xx-Antworten ins Audit-Log, daher landen dort auch gewöhnliche 403/500 — als WAF-Ereignisse zählt das Dashboard sie nicht.---RULES--- wird für den Bereich „Alle aktiven Regeln“ benötigt — das Dashboard zeigt nicht nur die ausgelösten, sondern alle geladenen CRS-Regeln + benutzerdefinierte an. Die drei Pfade in der Schleife for f in … sind die typischen Orte für CRS-Regeln und lokale Ergänzungen; bei einer anderen Aufteilung (das Paket legt Dateien in ein eigenes Verzeichnis, oder benutzerdefinierte Regeln liegen nicht in /etc/modsecurity/custom-rules.conf) ermitteln Sie die tatsächlichen Pfade mit sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null und tragen sie in die Liste ein. Ist der Wrapper alt (ohne diesen Abschnitt) — zeigt der Bereich einfach die Warnung „nicht verfügbar“ an, der Rest der Seite funktioniert wie zuvor.
Auditd (Linux Audit Daemon) protokolliert Systemaufrufe auf Kernel-Ebene: An- und Abmeldungen, sudo-Befehle, fehlgeschlagene Authentifizierungsversuche, Dateiänderungen. Der Monitor zeigt Anmeldungen, fehlgeschlagene Versuche und sudo-Befehle von heute.
ausearch (/usr/sbin/ausearch) und bei Bedarf aus /var/log/audit/audit.log per tail. Beide müssen in sudoers eingetragen sein.
Überwacht Dienste (nginx, php-fpm, mysql usw.) und startet sie bei einem Ausfall neu. Kann Warnmeldungen per E-Mail senden.
monit status. In /etc/monit/monitrc muss die HTTP-Schnittstelle aktiviert sein (Block set httpd mit allow localhost), sonst gibt monit status einen Fehler zurück.
monitrc ist die Zeile set httpd auskommentiert (standardmäßig als # set httpd port 2812 …). Kommentieren Sie den Block ein und erlauben Sie localhost. (2) Ein aktivierter httpd allein überwacht nichts — Monit zählt nur das, was in check-Stanzas beschrieben ist; ohne diese bleibt die Liste selbst bei laufender Schnittstelle leer. Minimale funktionierende Konfiguration:
conf.d mit httpd auf 2812 und einer Reihe von Prüfungen an — bei einer Neuinstallation ist keine manuelle Konfiguration nötig.
PSAD analysiert das iptables-Protokoll und erkennt Portscans sowie Netzwerkangriffe, wobei jeder Quelle eine Bedrohungsstufe (1–5) zugewiesen wird. Ergänzt fail2ban und Suricata.
psad --Status (in sudoers erforderlich). Ohne iptables-Protokollierung bleibt die Seite leer — das ist normal, solange keine Scans stattgefunden haben.
Mandatory Access Control schränkt ein, auf welche Dateien und Ressourcen ein Programm zugreifen darf – selbst wenn es kompromittiert wurde. Unter Ubuntu/Debian kommt standardmäßig AppArmor zum Einsatz (meist bereits installiert und aktiv).
aa-status (in sudoers erforderlich). Er zeigt die Anzahl der Profile im Modus enforce/complain sowie Prozesse ohne Profil.
„Geladene Profile“ sind mehr als enforce + complain – das ist normal. In AppArmor 4.x (Ubuntu 24.04 und neuer) gibt es den Modus unconfined: Das Profil ist in den Kernel geladen, schränkt aber nichts ein. Ubuntu markiert so Dutzende Profile für Programme, die user namespaces nutzen (Browser, Torrent-Clients und Ähnliches). Wenn solche Profile vorhanden sind, wird die Karte „Geladene Profile“ bernsteinfarben und zeigt ihre Anzahl – etwa unconfined: 90 bei 120 geladenen und 26 im enforce-Modus. Tatsächlich schützen nur Profile im enforce-Modus; unter Ubuntu 22.04 (AppArmor 3.x) gibt es diesen Modus nicht und die Zahlen stimmen immer überein.
unconfined belassen hat, sollten nur mit Bedacht in den enforce-Modus versetzt werden: Sie sind nicht aus Versehen deaktiviert, sondern weil sonst die Programme selbst nicht mehr funktionieren. Profile im Modus complain sind etwas anderes: Dort sind die Regeln bereits geschrieben und werden nur nicht angewendet.
debsums prüft, ob die Dateien installierter Pakete mit den Prüfsummen aus dem Repository übereinstimmen — erkennt manipulierte System-Binärdateien (ergänzt AIDE). Eine vollständige Prüfung dauert 1–2 Minuten und läuft daher per cron; das Dashboard liest das Ergebnis aus data/debsums/debsums.log und ordnet es selbst in Kategorien ein (wichtig sind nur Binärdateien und Bibliotheken).
Der Job gehört in den root-cron (sudo crontab -e). Der fertige Wrapper debsums-scan.sh wird in /usr/local/bin/ abgelegt (chmod +x; siehe cron-Übersicht) und schreibt den Bericht selbst nach data/debsums/ im Dashboard.
Der Wrapper debsums-scan.sh findet data/ im Dashboard selbst — der Pfad muss nicht eingetragen werden.
/etc/ (Konfigurationen) und /usr/share/ (Ressourcen) auf dem Server sind meist normal — das Dashboard markiert sie mit einer eigenen Farbe. Bedenklich sind Änderungen an Binärdateien und Bibliotheken (/bin, /sbin, /usr/lib usw.) — die Karte „Binärdateien / Bibliotheken“ zeigt genau diese an.
Lynis wird manuell oder per cron gestartet. Der Bericht muss im Ordner data/lynis/ des Projekts abgelegt werden — der Monitor liest die Datei lynis-report.dat.
lynis-scan.sh im Hintergrund direkt aus dem Panel (ohne auf cron zu warten): zeigt „Wird gescannt…“ an und aktualisiert nach Abschluss den Bericht selbst. Dafür braucht der Web-Benutzer eine sudoers-Zeile zum Ausführen des Skripts — das Installationsprogramm fügt sie automatisch in /etc/sudoers.d/monitor ein. Wurde das Panel manuell/früher installiert, ergänzen Sie sie mit demselben Benutzer, der bereits in der Datei angegeben ist:
Logwatch muss die täglichen Berichte im Format .txt im Ordner data/logwatch/ des Projekts speichern. Der Monitor zeigt den letzten Bericht und das Archiv an.
Der Netzwerk-Monitor erfordert keine Installation — er ist eine integrierte Seite des Dashboards. Sie zeigt den Netzwerkstatus des Servers aus lokalen Quellen:
/proc/net/dev;ip;ss;journalctl -k.Die ersten drei Quellen funktionieren ohne sudo, daher sind Schnittstellen, Traffic, Verbindungen und Ports sofort sichtbar. Der Block „Kernel-Ereignisse“ nutzt journalctl -k — er wird über die Gruppe systemd-journal gelesen („sudo einrichten“, Pkt. 2), sudo ist nicht nötig. So prüfen Sie, dass alles für den Web-Benutzer verfügbar ist:
UFW BLOCK erscheinen hier nicht — sie stehen auf den Seiten „UFW-Firewall“ und „Angriffskarte“. Ein leerer Block mit grünem Haken = in den letzten 24 h gab es keine Netzwerkstörungen.
Die integrierte Seite zeigt drei Dinge:
df); die Skala wird bei ≥90% rot;lsblk), nur reale (loop/snap ausgeblendet);smartctl).Speicherplatz und Geräteliste funktionieren sofort, ohne Konfiguration. Für SMART wird das Paket smartmontools benötigt. Der Web-Prozess hat keinen direkten Zugriff auf die Festplattengeräte, daher wird SMART per cron in die Datei data/disk/smart.txt geschrieben, und das Dashboard liest sie aus.
Der Auftrag gehört in den root-cron (sudo crontab -e). Der fertige Wrapper smart-scan.sh wird nach /usr/local/bin/ abgelegt (chmod +x; siehe die Übersicht der cron-Aufträge) und schreibt selbst in data/disk/ des Dashboards.
Der Wrapper smart-scan.sh findet data/ des Dashboards selbst — der Pfad muss nicht angegeben werden. Intern schließt lsblk -e7,11 loop/cdrom aus.
Die Seite zeigt den Auslastungsverlauf des Servers der letzten 24 Stunden — Load Average, CPU-Auslastung und I/O-Wartezeit, RAM/Swap, Netzwerkverkehr (Empfang/Sendung), Festplatten-I/O (Lesen/Schreiben), Festplatten- und Inode-Belegung, offene Dateideskriptoren und MySQL-Verbindungen sowie die aktuelle Anzahl der TCP-Verbindungen und Prozesse.
Die Daten erfasst cron/collect_metrics.php — alle 5 Minuten wird ein „roher“ Snapshot der Zähler (/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') in die DB-Tabelle system_metrics geschrieben; Prozentwerte und Geschwindigkeiten berechnet die Seite selbst aus der Differenz benachbarter Snapshots (Festplatten-/Inode-/Deskriptor-Belegung und MySQL-Verbindungen sind Momentanwerte, ohne Neuberechnung). Sudo wird nicht benötigt — die Quellen werden ohne Root-Rechte gelesen. Punkte, die älter als 24 Stunden sind, werden bei jeder Schreiboperation automatisch gelöscht.
Der Wrapper collect-metrics-all.sh (siehe Übersicht der Cron-Aufgaben) findet selbst alle auf dem Server installierten Panel-Instanzen und startet cron/collect_metrics.php jeder Instanz im Namen des Website-Eigentümers.
Auslastungsbenachrichtigungen (Bereich „Einstellungen“ → „Auslastungsbenachrichtigungen“) — bei Überschreiten des Schwellenwerts für CPU/RAM/Festplatte/Inodes sendet das Panel eine Benachrichtigung an Telegram/E-Mail (dieselben Kanäle wie der Tagesbericht — sie müssen für die Alerts nicht separat aktiviert werden) und eine weitere, sobald die Metrik wieder normal ist. Während der Schwellenwert gehalten wird, wird nicht erneut gespammt: Die nächste Benachrichtigung kommt erst nach einem Zyklus „wieder normal → erneut überschritten“.
collect_metrics.php bei jedem Lauf (alle 5 Minuten) — ein separater Cron ist nicht nötig. Der Status „bereits benachrichtigt / noch nicht“ wird in data/alerts_state.json gespeichert, die Schwellenwerte in den Panel-Einstellungen.
Die Seite „Angriffskarte“ ermittelt das Land anhand der IP-Adresse mit dem Befehl geoiplookup. Ohne das GeoIP-Paket werden keine Länder erkannt und es erscheinen keine Punkte auf der Karte:
/usr/share/GeoIP/GeoIP.dat ist für alle lesbar, die Ergebnisse werden in tmp/geoip_cache.json zwischengespeichert. Die Karte selbst (Leaflet + OpenStreetMap-Kacheln) wird im Browser geladen – der Rechner, auf dem das Dashboard geöffnet ist, benötigt Internetzugang.
Zwei integrierte Dashboard-Karten, die nicht „ein/aus“ eines Tools zeigen, sondern die tatsächliche Absicherung des Servers. Sie erfordern keine Installation und werden lokal ohne sudo ausgelesen.
Externe Exposition — wie viele Dienste auf allen Schnittstellen lauschen (0.0.0.0/[::]) und von außen erreichbar sind. Wird rot hervorgehoben, wenn eine Datenbank oder ein Cache nach außen offensteht (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — das ist ein direktes Sicherheitsleck (−10 auf die Sicherheitsbewertung). Quelle: ss -tuln.
127.0.0.1 (bind-address in der MySQL-/PostgreSQL-Konfiguration, bind 127.0.0.1 in Redis) oder schließen Sie den Port in UFW.
127.0.0.1 (loopback) lauscht, ist nur für den Server selbst sichtbar — von außen nicht erreichbar, selbst wenn der Port „offen“ ist. Deshalb ist Postfix auf Port 25, gebunden an loopback, sicher: Die Autokonfiguration setzt inet_interfaces = loopback-only (dazu ein neutraler smtpd_banner — behebt den Lynis-Hinweis MAIL-8818 zur Preisgabe der Version). Die Karte „Externe Exposition“ zählt nach außen nur, was auf 0.0.0.0/[::] lauscht; Loopback-Dienste fallen nicht darunter.
/etc/postfix/main.cf smtpd_banner = $myhostname ESMTP (ohne Version und OS) und inet_interfaces = loopback-only, dann sudo systemctl restart postfix.
Sicherheitsupdates — wie viele Sicherheitspatches zur Installation anstehen und ob nach einem Kernel-Update ein Neustart nötig ist (−5 auf die Sicherheitsbewertung, wenn Patches vorliegen). Quelle: /usr/lib/update-notifier/apt-check, Datei /var/run/reboot-required. Die detaillierte Liste finden Sie auf der Seite „Sicherheitsupdates“.
update-notifier-common). Fehlt apt-check — zählt der Monitor die Patches über apt-get -s upgrade.
Automatische Sicherheitsupdates (unattended-upgrades) — auf der Seite „Sicherheitsupdates“ zeigt eine eigene Karte, ob die automatische Installation von Sicherheitspatches aktiviert ist und wann sie zuletzt lief. Sudo ist nicht nötig — der Status wird über apt-config dump ausgelesen.
Ein Backup ist die wichtigste Absicherung: Datenverlust ist schlimmer als jeder Einbruch. Zwei Dinge sind nötig — ein Backup des Servers/der Websites und separat ein Backup der Panel-Datenbank (dort liegen Benutzer, WebAuthn-Schlüssel, Einstellungen, Lizenz).
Variante A — HestiaCP: Reiter Backup beim Benutzer → Schaltfläche zum Erstellen eines Backups (oder zeitgesteuert in den Servereinstellungen). Das Backup umfasst Websites und ihre Datenbanken.
Variante B — manuell (cron): Datenbank-Dump + Archiv des Verzeichnisses data/ des Panels:
Aktualisierung auf eine neue Version. Erstellen Sie zuerst ein Backup. Laden Sie dann die Code-Dateien neu hoch und behalten Sie Ihre Daten:
public/, includes/, assets/, cron/, database/ sowie die Root-.htaccess (Front-Controller — das Routing darf nicht von der alten Version stammen), manifest.json, sw.js;config.php (DB-Daten), data/ (Berichte), logs/, tmp/ (Sitzungen und Cache).SSH_FX_PERMISSION_DENIED — Permission denied. Die Panel-Dateien gehören www-data (so wurden sie bei der Installation gesetzt), während sich der SFTP-Client unter Ihrem eigenen Benutzer verbindet, der keine Schreibrechte hat. Dem www-data das gesamte Panel „damit es läuft“ zu übergeben — genau das führt zu diesem Fehler; unten drei Wege, jeder löst das Problem.
data/ (Berichte), tmp/ (Sitzungen und Cache), logs/; diese bleiben bei www-data. Der Rest ist Code, und der Webserver braucht ihn nur zum Lesen, was die Gruppe www-data mit den Rechten 644 ermöglicht. Als Nebeneffekt: Bei einer PHP-Schwachstelle lassen sich die Panel-Dateien nicht mehr überschreiben. Auf Hosting-Panels (HestiaCP und ähnliche) ist Variante A nicht nötig: Dort gehören die Website-Dateien ohnehin dem Konto, mit dem Sie sich per SFTP anmelden, und der Webserver liest sie über die Gruppe.
chmod auf die Dateien setzt die ACL-Maske zurück, und der Zugriff verschwindet stillschweigend. Wenn nach dem „Aufräumen der Rechte“ das Hochladen erneut an Permission denied scheitert — führen Sie beide setfacl-Befehle noch einmal aus.
2 in Variante C ist setgid: per SFTP hochgeladene Dateien bleiben in der Gruppe www-data, sonst kann das Panel sie nicht überschreiben. Nach Variante C verbinden Sie sich in FileZilla neu — die neue Gruppe wird erst bei einer neuen Anmeldung wirksam. Prüfen: id deploy (die Gruppe www-data muss erscheinen) und ls -ld /path/to/monitor (drwxrwsr-x — das s bedeutet, dass setgid gesetzt ist).
Umzug auf einen anderen Server:
config.php, data/.mysqldump auf dem alten → Import auf dem neuen; passen Sie die DB-Daten in config.php an.adm, cron-Aufgaben.Wenn Sie sich nicht anmelden können, lässt sich alles direkt in der Datenbank auf dem Server beheben. Öffnen Sie die Datenbank (Name aus config.php):
WebAuthn-Schlüssel verloren (zweiter Faktor scheitert) — 2FA deaktivieren, per Passwort anmelden, neuen Schlüssel registrieren:
Passwort vergessen — neuen Hash setzen (auf dem Server erzeugen und einsetzen):
Selbst per IP-Filter ausgesperrt — Einschränkung deaktivieren:
sudo mysql auf dem Server oder phpMyAdmin / Datenbankbereich im Hosting-Panel. Aktivieren Sie nach der Wiederherstellung WebAuthn und den IP-Filter erneut.
Die Aufgabenübersicht liegt im root-Cron des Servers (hinzugefügt über sudo crontab -e). Behalten Sie nur die Zeilen der Tools, die Sie nutzen; passen Sie die Pfade an Ihren Server an.
sudo crontab -l und ob der cron-Dienst aktiv ist.
TIMEZONE aus config.php. Die Konstante TIMEZONE wirkt nur auf PHP (wie das Dashboard Datumsangaben anzeigt), aber der cron-Daemon startet Aufgaben nach der Systemzeit des OS. Stimmt die Serverzeitzone nicht mit Ihrer überein, kommt der „08:00“-Bericht zur falschen Zeit. Beispiel: Der Server steht in einer anderen Zone (Europe/London, UTC+1), Sie aber in Berlin (UTC+2) → der „08:00“-Bericht kommt bei Ihnen um 09:00. Prüfen Sie die Systemzone und passen Sie sie bei Bedarf an Ihre an:
0 8 * * * um 08:00 Ortszeit. Andernfalls müsste man den Cron selbst verschieben, aber bei der Zeitumstellung Winter/Sommer würde die Verschiebung wieder abweichen — daher ist es korrekter, die Systemzone einzustellen.
crontab.txt) liegen im Ordner system/ neben dem Projekt, außerhalb von public_html. Das ist kein Teil der Website — sie müssen nicht ins Web-Root geladen werden; platzieren Sie sie auf dem Server unter den Systempfaden (wie in der crontab oben):
lynis-scan.sh → /usr/local/bin/ (chmod +x) — startet lynis audit system, setzt während des Scans das Flag /tmp/lynis-running und kopiert lynis-report.dat in data/lynis/ des Dashboards;logwatch_daily.sh → /usr/local/bin/ (chmod +x) — erstellt den täglichen Logwatch-Bericht (sshd, fail2ban, sudo, postfix) in data/logwatch/;smart-scan.sh → /usr/local/bin/ (chmod +x) — erfasst den Zustand der Datenträger (smartctl) in data/disk/;debsums-scan.sh → /usr/local/bin/ (chmod +x) — prüft die Paketintegrität (debsums) in data/debsums/;clamav-scan.sh → /usr/local/bin/ (chmod +x) — ClamAV-Virenscan gefährlicher Pfade (web, home, temp); schreibt die Übersicht nach /var/log/clamav/scan.log, von wo sie die ClamAV-Seite liest (Zeile 01:30 in der crontab oben);load-ipsum.sh → /usr/local/bin/ (chmod +x) — aktualisiert das ipset-Set ipsum (Level 1) an Ort und Stelle, ohne die aktiven Firewall-Regeln zu unterbrechen (Zeile 04:00 in der crontab oben);daily-report-all.sh → /usr/local/bin/ (chmod +x) — startet den Bericht cron/daily_report.php des Dashboards (Zeile 08:00 in der crontab oben);daily_report.php — ist bereits im Dashboard enthalten (cron/daily_report.php), wird über daily-report-all.sh gestartet, muss nicht separat installiert werden;collect-metrics-all.sh → /usr/local/bin/ (chmod +x) — startet cron/collect_metrics.php des Dashboards (Seite „Leistung“, Zeile */5 in der crontab oben); collect_metrics.php ist bereits im Dashboard enthalten, muss nicht separat installiert werden;crontab.txt (system/cron/) — Muster-Aufgaben; tragen Sie die benötigten Zeilen über sudo crontab -e ein./usr/local/bin/. Direkt aus FileZilla lässt sich dort nichts schreiben — das Verzeichnis gehört root, und der SFTP-Client erhält SSH_FX_PERMISSION_DENIED. Vorgehen: zuerst die Datei nach /tmp hochladen (dorthin dürfen alle schreiben), dann mit einem Befehl an ihren Platz verschieben:
/tmp im Wurzelverzeichnis des Servers — nicht /var/tmp und nicht tmp/ innerhalb des Dashboards selbst (Letzteres gehört www-data und ist für Ihren Benutzer gesperrt). Im FileZilla-Baum ist /tmp ein Zweig der obersten Ebene, neben var, nicht darin.
/usr/local/bin/, Log — /var/log/arciveo-cron.log) — manuell ist nichts zu tun.
/home/*/web/*/public_html und /var/www/* durchgehen, und legen Berichte in deren data/ ab. Liegt das Dashboard unter einem anderen Pfad — fügen Sie ihn in der Zeile for app in … innerhalb der Skripte hinzu, sonst gelangen die Berichte von Lynis/SMART/debsums/Logwatch nicht ins Dashboard.
logs/cron.log wird zuerst vom root-Cron erstellt — sie gehört dann root, und der Tab „Cron-Journal“ im Dashboard kann sie weder lesen noch leeren. Erstellen Sie die Datei vorab als Web-Benutzer (Eigentümer des Website-Verzeichnisses; bei HestiaCP das Konto, z. B. admin) — dann schreibt der root-Cron nur an, ohne den Eigentümer zu ändern:
stat -c %U /path/to/monitor.
sudo crontab -e), sonst wird sie doppelt ausgeführt.
sudo crontab (das wäre eine direkte Eskalation zu root für jeden, der Zugriff auf die Dashboard-Sitzung erhält), sondern ein enges Skript mit zwei Befehlen (list/set), das nur seinen eigenen Block zwischen den Dienstkommentaren berührt. Einmalig installieren:
www-data unterscheiden — prüfen Sie, unter wem der PHP-FPM-Pool der Website läuft (ps -o user= -C php-fpm), und setzen Sie ihn in der sudoers-Zeile ein.
public/crontab_monitor.php per FTP/SFTP unter einem anderen Systembenutzer (z. B. root) als die übrigen Website-Dateien hochgeladen wurde, kann der Webserver sie nicht lesen. Gleichen Sie Eigentümer und Rechte mit einer benachbarten Datei ab und passen Sie sie an:
Der Monitor erkennt vorhandene Werkzeuge über dpkg-query — die APT-Paketdatenbank. Wenn ein Werkzeug nicht über apt installiert wurde (manuell, per snap oder aus dem Quellcode), sieht dpkg es nicht.
Fehler 500 — prüfen Sie die Logs von PHP, Nginx und des Monitors selbst:
www-data, sondern unter dem Benutzerkonto (z. B. admin — Eigentümer des Website-Verzeichnisses). Alle sudo-Regeln und Gruppenmitgliedschaften (adm, systemd-journal) müssen für diesen Benutzer eingetragen werden, sonst zeigen die Module „Nicht aktiv / 0“ bei laufenden Diensten. Den realen PHP-Benutzer ermitteln: ps -o user= -C php-fpm | sort -u oder den Eigentümer des Website-Verzeichnisses stat -c '%U' /path/to/monitor. Ersetzen Sie in allen folgenden Befehlen www-data durch diesen. Die automatische Installation erkennt den Web-Benutzer selbst und trägt sudoers darauf ein.
Daten werden nicht angezeigt — fast immer fehlen sudo-Rechte. Prüfen Sie den konkreten Befehl als Web-Benutzer (ersetzen Sie www-data durch Ihren). Der Schalter -n = ohne Passwort, wie bei PHP — wenn ein Passwort verlangt wird, fehlt die Regel in sudoers:
sudo aa-status im Terminal zeigt Profile, aber die Seite „AppArmor“ zeigt „Inaktiv“). Ursache: Der Web-Benutzer hat kein sudo-Recht für den Befehl dieses Moduls. Prüfen Sie ihn aus der Liste oben: Wird ein Passwort verlangt — fügen Sie die fehlende Zeile in /etc/sudoers.d/monitor hinzu („sudo-Einrichtung“). Häufige „neue“ Befehle: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
apache2ctl, ausearch, aa-status oder ss nicht erlaubt, oder der Web-Benutzer ist nicht in den Gruppen adm/systemd-journal (von dort werden die Logs von fail2ban/auth/modsec und journalctl gelesen — Falco und Kernel-Ereignisse).
Symptom: Auf dem Server sind Daten vorhanden (per Shell sichtbar), doch die Seite zeigt „keine Daten“ oder einen falschen Status – zum Beispiel meldet AIDE „Nicht initialisiert“, obwohl die Datenbank erstellt wurde.
Ursache ist open_basedir: Viele Panels und Hoster beschränken den PHP-FPM-Pool auf das Domain-Verzeichnis, daher werden die PHP-Funktionen file_exists(), file_get_contents(), filemtime() auf Systempfaden (/var/lib/aide, /var/log, /proc…) blockiert. Der Monitor umgeht dies, indem er solche Pfade mit regulären Systembefehlen (cat, test, stat) liest.
open_basedir. Die richtige Lösung ist das Lesen über Systembefehle (für AIDE und den Netzwerk-Monitor bereits umgesetzt). open_basedir auf /var, /proc auszuweiten ist unnötig und weniger sicher.
Der Monitor prüft Zertifikate, indem er sich direkt über Port 443 mit den Domains verbindet. Ist eine Domain vom Server selbst nicht erreichbar oder der Port durch die Firewall gesperrt, schlägt die Prüfung fehl.
/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) und Apache (/etc/apache2/sites-enabled/) sowie dem aktuellen Host aus HTTP_HOST.
Der Monitor verbindet sich mit MySQL unter einem Benutzer aus config.php, der nur Zugriff auf seine eigene Datenbank hat. MySQL zeigt in information_schema nur Datenbanken mit entsprechenden Rechten – die übrigen bleiben daher unsichtbar.
Damit der Monitor alle Datenbanken sieht, erteilen Sie diesem Benutzer nur Leserechte (einmalig als root; setzen Sie den Benutzernamen aus config.php ein):
sudo mysql: Die Datenbankliste wird über die eigene PDO-Verbindung abgerufen.
PostgreSQL erfordert Zugriff auf der Ebene des Benutzers postgres, den der Web-Benutzer des Dashboards nicht hat. Ein weit gefasstes sudo psql aus PHP zu öffnen, ist unsicher — stattdessen ruft das Dashboard einen eng begrenzten Wrapper ohne Parameter auf, der nur die Version, die Anzahl der Verbindungen und die Liste der Datenbanken mit Größen ausgibt. Erstellen Sie ihn:
monitor-pgstat aus sudoers (Schritt 13 der manuellen Installation) und erstellen Sie das Skript nicht: Die PostgreSQL-Karte bleibt einfach inaktiv.
Das Dashboard zeigt, was passiert; unten steht, was zu tun ist in typischen Situationen. Grundprinzip: nicht in Panik geraten, mit legitimer Aktivität abgleichen (Ihre Aktionen, Updates, Backups) und je nach Schweregrad reagieren.
ignoreip steht./etc, außerhalb von /usr/share) — potenziell manipuliert. Prüfen Sie das Paket: debsums PACKAGE_NAME, installieren Sie es im Zweifel neu (apt install --reinstall).127.0.0.1 oder schließen Sie den Port in UFW. Das ist ein echtes Loch.certbot renew oder die Einstellungen im Panel).sudo apt update && sudo apt upgrade; nach einem Kernel-Update den Server neu starten.