To jest przewodnik po instalacji, konfiguracji i obsłudze Arcivéo Monitor. Sekcje pogrupowano: ogólny przegląd, wdrożenie panelu, podłączenie narzędzi bezpieczeństwa, wbudowane moduły i diagnostyka. Polecenia można kopiować przyciskiem po prawej.
Instalacja panelu opisana jest na osobnych stronach krok po kroku. Wybierz metodę:
Arcivéo Monitor — panel bezpieczeństwa serwera. Zbiera dane z zainstalowanych narzędzi (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco i in.) i wyświetla je w jednym interfejsie z pulpitem, mapą ataków oraz szczegółowymi stronami dla każdego narzędzia.
Monitor nie jest aktywnym środkiem ochrony — sam nie blokuje ataków. Jego zadaniem jest agregowanie informacji z już działających narzędzi i przedstawianie ich w wygodnej formie.
Monitor działa tylko lokalnie — musi być zainstalowany na tym samym serwerze, który monitoruje. Nie ma żadnego SSH ani zdalnego API.
Wszystkie polecenia (fail2ban-client, ufw status, ipset list itd.) panel wykonuje w imieniu użytkownika serwera WWW (zwykle www-data, na panelach hostingowych — konto witryny) z wąskim zestawem uprawnień sudo — tylko do konkretnych narzędzi, bez ogólnego dostępu root. Wyniki są parsowane i wyświetlane w przeglądarce.
Ocena zaczyna się od maksimum i spada za każdy wykryty problem:
PermitRootLogin yes) — −20Wynik: 80+ = Zabezpieczony, 60–79 = Uwaga, <60 = Zagrożony.
WebAuthn to standard uwierzytelniania bez hasła za pomocą sprzętowego klucza. Obsługuje YubiKey, Touch ID, Face ID, Windows Hello, Passkey.
Po zalogowaniu hasłem system prosi o potwierdzenie zarejestrowanym kluczem. Nawet jeśli hasło wycieknie — bez fizycznego klucza lub biometrii logowanie jest niemożliwe.
Aby to skonfigurować, otwórz Klucze WebAuthn w menu bocznym i kliknij „Zarejestruj klucz”. Proszę od razu zarejestrować dwa klucze: jeśli jedyny klucz zostanie zgubiony lub uszkodzony, logowanie nim do panelu będzie niemożliwe.
Panel potrafi wysyłać raport bezpieczeństwa do Telegrama i na e-mail (przyciskiem lub według harmonogramu). Konfiguruje się to w sekcji „Ustawienia”.
Telegram. Potrzebne są token bota oraz chat id:
@BotFather → /newbot → otrzymasz token w postaci 123456:ABC....@userinfobot lub otwórz https://api.telegram.org/bot<TOKEN>/getUpdates i znajdź "chat":{"id":...}.Email. Dwa sposoby do wyboru w „Ustawienia” → Email:
re_...) oraz zweryfikowaną domenę nadawcy.Status raportu: „UWAGA” lub „OK”. Nagłówek staje się „UWAGA” tylko przy realnym problemie lub oczekującym działaniu: wykryto zagrożenie ClamAV, zmiany plików w AIDE, krytyczne zdarzenia Falco (Emergency/Alert/Critical z ostatnich 24 h), padłą usługę w Monit, wymagany restart, wygasający SSL (≤14 dni) lub oczekujące aktualizacje zabezpieczeń. Szum tła — próby zgadywania SSH przez boty, adresy IP zbanowane przez fail2ban, alerty Suricata, ostrzeżenia Lynis i już odparte żądania ModSecurity — nie podnosi statusu, dlatego takie liczby w raporcie same w sobie nie oznaczają „UWAGA”.
Szczegółowe moduły monitorowania (Lynis, UFW, ModSecurity, mapa ataków, AIDE, ClamAV i inne) odblokowują się po posiadaniu ważnej licencji. Bez niej dashboard, ustawienia i konto działają, a moduły pokazują kartę „Wymagana licencja”.
Po zakupie w panelu klienta ma Pan/Pani kod aktywacyjny w postaci ARCIVEO-XXXX-XXXX-XXXX-XXXX. Trzeba go „aktywować” na domenę swojego panelu — zmieni to kod w podpisany plik licencyjny (blok [license]), który wkleja Pan/Pani do panelu.
Jak aktywować (3 kroki):
my.arciveo.com → sekcja „Licencje” / „Aktywacja licencji” — skopiuj kod ARCIVEO-….monitor.example.com). Naciśnij aktywuj — system wygeneruje plik licencyjny powiązany z tą domeną i pokaże go w polu z przyciskiem „Kopiuj”.Panel weryfikuje klucz kryptograficznie: podpis, powiązanie z domeną i termin ważności.
APP_URL w config.php i wprowadź tylko nazwę hosta — bez https:// i bez prefiksu www. Aktywacja jest jednorazowa: kod zmienia się w licencję dla wprowadzonej domeny i nie da się go aktywować ponownie — przy błędzie w domenie klucz nie będzie pasował do Pańskiego panelu, a kod zostanie zużyty. Dlatego proszę wprowadzać domenę uważnie.
Wszystkie podstawowe parametry panelu są zdefiniowane w jednym pliku config.php w katalogu głównym (obok folderu public/) za pomocą zwykłych stałych define(). Plik jest tworzony podczas instalacji; ręczna edycja jest rzadko potrzebna — głównie przy zmianie domeny, przenoszeniu lub podłączaniu do innej bazy. Po każdej zmianie uruchom ponownie PHP-FPM (w przeciwnym razie zmiany nie zostaną zastosowane z powodu OPcache).
Wstaw własne wartości w podświetlonych miejscach; resztę pozostaw bez zmian:
Baza danych. Dane połączenia z MySQL/MariaDB:
DB_HOST — host bazy danych, prawie zawsze localhost;DB_NAME — nazwa bazy danych panelu;DB_USER — użytkownik bazy (dostęp tylko do własnej bazy);DB_PASS — hasło tego użytkownika;DB_CHARSET — kodowanie połączenia, pozostaw utf8mb4.Aplikacja.
APP_URL — pełny adres panelu (np. https://monitor.example.com). Musi być zgodny z domeną, na którą aktywowano licencję — w przeciwnym razie klucz zostanie odrzucony (zob. sekcję „Licencja”);TIMEZONE — strefa czasowa PHP: wpływa tylko na to, jak panel wyświetla daty i godziny. Na czas uruchamiania zadań cron nie wpływa — tam obowiązuje strefa systemu (zob. „Wszystkie zadania cron”).Czas sesji. SESSION_LIFETIME — limit bezczynności sesji w sekundach (przesuwny: odnawia się przy aktywności). Domyślnie 28800 = 8 godzin; po tym czasie bezczynności panel poprosi o ponowne zalogowanie. Na przykład 3600 = 1 godzina, 86400 = doba.
Rejestrowanie błędów. Błędy nigdy nie są pokazywane odwiedzającym, lecz zapisywane w logs/php_errors.log — widać je na stronie „Logi aplikacji”. Tych wierszy (display_errors=0, log_errors=1, ścieżka error_log) zwykle nie trzeba zmieniać — ustawienia są zdefiniowane bezpośrednio w pliku i nie zależą od php.ini.
public/), a w tym panelu katalog główny serwera (DocumentRoot) to właśnie katalog główny panelu, a nie public/. Sam plik nie „wycieka”: w głównym .htaccess ma dla niego ustawiony jawny zakaz (Require all denied) — serwer zwraca 403. Nawet bez tej reguły kod źródłowy by nie wyciekł: to PHP — serwer go wykonuje, a nie wysyła jako tekst. Na wszelki wypadek: nie publikuj go w publicznych repozytoriach i nie przekazuj do pomocy technicznej z prawdziwym hasłem. Uprawnienia pliku — 640.
UFW (Uncomplicated Firewall) to prosty interfejs do nftables/iptables. Blokuje wszystkie porty przychodzące poza jawnie dozwolonymi. Strona „Zapora UFW” pokazuje status i reguły.
ufw enable koniecznie zezwól na SSH (ufw allow OpenSSH), w przeciwnym razie utracisz Pan dostęp do serwera.
deny nie jest uznawany za dostępny z zewnątrz.
Skipping adding existing rule — to nie błąd. W ten sposób UFW informuje, że dokładnie taka reguła już istnieje i nie dodaje jej ponownie. Przy ponownym uruchomieniu autokonfiguracji (jest idempotentna) to standardowy komunikat — nie trzeba reagować.
Automatycznie blokuje adres IP po przekroczeniu liczby nieudanych prób logowania. Analizuje logi SSH, nginx, Apache i innych usług.
Instalacja podstawowa — powyżej. Tutaj — działająca konfiguracja dająca dziesiątki aktywnych jaili i tysiące blokad: ustawienia ogólne, kluczowe jaile oraz automatyczny ban złośliwych IP z listy ipsum.
Plik /etc/fail2ban/jail.local — ustawienia ogólne i najważniejsze jaile:
ignoreip koniecznie wpisz swój IP i zaufane sieci, w przeciwnym razie można zbanować samego siebie. Po zmianach: sudo fail2ban-client reload.
Automatyczne wczytywanie listy blokad ipsum — w cronie root (sudo crontab -e): level 1 (ponad 100 tysięcy IP) ładuje się do zbioru ipsum, który jest odcinany na zaporze (więcej — w sekcji „Lista blokad IPset”):
ipsum — właśnie jego odczytuje dashboard (karta „IPset ipsum”). Poziomy: levels/1.txt — maksymalny zasięg, levels/3.txt — dokładniejszy (3+ źródła).
Dlaczego „Monitor bezpieczeństwa” jest podzielony na dwie strefy. Ochrona działa na dwóch poziomach, a dashboard ich nie miesza:
sshd, apache-*, nginx-* itp.) oraz groźni recydywiści (jail recidive — ci, którzy byli już banowani kilka razy). To adresy IP, które naprawdę się do Pana dobijały — są na mapie ataków i „Osi czasu”.ipset ipsum, odcinana na zaporze regułą DROP. Te adresy w większości nawet nie dotknęły Pana serwera — są odcinane z wyprzedzeniem; licznik „IPset ipsum” pokazuje, ile odcięto prewencyjnie.Różnica jest prosta: reakcja — „ci zaatakowali i dostali bana”, prewencja — „tych zablokowano jeszcze przed próbą”. Wcześniej do recidive sztucznie wciągano list-3 ipsum (stąd dawny podział „recidive z listy”); teraz recidive to tylko prawdziwi recydywiści, a prewencja w całości na zaporze.
ipsum — publiczna lista złośliwych adresów IP, aktualizowana codziennie. Monitor pokazuje liczbę załadowanych adresów na pulpicie i mapie ataków oraz uwzględnia ją w Ocenie bezpieczeństwa (−10, jeśli zestaw nie jest załadowany).
Minimalny wariant bez fail2ban — osobny zestaw ipsum z blokowaniem przez iptables:
@reboot. Przy okazji polecenie create … -exist ustawia limit maxelem 300000 (domyślnie 65536 — level 1 się nie mieści, wystąpi „Hash is full”):
ipsum i — jeśli zaporą zarządza instalator (świeży VPS — profile „Pełna”/„Odchudzona”) — podłącza zestaw do UFW regułą DROP, dzięki czemu ruch z tych IP jest faktycznie blokowany. Reguła znajduje się po ESTABLISHED,RELATED, więc bieżące połączenia (w tym Pana SSH) nie są zrywane — blokowane są tylko nowe połączenia z listy. Zestaw jest odtwarzany przy uruchomieniu usługi ipsum-load.service przed zaporą (inaczej UFW by się nie podniosło) i aktualizowany cronem o 04:00. Na już skonfigurowanym serwerze (panel, własna zapora) instalator nie ingeruje w zaporę — tam ipsum pozostaje listą dla pulpitu i mapy ataków, a regułę DROP w razie potrzeby dodaje się ręcznie (minimalny wariant z iptables … --match-set ipsum … -j DROP — powyżej). Przy automatycznej instalacji nie trzeba nic robić ręcznie.
Nowoczesny zamiennik Fail2ban z kolektywnym threat intelligence: blokady od społeczności oraz własne reguły. Wymaga osobnego bouncera do stosowania blokad w zaporze.
systemctl is-active crowdsec). Uruchom: sudo systemctl enable --now crowdsec; przy awarii sprawdź sudo journalctl -u crowdsec -n 30. Ta sama zasada dotyczy każdej usługi w statusie „Nie uruchomiono” (Suricata, Falco, Monit, MySQL).
stream halted / blokady nie są stosowane. To osierocony klucz API: bouncer został usunięty z cscli bouncers list, ale jego stary klucz pozostał w /etc/crowdsec/bouncers/*.yaml. Ponownie zarejestruj bouncera i wpisz świeży klucz:
AIDE (Advanced Intrusion Detection Environment) tworzy migawkę systemu plików i przy każdym sprawdzeniu zgłasza zmiany w /etc, /bin, /usr. Po instalacji konieczna jest inicjalizacja bazy (aideinit).
aideinit terminal przez 5–15 minut stoi na linii Running aide --init... — to normalne (haszowanie całego systemu plików, obciążenie dysku). Nie przerywaj klawiszami Ctrl+C. Jeśli proces „wisi”, ale nic nie wypisuje — możliwe, że czeka na odpowiedź na ukryte zapytanie Overwrite existing aide.db.new [Yn]? (naciśnij Y). Sprawdź aktywność z innej sesji: pgrep -af aide.
aideinit: „21_aide_spamassassin … printf: invalid number” (return code 20) — znany błąd fragmentu konfiguracji AIDE w Ubuntu 22.04. Baza nie zostaje utworzona. Wynieś uszkodzony fragment i powtórz:
aideinit nie był uruchomiony, albo (Ubuntu 24.04) katalog /var/lib/aide został utworzony w trybie 700 i jest niedostępny dla www-data — naprawisz to poleceniem sudo chmod 755 /var/lib/aide (patrz blok powyżej). „Brak sprawdzeń” = baza istnieje, ale sprawdzenie nie zostało jeszcze wykonane — to nie błąd. Wyniki monitor czyta z /var/log/aide/aide.log.
/etc/cron.daily/aide na nowych Ubuntu/Debian może nie zapisywać /var/log/aide/aide.log we właściwej postaci (a aide.wrapper już w nich nie ma). Pewniejsze jest dodanie własnego crona z jawnym --config — zapisuje on log od root w trybie 644, a monitor czyta go bez dodatkowych grup:
chmod 755 /var/lib/aide i cron sprawdzania o 02:00 — ręcznie nic nie trzeba.
sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.
Skaner antywirusowy dla Linux. Szczególnie przydatny do sprawdzania /var/www pod kątem PHP-shelli i złośliwego kodu.
enable --now? Trzy typowe przyczyny:
1. W konfiguracji pozostał wiersz Example — clamd nie uruchomi się, dopóki tam jest:
2. Nie pobrano bazy sygnatur — clamd nie uruchomi się bez niej:
3. Po prostu się ładuje — clamd wczytuje ~8 mln sygnatur do pamięci przez 30–60 s. Proszę poczekać i sprawdzić: systemctl is-active clamav-daemon (status activating → nadal ładuje).
sudo journalctl -u clamav-daemon -n 30 --no-pager.
clamd tylko trzyma sygnatury w pamięci, sam niczego nie skanuje według harmonogramu. Panel pokazuje wyniki zaplanowanego skanowania, dlatego potrzebny jest cron, który skanuje i zapisuje log. Automatyczna instalacja dodaje nakładkę /usr/local/bin/clamav-scan.sh oraz cron o 01:30 — po pierwszym uruchomieniu wypełnią się „Sprawdzonych plików” i „Ostatnie skanowanie”. Aby uruchomić od razu, bez czekania na harmonogram: sudo /usr/local/bin/clamav-scan.sh.
Linux Malware Detect (LMD) — skaner złośliwego oprogramowania nastawiony na zagrożenia webowe: powłoki PHP, webowe backdoory, loadery. Wykorzystuje silnik ClamAV i uzupełnia go własnymi sygnaturami.
maldet --report.
update-rc.d: error: unable to read /etc/init.d/maldet — jest on nieszkodliwy. maldet nie korzysta z init.d, aktualizacja sygnatur i skany uruchamiane są przez /etc/cron.daily/maldet. Jeśli poniżej widać installation completed — wszystko się zainstalowało.
apt, lecz w /usr/local/maldetect, a przy włączonym open_basedir jego obecność sprawdzana jest przez powłokę — zob. sekcję „Strona jest pusta, choć dane na serwerze istnieją”.
Sieciowy system wykrywania włamań: analizuje ruch na poziomie pakietów i zna tysiące sygnatur ataków. Uzupełnia ModSecurity (ten działa na poziomie HTTP, Suricata — na poziomie TCP/IP).
/var/log/suricata/eve.json jako root w trybie 750 dla katalogu, a serwer WWW (www-data) nie może go odczytać. Otwórz katalog na przejście — pliki wewnątrz pozostają chronione:
Przechwytuje wywołania systemowe przez eBPF/kernel module i wykrywa anomalie w czasie rzeczywistym: shell z nginx, odczyt /etc/passwd przez proces webowy, zapis do /bin itd.
journalctl -u falco (bez sudo — przez grupę systemd-journal). Proszę upewnić się, że www-data należy do tej grupy — patrz „Konfiguracja sudo” (pkt 2) na stronie instalacji ręcznej.
/etc/passwd, zapis do katalogów systemowych). Zero zdarzeń krytycznych w ciągu doby na spokojnym serwerze to zdrowy stan.
journalctl wymaga uprawnień do dziennika; aby panel widział zdarzenia stabilnie, autoinstalacja włącza w Falco file_output → /var/log/falco/falco.log, a usłudze ustawia UMask=0022 (log odczytywany przez serwer WWW). Przy nowej instalacji nie trzeba tego konfigurować ręcznie.
ModSecurity — zapora webowa (WAF) dla Apache lub Nginx. Blokuje ataki na poziomie aplikacji: wstrzyknięcia SQL, XSS, obejście ścieżek, skanery.
IncludeOptional /etc/modsecurity/*.conf, a pakiet umieszcza tylko modsecurity.conf-recommended — pod maskę *.conf ten plik nie pasuje. Jeśli nie skopiuje go Pan do modsecurity.conf, SecRuleEngine pozostaje Off: moduł jest załadowany, reguły CRS załadowane, ale ruch nie jest sprawdzany, a log audytu nie powstaje. Tryb pośredni DetectionOnly tylko zapisuje zdarzenia do logu, nie blokując żądań — panel pokazuje go na żółto.
Dostęp panelu do logu audytu. Log /var/log/apache2/modsec_audit.log należy do root (uprawnienia 640), użytkownik webowy go nie odczyta. Panel pobiera dane przez nakładkę — proszę ją utworzyć:
SecRuleEngine bez wcięcia: wiersze z wcięciem znajdują się wewnątrz bloków <LocationMatch>/<Directory> (na przykład wyłączenie WAF dla phpMyAdmin) i nie określają trybu globalnego.www-data, w HestiaCP pula witryny działa jako właściciel witryny (na przykład admin) — proszę sprawdzić grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.X-Forwarded-For. Do statystyk trafiają tylko transakcje z wyzwoloną regułą: dyrektywa SecAuditLogRelevantStatus zapisuje w logu audytu wszelkie odpowiedzi 4xx/5xx, dlatego trafiają tam także zwykłe 403/500 — panel nie traktuje ich jako zdarzeń WAF.---RULES--- jest potrzebny sekcji „Wszystkie aktywne reguły” — panel pokazuje nie tylko wyzwolone, ale w ogóle wszystkie załadowane reguły CRS + niestandardowe. Trzy ścieżki w pętli for f in … to typowe miejsca dla reguł CRS i lokalnych dodatków; jeśli ma Pan inny układ (pakiet umieszcza pliki we własnym katalogu lub reguły niestandardowe leżą nie w /etc/modsecurity/custom-rules.conf), proszę znaleźć rzeczywiste ścieżki poleceniem sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null i podstawić je na liście. Jeśli nakładka jest stara (bez tej sekcji) — sekcja po prostu pokaże ostrzeżenie „niedostępne”, reszta strony działa jak wcześniej.
Auditd (Linux Audit Daemon) rejestruje wywołania systemowe na poziomie jądra: logowania i wylogowania, polecenia sudo, nieudane próby uwierzytelniania, zmiany plików. Monitor pokazuje logowania, nieudane próby i polecenia sudo z dzisiaj.
ausearch (/usr/sbin/ausearch), a w razie potrzeby z /var/log/audit/audit.log poleceniem tail. Oba muszą znajdować się w sudoers.
Monitoruje usługi (nginx, php-fpm, mysql itd.) i restartuje je po awarii. Może wysyłać alerty na e-mail.
monit status. W /etc/monit/monitrc musi być włączony interfejs HTTP (blok set httpd z allow localhost), w przeciwnym razie monit status zwróci błąd.
monitrc wiersz set httpd jest zakomentowany (domyślnie jako # set httpd port 2812 …). Odkomentuj blok i zezwól na localhost. (2) Samo włączenie httpd niczego nie monitoruje — Monit liczy tylko to, co opisano stansami check; bez nich lista jest pusta nawet przy działającym interfejsie. Minimalna działająca konfiguracja:
conf.d z httpd na 2812 i zestawem sprawdzeń — przy nowej instalacji nie trzeba nic konfigurować ręcznie.
PSAD analizuje dziennik iptables i wykrywa skanowanie portów oraz ataki sieciowe, przypisując każdemu źródłu poziom zagrożenia (1–5). Uzupełnia fail2ban i Suricata.
psad --Status (wymagany w sudoers). Bez logowania iptables strona będzie pusta — to normalne, dopóki nie wystąpiły skanowania.
Mandatory Access Control ogranicza, do jakich plików i zasobów może sięgać program, nawet jeśli został przejęty. W Ubuntu/Debian domyślnie używany jest AppArmor (zwykle już zainstalowany i aktywny).
aa-status (wymagany w sudoers). Pokazuje liczbę profili w trybie enforce/complain oraz procesy bez profilu.
„Załadowanych profili” jest więcej niż enforce + complain — to normalne. W AppArmor 4.x (Ubuntu 24.04 i nowsze) pojawił się tryb unconfined: profil jest załadowany do jądra, ale niczego nie ogranicza. Ubuntu oznacza w ten sposób dziesiątki profili dla programów korzystających z user namespaces (przeglądarki, klienty torrent i podobne). Gdy takie profile występują, karta „Załadowanych profili” zmienia kolor na bursztynowy i pokazuje ich liczbę — na przykład unconfined: 90 przy 120 załadowanych i 26 w enforce. Realnie chronią tylko profile w enforce; w Ubuntu 22.04 (AppArmor 3.x) tego trybu nie ma i liczby zawsze się zgadzają.
unconfined, warto robić tylko świadomie: nie są one wyłączone przez pomyłkę, lecz dlatego, że inaczej psuje się działanie samych programów. Profile w complain to inna sprawa: reguły są już napisane, tylko nie są stosowane.
debsums sprawdza, czy pliki zainstalowanych pakietów zgadzają się z sumami kontrolnymi z repozytorium — wykrywa podmienione systemowe pliki binarne (uzupełnia AIDE). Pełne sprawdzenie trwa 1–2 minuty, dlatego uruchamiane jest przez cron, a panel odczytuje wynik z data/debsums/debsums.log i sam porządkuje go według kategorii (istotne są tylko pliki binarne i biblioteki).
Zadanie umieszcza się w cronie roota (sudo crontab -e). Gotowy skrypt debsums-scan.sh należy umieścić w /usr/local/bin/ (chmod +x; zob. podsumowanie zadań cron) i sam zapisuje raport w katalogu data/debsums/ panelu.
Skrypt debsums-scan.sh sam odnajduje katalog data/ panelu — nie trzeba podawać ścieżki.
/etc/ (konfiguracje) i /usr/share/ (zasoby) na serwerze są zwykle normalne — panel oznacza je osobnym kolorem. Niepokojące są zmiany plików binarnych i bibliotek (/bin, /sbin, /usr/lib itp.) — karta „Pliki binarne / biblioteki” pokazuje właśnie je.
Lynis uruchamia się ręcznie lub przez cron. Raport musi być zapisywany w folderze data/lynis/ projektu — monitor odczytuje plik lynis-report.dat.
lynis-scan.sh w tle bezpośrednio z panelu (bez czekania na cron): pokazuje „Skanowanie…”, a po zakończeniu sam odświeża raport. Wymaga to wiersza sudoers dla użytkownika serwera WWW na uruchomienie skryptu — instalator dodaje go automatycznie do /etc/sudoers.d/monitor. Jeśli panel był instalowany ręcznie/wcześniej, dopisz go dla tego samego użytkownika, który jest już wskazany w pliku:
Logwatch powinien zapisywać dzienne raporty w folderze data/logwatch/ projektu w formacie .txt. Monitor pokazuje ostatni raport oraz archiwum.
Monitor sieci nie wymaga instalacji — to wbudowana strona panelu. Pokazuje stan sieci serwera z lokalnych źródeł:
/proc/net/dev;ip;ss;journalctl -k.Pierwsze trzy źródła działają bez sudo, dlatego interfejsy, ruch, połączenia i porty są widoczne od razu. Blok „Zdarzenia jądra” korzysta z journalctl -k — odczyt odbywa się przez grupę systemd-journal („Konfiguracja sudo”, p.2), sudo nie jest potrzebne. Aby sprawdzić, czy wszystko jest dostępne dla użytkownika WWW:
UFW BLOCK tutaj nie trafiają — są na stronach „Zapora UFW” i „Mapa ataków”. Pusty blok z zielonym znaczkiem = w ciągu doby nie było awarii sieci.
Wbudowana strona pokazuje trzy rzeczy:
df); skala czerwienieje przy ≥90%;lsblk), tylko rzeczywiste (loop/snap ukryte);smartctl).Miejsce i lista urządzeń działają od razu, bez konfiguracji. Dla SMART potrzebny jest pakiet smartmontools. Proces webowy nie ma bezpośredniego dostępu do urządzeń dyskowych, dlatego SMART jest zbierany przez cron do pliku data/disk/smart.txt, a panel go odczytuje.
Zadanie umieszcza się w root-cronie (sudo crontab -e). Gotowa nakładka smart-scan.sh jest umieszczana w /usr/local/bin/ (chmod +x; zob. zestawienie zadań cron) i sama zapisuje do data/disk/ panelu.
Nakładka smart-scan.sh sama znajduje data/ panelu — ścieżki nie trzeba podawać. Wewnątrz lsblk -e7,11 wyklucza loop/cdrom.
Strona pokazuje historię obciążenia serwera z ostatnich 24 godzin — Load Average, zajętość CPU i oczekiwanie I/O, RAM/Swap, ruch sieciowy (odbiór/wysyłka), I/O dysku (odczyt/zapis), zapełnienie dysku i i-węzłów, otwarte deskryptory plików i połączenia MySQL, a także bieżącą liczbę połączeń TCP i procesów.
Dane zbiera cron/collect_metrics.php — co 5 minut zapisuje jeden „surowy” zrzut liczników (/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') do tabeli bazy system_metrics; procenty i prędkości strona liczy sama na podstawie różnicy między sąsiednimi zrzutami (zapełnienie dysku/i-węzłów/deskryptorów/połączenia MySQL — wartości chwilowe, bez przeliczania). Sudo nie jest wymagane — źródła są odczytywane bez uprawnień root. Punkty starsze niż 24 godziny są usuwane automatycznie przy każdym zapisie.
Nakładka collect-metrics-all.sh (zob. zestawienie zadań cron) sama wykrywa wszystkie zainstalowane instancje panelu na serwerze i uruchamia cron/collect_metrics.php każdej z nich w imieniu właściciela witryny.
Alerty o obciążeniu (sekcja „Ustawienia” → „Alerty o obciążeniu”) — po przekroczeniu progu CPU/RAM/dysku/i-węzłów panel wysyła powiadomienie na Telegram/Email (te same kanały, co raport dzienny — nie trzeba włączać ich osobno dla alertów), a kolejne — gdy metryka wróci do normy. Podczas utrzymywania się przekroczenia progu nie spamuje ponownie: następne powiadomienie przyjdzie dopiero po cyklu „wróciło do normy → ponownie przekroczyło”.
collect_metrics.php przy każdym uruchomieniu (co 5 minut) — osobny cron nie jest potrzebny. Stan „już powiadomiono / jeszcze nie” jest przechowywany w data/alerts_state.json, a progi — w ustawieniach panelu.
Strona „Mapa ataków” określa kraj na podstawie IP za pomocą polecenia geoiplookup. Bez pakietu GeoIP kraje nie zostaną określone, a punkty na mapie się nie pojawią:
/usr/share/GeoIP/GeoIP.dat jest czytelna dla wszystkich, a wyniki są buforowane w tmp/geoip_cache.json. Sama mapa (Leaflet + kafelki OpenStreetMap) ładuje się w przeglądarce — potrzebny jest internet na komputerze, na którym otwarto panel.
Dwie wbudowane karty pulpitu, które pokazują nie „wł./wył.” narzędzia, lecz rzeczywisty poziom zabezpieczenia serwera. Nie wymagają instalacji, są odczytywane lokalnie bez sudo.
Ekspozycja zewnętrzna — ile usług nasłuchuje na wszystkich interfejsach (0.0.0.0/[::]) i jest dostępnych z zewnątrz. Zaznacza na czerwono, jeśli na zewnątrz wystawione są bazy danych lub cache (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — to bezpośrednia luka (−10 do Oceny bezpieczeństwa). Źródło: ss -tuln.
127.0.0.1 (bind-address w konfiguracji MySQL/PostgreSQL, bind 127.0.0.1 w Redis) lub zamknij port w UFW.
127.0.0.1 (loopback) jest widoczna tylko dla samego serwera — z zewnątrz nie da się do niej dotrzeć, nawet jeśli port jest „otwarty”. Dlatego Postfix na porcie 25 przypisany do loopback jest bezpieczny: automatyczna konfiguracja ustawia inet_interfaces = loopback-only (plus neutralny smtpd_banner — usuwa uwagę Lynis MAIL-8818 o ujawnianiu wersji). Karta „Ekspozycja zewnętrzna” liczy jako zewnętrzne tylko to, co nasłuchuje na 0.0.0.0/[::]; usługi loopback tam nie trafiają.
/etc/postfix/main.cf ustaw smtpd_banner = $myhostname ESMTP (bez wersji i systemu) oraz inet_interfaces = loopback-only, następnie sudo systemctl restart postfix.
Aktualizacje zabezpieczeń — ile poprawek bezpieczeństwa czeka na instalację i czy po aktualizacji jądra wymagany jest restart (−5 do Oceny bezpieczeństwa przy dostępnych poprawkach). Źródło: /usr/lib/update-notifier/apt-check, plik /var/run/reboot-required. Szczegółowa lista — na stronie „Aktualizacje zabezpieczeń”.
update-notifier-common). Jeśli apt-check jest niedostępny — monitor liczy poprawki poprzez apt-get -s upgrade.
Automatyczne aktualizacje zabezpieczeń (unattended-upgrades) — na stronie „Aktualizacje zabezpieczeń” osobna karta pokazuje, czy automatyczna instalacja poprawek bezpieczeństwa jest włączona i kiedy uruchomiono ją ostatnio. Sudo nie jest potrzebne — status jest odczytywany przez apt-config dump.
Kopia zapasowa to główne zabezpieczenie: utrata danych jest gorsza niż każde włamanie. Potrzebne są dwie rzeczy — kopia serwera/witryn oraz osobno kopia bazy danych panelu (tam znajdują się użytkownicy, klucze WebAuthn, ustawienia, licencja).
Wariant A — HestiaCP: zakładka Backup u użytkownika → przycisk tworzenia kopii (lub według harmonogramu w ustawieniach serwera). Kopia obejmuje witryny i ich bazy danych.
Wariant B — ręcznie (cron): zrzut bazy danych + archiwum katalogu data/ panelu:
Aktualizacja do nowej wersji. Najpierw proszę wykonać kopię zapasową. Następnie proszę ponownie wgrać pliki kodu, zachowując swoje dane:
public/, includes/, assets/, cron/, database/, a także główne .htaccess (kontroler frontowy — routingu nie można pozostawić z poprzedniej wersji), manifest.json, sw.js;config.php (dane bazy danych), data/ (raporty), logs/, tmp/ (sesje i pamięć podręczna).SSH_FX_PERMISSION_DENIED — Permission denied. Pliki panelu należą do www-data (tak zostały ustawione przy instalacji), a klient SFTP łączy się na własnym użytkowniku, który nie ma prawa zapisu. Oddanie www-data całego panelu „żeby działało” to właśnie to, co prowadzi do tego błędu; poniżej trzy sposoby, każdy rozwiązuje problem.
data/ (raporty), tmp/ (sesje i pamięć podręczna), logs/; pozostają one przy www-data. Reszta to kod, a serwer WWW potrzebuje go jedynie do odczytu, który zapewnia grupa www-data z prawami 644. Dodatkowa korzyść: przy podatności w PHP plików panelu już nie da się nadpisać. Na panelach hostingowych (HestiaCP i podobnych) wariant A nie jest potrzebny: tam pliki witryny i tak należą do konta, na które Pan loguje się przez SFTP, a serwer WWW czyta je po grupie.
chmod na plikach resetuje maskę ACL i dostęp po cichu znika. Jeśli po „uporządkowaniu praw” wgrywanie znów natrafia na Permission denied — proszę powtórzyć obie komendy setfacl.
2 w wariancie C to setgid: pliki wgrane przez SFTP pozostają w grupie www-data, inaczej panel nie będzie mógł ich nadpisać. Po wariancie C proszę połączyć się ponownie w FileZilli — nowa grupa działa dopiero przy nowym logowaniu. Sprawdzenie: id deploy (musi pojawić się grupa www-data) oraz ls -ld /path/to/monitor (drwxrwsr-x — litera s oznacza, że setgid jest ustawiony).
Migracja na inny serwer:
config.php, data/.mysqldump na starym → import na nowym; proszę poprawić dane bazy danych w config.php.adm, zadania cron.Jeśli nie może się Pan zalogować — wszystko naprawia się bezpośrednio w bazie danych z serwera. Proszę otworzyć bazę danych (nazwa — z config.php):
Utracony klucz WebAuthn (drugi składnik nie przechodzi) — proszę wyłączyć 2FA, zalogować się hasłem i zarejestrować nowy klucz:
Zapomniane hasło — proszę ustawić nowy hash (wygeneruj go na serwerze i podstaw):
Zablokowanie samego siebie filtrem IP — proszę wyłączyć ograniczenie:
sudo mysql na serwerze albo phpMyAdmin / sekcja bazy danych w panelu hostingu. Po odzyskaniu proszę ponownie włączyć WebAuthn i filtr IP.
Zestawienie zadań — w cronie root serwera (dodawane przez sudo crontab -e). Proszę zostawić tylko wiersze narzędzi, których Pan/Pani używa; ścieżki dopasować do swojego serwera.
sudo crontab -l oraz to, że usługa cron jest aktywna.
TIMEZONE z config.php. Stała TIMEZONE wpływa tylko na PHP (jak panel pokazuje daty), ale demon cron uruchamia zadania według czasu systemowego OS. Jeśli strefa serwera nie zgadza się z Pana/Pani strefą, raport „08:00” przyjdzie o innej porze. Przykład: serwer stoi w innej strefie (Europe/London, UTC+1), a Pan/Pani jest w Warszawie (UTC+2) → raport „08:00” przyjdzie o 09:00 według Pana/Pani czasu. Proszę sprawdzić i w razie potrzeby dostosować strefę systemu do swojej:
0 8 * * * zadziała o 08:00 czasu lokalnego. Inaczej trzeba by przesuwać sam cron, ale przy zmianie czasu zimowego/letniego przesunięcie znów się rozjedzie — dlatego właściwsze jest ustawienie strefy systemu.
crontab.txt) leżą w folderze system/ obok projektu, poza public_html. To nie część witryny — nie trzeba ich wgrywać do katalogu web; proszę umieścić je na serwerze pod ścieżkami systemowymi (jak w crontab powyżej):
lynis-scan.sh → /usr/local/bin/ (chmod +x) — uruchamia lynis audit system, na czas skanu ustawia flagę /tmp/lynis-running i kopiuje lynis-report.dat do data/lynis/ panelu;logwatch_daily.sh → /usr/local/bin/ (chmod +x) — tworzy codzienny raport Logwatch (sshd, fail2ban, sudo, postfix) w data/logwatch/;smart-scan.sh → /usr/local/bin/ (chmod +x) — zbiera stan dysków (smartctl) w data/disk/;debsums-scan.sh → /usr/local/bin/ (chmod +x) — sprawdza integralność pakietów (debsums) w data/debsums/;clamav-scan.sh → /usr/local/bin/ (chmod +x) — skan antywirusowy ClamAV po niebezpiecznych ścieżkach (web, home, temp); zapisuje zestawienie do /var/log/clamav/scan.log, skąd czyta je strona ClamAV (wiersz 01:30 w crontab powyżej);load-ipsum.sh → /usr/local/bin/ (chmod +x) — aktualizuje zbiór ipset ipsum (level 1) w miejscu, bez zrywania aktywnych reguł zapory (wiersz 04:00 w crontabie powyżej);daily-report-all.sh → /usr/local/bin/ (chmod +x) — uruchamia raport cron/daily_report.php panelu (wiersz 08:00 w crontab powyżej);daily_report.php — już wchodzi w skład panelu (cron/daily_report.php), uruchamiany przez daily-report-all.sh, nie trzeba go osobno instalować;collect-metrics-all.sh → /usr/local/bin/ (chmod +x) — uruchamia cron/collect_metrics.php panelu (strona „Wydajność”, wiersz */5 w crontab powyżej); collect_metrics.php już wchodzi w skład panelu, nie trzeba go osobno instalować;crontab.txt (system/cron/) — wzór zadań; potrzebne wiersze proszę wpisać przez sudo crontab -e./usr/local/bin/. Bezpośrednio z FileZilla nie da się tam zapisać — katalog należy do root, a klient SFTP otrzyma SSH_FX_PERMISSION_DENIED. Kolejność jest taka: najpierw wgrać plik do /tmp (tam piszą wszyscy), następnie przenieść go na miejsce jednym poleceniem:
/tmp w katalogu głównym serwera — nie /var/tmp i nie tmp/ wewnątrz samego panelu (ten ostatni należy do www-data i jest zamknięty dla Pana/Pani użytkownika). W drzewie FileZilla /tmp to gałąź najwyższego poziomu, obok var, a nie wewnątrz niej.
/usr/local/bin/, log — /var/log/arciveo-cron.log) — ręcznie nie trzeba nic robić.
/home/*/web/*/public_html i /var/www/*, i zapisują raporty do ich data/. Jeśli panel leży pod inną ścieżką — proszę dodać ją do wiersza for app in … wewnątrz skryptów, inaczej raporty Lynis/SMART/debsums/Logwatch nie trafią do panelu.
logs/cron.log jako pierwszy tworzy cron root — będzie należał do root, a zakładka „Dziennik cron” w panelu nie będzie mogła go ani odczytać, ani wyczyścić. Proszę utworzyć plik wcześniej jako użytkownik web (właściciel katalogu witryny; w HestiaCP to konto, np. admin) — wtedy cron root będzie tylko dopisywać, nie zmieniając właściciela:
stat -c %U /path/to/monitor.
sudo crontab -e), inaczej będzie wykonywane dwa razy.
sudo crontab (to byłaby bezpośrednia eskalacja do root dla każdego, kto uzyska dostęp do sesji panelu), lecz wąskiego skryptu z dwoma poleceniami (list/set), który rusza tylko swój blok między komentarzami służbowymi. Proszę zainstalować raz:
www-data — proszę sprawdzić, na kim działa pula PHP-FPM witryny (ps -o user= -C php-fpm), i podstawić go w wierszu sudoers.
public/crontab_monitor.php został wgrany przez FTP/SFTP jako inny użytkownik systemowy (np. root) niż pozostałe pliki witryny, serwer web nie zdoła go odczytać. Proszę porównać właściciela i uprawnienia z sąsiednim plikiem i doprowadzić do zgodności:
Monitor wykrywa obecność narzędzi za pomocą dpkg-query — bazy pakietów APT. Jeśli narzędzie nie zostało zainstalowane przez apt (ręcznie, ze snap lub ze źródeł), dpkg go nie widzi.
Błąd 500 — proszę sprawdzić logi PHP, nginx oraz samego monitora:
www-data, lecz pod kontem użytkownika (na przykład admin — właściciel katalogu witryny). Wszystkie reguły sudo i przynależność do grup (adm, systemd-journal) należy zapisać dla tego użytkownika, inaczej moduły pokażą „Nieaktywny / 0” przy działających usługach. Aby poznać rzeczywistego użytkownika PHP: ps -o user= -C php-fpm | sort -u lub właściciela katalogu witryny stat -c '%U' /path/to/monitor. Dalej we wszystkich poleceniach poniżej proszę podstawić go zamiast www-data. Automatyczna instalacja sama wykrywa użytkownika serwera WWW i zapisuje dla niego sudoers.
Dane się nie wyświetlają — prawie zawsze przyczyną są nieustawione uprawnienia sudo. Proszę sprawdzić konkretne polecenie jako użytkownik serwera WWW (zamieniając www-data na własnego). Flaga -n = bez hasła, tak jak w PHP — jeśli prosi o hasło, to znaczy, że reguły w sudoers nie ma:
sudo aa-status w terminalu pokazuje profile, a strona „AppArmor” — „Nieaktywny”). Przyczyna: użytkownik serwera WWW nie ma uprawnienia sudo do polecenia tego modułu. Proszę je sprawdzić z listy powyżej: jeśli prosi o hasło — dodać brakujący wiersz do /etc/sudoers.d/monitor („Konfiguracja sudo”). Częste „nowe” polecenia: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
apache2ctl, ausearch, aa-status lub ss, albo użytkownik serwera WWW nie należy do grup adm/systemd-journal (stamtąd czytane są logi fail2ban/auth/modsec oraz journalctl — Falco i zdarzenia jądra).
Objaw: na serwerze dane są (widać je przez shell), a strona pokazuje „brak danych” lub nieprawidłowy status — na przykład AIDE wyświetla „Nie zainicjalizowana”, choć baza została utworzona.
Przyczyną jest open_basedir: wiele paneli i hostingów ogranicza pulę PHP-FPM do katalogu domeny, przez co funkcje PHP file_exists(), file_get_contents(), filemtime() na ścieżkach systemowych (/var/lib/aide, /var/log, /proc…) są blokowane. Monitor omija to, odczytując takie ścieżki standardowymi poleceniami systemowymi (cat, test, stat).
open_basedir. Właściwym rozwiązaniem jest odczyt poleceniami systemowymi (już zrobione dla AIDE i Monitora sieci). Rozszerzanie open_basedir na /var, /proc nie jest potrzebne i jest mniej bezpieczne.
Monitor sprawdza certyfikaty, łącząc się z domenami bezpośrednio przez port 443. Jeśli domena jest niedostępna z samego serwera lub port jest zablokowany przez zaporę — sprawdzenie się nie powiedzie.
/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) i Apache (/etc/apache2/sites-enabled/) oraz z bieżącego hosta z HTTP_HOST.
Monitor łączy się z MySQL jako użytkownik z config.php, który ma dostęp tylko do własnej bazy. MySQL pokazuje w information_schema jedynie bazy, do których użytkownik ma uprawnienia — dlatego pozostałe są niewidoczne.
Aby monitor widział wszystkie bazy, nadaj temu użytkownikowi prawo tylko do odczytu (jednorazowo jako root; wstaw nazwę użytkownika z config.php):
sudo mysql: lista baz jest pobierana przez jego własne połączenie PDO.
PostgreSQL wymaga dostępu na poziomie użytkownika postgres, którego użytkownik sieciowy panelu nie posiada. Otwieranie z poziomu PHP szerokiego sudo psql jest niebezpieczne — zamiast tego panel wywołuje wąską nakładkę bez parametrów, która wypisuje jedynie wersję, liczbę połączeń oraz listę baz z ich rozmiarami. Proszę ją utworzyć:
monitor-pgstat z sudoers (krok 13 instalacji ręcznej) i nie tworzyć samego skryptu: karta PostgreSQL pozostanie po prostu nieaktywna.
Panel pokazuje, co się dzieje; poniżej — co robić w typowych sytuacjach. Ogólna zasada: nie panikować, porównać z legalną aktywnością (Pana działania, aktualizacje, kopie zapasowe) i reagować odpowiednio do powagi.
ignoreip./etc, poza /usr/share) — potencjalnie podmiana. Proszę sprawdzić pakiet: debsums PACKAGE_NAME, w razie wątpliwości zainstalować go ponownie (apt install --reinstall).127.0.0.1 lub zamknąć port w UFW. To realna luka.certbot renew lub ustawienia w panelu).sudo apt update && sudo apt upgrade; po aktualizacji jądra proszę zrestartować serwer.