To jest przewodnik po instalacji, konfiguracji i obsłudze Arcivéo Security 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 Security 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.
Dwa rytmy pracy. Strony panelu odpytują narzędzia w chwili otwarcia — zawsze widać stan bieżący. Poza tym w tle działają zadania uruchamiane według harmonogramu (cron):
Pełna lista zadań znajduje się w rozdziale „Wszystkie zadania cron w jednym miejscu”.
Ocena zaczyna się od maksimum i spada za każdy wykryty problem:
PermitRootLogin yes) — −20PasswordAuthentication yes) — −10X11Forwarding, MaxAuthTries powyżej 3 lub sshd_config czytelny dla wszystkich kont — −5TRACE albo brakuje nagłówka Strict-Transport-Security lub X-Frame-Options — −5Wynik: 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.
Kanały są cztery: Telegram, Email, webhook i push w przeglądarce. Są od siebie niezależne — można włączyć dowolne, nawet wszystkie cztery. Tymi samymi kanałami idą dzienny raport bezpieczeństwa, alerty o obciążeniu i znaleziska czujnika zdarzeń; konfiguruje się je raz, tutaj, 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.Webhook. Jeden adres przyjmujący POST obsługuje Slacka, Discorda, Mattermosta, n8n i własny skrypt. „Ustawienia” → Webhook: proszę wkleić adres i włączyć przełącznik.
{"text": …}, do Discorda {"content": …} (Discord odrzuca wiadomości dłuższe niż 2000 znaków, więc tekst jest przycinany);text, event, severity, source, count, host, ts — nie trzeba ponownie rozbierać treści wiadomości.Powiadomienia push. Komunikat trafia wprost do przeglądarki, a jeśli panel jest dodany do ekranu głównego telefonu — jako zwykłe powiadomienie aplikacji, bez bota i bez serwera pocztowego po drodze. „Ustawienia” → Powiadomienia push: proszę włączyć przełącznik i nacisnąć „Podłącz to urządzenie” na każdym urządzeniu, które ma odbierać powiadomienia. Licznik „Podłączone urządzenia” pokazuje, ile ich jest.
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.
Panel chroniony jest logowaniem hasłem oraz, jeśli jest włączony, filtrem IP. Programowi nie odpowiada ani jedno, ani drugie, dlatego systemy zewnętrzne mają własne wejście — dwa adresy tylko do odczytu zabezpieczone tokenem. Token niczego na serwerze nie zmienia: da się nim wyłącznie pobrać wskaźniki.
Włączenie — „Ustawienia” → „API tylko do odczytu”: przełącznik „Włączyć API”; token tworzony jest automatycznie przy pierwszym zapisie. Przycisk „Nowy token” wydaje inny i w tej samej chwili odcina wszystkich, którzy korzystali z poprzedniego.
/api/status.php — JSON: ocena bezpieczeństwa, stan modułów, ostatni pomiar obciążenia wraz z najcięższymi procesami oraz zdarzenia bezpieczeństwa z ostatnich 24 godzin;/api/metrics.php — te same liczby w tekstowym formacie Prometheusa (metryki arciveo_*: arciveo_security_score, arciveo_fail2ban_banned, arciveo_cpu_busy_pct i tak dalej).Jeśli klient nie potrafi ustawić nagłówka, token przyjmowany jest także jako parametr — ?token=…. Proszę pamiętać, że w tej postaci trafia on do dziennika dostępu serwera WWW, więc nagłówek jest lepszy.
Prometheus. Gotowy blok do scrape_configs:
api disabled — API jest wyłączone w ustawieniach. Odrzucone żądania zapisywane są w dzienniku aplikacji wraz z adresem IP nadawcy, więc próby zgadywania tokenu widać na stronie „Logi aplikacji”.
Panel instaluje się na każdym serwerze osobno i dobrze odpowiada na pytanie „jak się miewa ta maszyna”. Na pytanie „jak się miewają wszystkie moje maszyny” nie odpowiada — po to każdy panel może wysyłać krótkie podsumowanie do panelu klienta, gdzie serwery widoczne są na jednej liście.
Co wziąć w panelu klienta my.arciveo.com → sekcja „Moje serwery”: wydawany jest tam token (postaci fk_…) i podany adres odbiorcy https://my.arciveo.com/api/fleet.php. Token jest jeden na konto — taki sam dla wszystkich Państwa serwerów.
Co ustawić w panelu — „Ustawienia” → „Przegląd serwerów”: adres odbiorcy, token, nazwa serwera (jak będzie podpisany na liście; pozostawiona pusta oznacza domenę panelu) oraz przełącznik „Wysyłać podsumowanie”. Przycisk „Wyślij teraz” sprawdza łączność natychmiast, bez czekania na harmonogram.
Dalej podsumowanie wychodzi przez cron, co 15 minut:
Co dokładnie wychodzi: nazwa i domena serwera, system operacyjny, czas pracy, wersja PHP; ocena bezpieczeństwa; stan modułów (UFW, liczba jaili Fail2ban, bany z dzisiaj, czy działają CrowdSec, Suricata i Falco, zagrożenia ClamAV, zmiany AIDE, indeks Lynis, oczekujące aktualizacje, czy potrzebny jest restart, dni do wygaśnięcia certyfikatu, liczba niebezpiecznie otwartych portów); ostatni pomiar obciążenia (load, CPU, RAM, dysk, inody); liczniki zdarzeń z ostatnich 24 godzin i ostatnie zdarzenie krytyczne. Dzienników, haseł ani treści plików w podsumowaniu nie ma.
sudo crontab -l) oraz to, co odpowiada przycisk „Wyślij teraz”. Błędy wysyłki zapisywane są w dzienniku aplikacji pod znacznikiem FLEET — widać tam, czy token został odrzucony (HTTP 401), czy też samo połączenie nie doszło do skutku.
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. Domyślne jest okno 24 godzin: przyciski u góry przełączają je na 7 dni lub 30 dni.
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.
Dwie głębokości przechowywania. „Surowe” pięciominutowe migawki żyją dobę (plus godzina zapasu, żeby najstarszy punkt na wykresie miał jeszcze poprzednika do obliczeń). Każda zakończona godzina jest zwijana do jednego wiersza; ten szereg godzinowy przechowywany jest 30 dni i to właśnie jego czytają widoki „7 dni” i „30 dni”. Miesiąc historii kosztuje dzięki temu około 720 wierszy zamiast mniej więcej 8600.
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.
Najcięższe procesy. Pod wykresami są dwie tabele z pięcioma procesami najbardziej obciążającymi CPU:
Obie tabele zawsze opisują ostatnie 24 godziny, nawet gdy wykresy pokazują miesiąc: migawkę procesów mają tylko wiersze pięciominutowe, a te nie są przechowywane dłużej niż dobę.
ps, skrypt PHP zbierający dane oraz łańcuch cron/sudo nad nim) są z listy wykluczane — inaczej zajmowałyby pierwsze miejsca w każdej migawce: ps w chwili startu pokazuje prawie 100 % CPU. Inne zadania cron uruchomione w tej samej minucie jak najbardziej się pojawiają — właśnie po to ta tabela jest.
Alerty o obciążeniu (sekcja „Ustawienia” → „Alerty o obciążeniu”) — po przekroczeniu progu CPU/RAM/dysku/inodów panel wysyła powiadomienie wszystkimi włączonymi kanałami (Telegram, Email, webhook, push — tymi samymi co raport dzienny; dla alertów nie trzeba włączać nic osobno), a drugie wtedy, gdy metryka wróci do normy. Dopóki próg jest utrzymywany, nie spamuje: kolejne powiadomienie przyjdzie dopiero po cyklu „wróciło do normy → znowu przekroczone”.
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.
Raport dzienny odpowiada na pytanie „jak się miewa serwer”. Czujnik odpowiada na inne — „co się właśnie stało”. Co 5 minut odpytuje szybkie źródła i zapisuje tylko to, co zmieniło się od poprzedniej kontroli; strona „Zdarzenia bezpieczeństwa” w menu pokazuje listę znalezisk.
Wolnych kontroli — Lynis, debsums, aktualizacji pakietów, terminu ważności SSL — czujnik nie rusza: ich liczby i tak zmieniają się raz na dobę i pozostają domeną raportu dziennego.
Co zauważa — dziewięć źródeł:
[Priority: 1] podnosi znalezisko do rangi krytycznego;FOUND w dzienniku skanowania;root (krytyczne) oraz logowanie z adresu, którego wcześniej nie było (ostrzeżenie);Narzędzie niezainstalowane albo takie, którego dziennika panel nie może odczytać, po prostu milczy — to nie błąd i nie zdarzenie.
data/secwatch_state.json), a pierwsze przejście tylko ten znacznik zapisuje. Inaczej po włączeniu nadzoru przyszłoby powiadomienie o wszystkim, co dzienniki zebrały przez miesiące.
Konfiguracja — „Ustawienia” → „Nadzór nad zdarzeniami”:
23-7, w którym ostrzeżenia nie są wysyłane.Powiadomienia idą tymi samymi kanałami co raport dzienny (Telegram, Email, webhook, push) — nie trzeba włączać nic osobno. Wszystkie znaleziska trafiają na listę niezależnie od tego, czy powiadomienie wyszło, i są przechowywane 90 dni.
Lista zdarzeń. Filtry: okres (24 godziny, 7, 30 lub 90 dni), ważność i źródło; pokazywanych jest ostatnich 500 wpisów. Przycisk „Sprawdź teraz” uruchamia dokładnie to samo przejście co cron — wygodnie zaraz po konfiguracji, żeby nie czekać pięciu minut; podaje też powód, gdy powiadomienie nie wyszło („poniżej progu ważności”, „godziny ciszy”, „nie skonfigurowano żadnego kanału powiadomień”). Czerwony licznik przy pozycji menu to liczba zdarzeń krytycznych z ostatnich 24 godzin.
Karta adresu. Kliknięcie wiersza na liście zdarzeń lub w bloku Powiązane adresy otwiera wszystko, co wiadomo o jednym adresie: przebieg jego zdarzeń w czasie, kraj oraz w pierwszym wierszu wniosek. Wiersz listy otwiera kartę, gdy zdarzenie dotyczy dokładnie jednego adresu; jeśli wymienia kilka, odnośnikami są same adresy wewnątrz wiersza. Wnioski są cztery:
Pod przebiegiem w czasie znajduje się blok Co działo się na serwerze w tym samym czasie: zdarzenia, które w ogóle nie mają adresu. AIDE nie wie, kto zmienił plik, ClamAV nie wie, kto przyniósł zakażony. Pokazane są te, które przypadają na aktywność adresu i sześć godzin po niej. To właśnie logowanie wraz z tym, co po nim nastąpiło, oddziela próbę od rzeczywistego dostępu.
Harmonogram. Zadanie trafia do crontaba root (sudo crontab -e), przesunięte o 2 minuty względem zbierania metryk, żeby oba nie startowały jednocześnie:
php cron/security_watch.php. Wrapper znajduje wszystkie instalacje panelu na serwerze i uruchamia kontrolę w imieniu właściciela witryny — z tymi samymi uprawnieniami sudo, z których panel korzysta z poziomu WWW. Bezpośrednie wywołanie z crontaba root utworzyłoby plik stanu data/secwatch_state.json należący do root, a przycisk „Sprawdź teraz” przestałby działać.
Strona „Serwer WWW” analizuje dziennik dostępu i pokazuje, ile było żądań, jaka ich część zakończyła się błędem i kto je wysyłał. ModSecurity odpowiada na pytanie „co zostało zablokowane”, ta strona — na pytanie „co w ogóle dotarło do witryny”.
Co widać: liczbę żądań, RPS, udział błędów, osobny licznik 5xx oraz objętość przesłanych danych; wykres żądań w godzinach; rozkład kodów 2xx/3xx/4xx/5xx; częste adresy, częste IP, częste błędy (kod plus ścieżka) i klientów (User-Agent). Okres: 24 godziny albo 7 dni.
Źródłem jest dziennik dostępu w formacie combined, dlatego nadają się zarówno Nginx, jak i Apache, a dodatkowy moduł nie jest potrzebny. Panel szuka dziennika wśród standardowych plików:
/var/log/nginx/access.log/var/log/apache2/access.log/var/log/apache2/other_vhosts_access.log/var/log/httpd/access_logOprócz nich panel sprawdza pliki *access*.log i *requests*.log w katalogach /var/log/nginx/, /var/log/apache2/ i /var/log/httpd/. W ten sposób znajduje się także dziennik, który witryna zapisuje do własnego pliku dyrektywą CustomLog — na przykład arciveo-monitor_requests.log, tworzony przez instalator Arcivéo.
Czytany jest tylko jeden dziennik: gdy Nginx stoi przed Apache, zsumowanie dwóch dzienników liczyłoby każde żądanie dwa razy. Brany jest pierwszy dziennik z powyższej listy, do którego coś zapisano w ciągu ostatniej doby (pliki znalezione według maski sprawdzane są po nim, od najświeższych); jeśli przez dobę nie zapisano nic do żadnego, brany jest najświeższy niepusty. Dziennik opróżniony przez logrotate albo pozostały po wyłączonym serwerze WWW nie przesłania więc działającego. Czytany jest ostatni fragment dziennika (3 MB), a wynik trafia do pamięci podręcznej na 5 minut — na obciążonej witrynie wybrany okres może więc nie być pokryty w całości; faktyczny zasięg podany jest nad wykresem.
adm, a użytkownik WWW do niej nie należy. Instalator Arcivéo dodaje go do tej grupy; po ręcznej instalacji pomoże mały wrapper roota, któremu wolno dokładnie jedno — pokazać dziennik (strona ModSecurity działa tak samo). Wrapper wybiera dziennik według tych samych zasad co panel. Polecenie wyświetlane jest na samej stronie; oto ono. Proszę wkleić je w całości — to jedno polecenie:
Użytkownik WWW może być inny niż www-data — proszę sprawdzić, na jakim użytkowniku działa pula PHP-FPM witryny (ps -o user= -C php-fpm), i wpisać go w wierszu sudoers. Jeśli nazwa dziennika nie zawiera ani access, ani requests, proszę dopisać jego ścieżkę na początku wiersza L=… wewnątrz wrappera.
Próby znanych exploitów. Panel porównuje zapytania z dziennika z sygnaturami około dwudziestu popularnych exploitów: PHP-CGI, przejście poza katalog w Apache, PHPUnit, Log4Shell, luki w routerach, kamerach i bramach VPN. Dla każdej próby podaje, czy może zadziałać na tym serwerze, i opiera się na faktach: zainstalowanych wersjach Apache i PHP, obecności Javy oraz kodzie, którym serwer odpowiedział na zapytanie o plik. Na czerwono oznaczone jest tylko to, co naprawdę może zadziałać.
Zabezpieczenie serwera WWW. Panel odpytuje każdą witrynę serwera przez 127.0.0.1 i sprawdza, co otrzymuje odwiedzający: czy widać wersje serwera WWW i PHP, czy włączona jest metoda TRACE oraz czy są nagłówki ochronne Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy i Content-Security-Policy. Witryny pochodzą z adresu, pod którym otwarto panel, oraz z plików hostów wirtualnych, jeśli panel może je odczytać. Wynik odświeża się co 10 minut.
Jeśli czegoś brakuje, pod tabelą pojawia się jedno polecenie. Tworzy osobny plik zz-arciveo-hardening.conf i przeładowuje serwer WWW dopiero po pomyślnym teście konfiguracji; nagłówki, które witryna już wysyła sama, nie są dublowane. CSP nie jest proponowane jako jedna linia: politykę buduje się pod konkretną witrynę, inaczej przestanie ona ładować własne skrypty, style i czcionki. Cofnięcie zmiany w Apache:
ServerSignature) nie jest oznaczany, jeśli wersja serwera WWW jest już ukryta: bez wersji pokazuje tylko nazwę serwera i nazwę hosta.
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.Panel już działa, a na tym samym serwerze potrzebna jest jeszcze jedna witryna — z własną domeną obok monitora. Po automatycznej konfiguracji serwer to zwykły Apache + PHP-FPM, więc witrynie potrzebne są trzy rzeczy: własny katalog, własny vhost i własny certyfikat. Panelu przy tym nie ruszamy: obserwuje cały serwer, druga instancja dla drugiej domeny nie jest potrzebna.
site2.example.com to adres nowej witryny. Może to być zarówno osobna domena (mycompany.com), jak i subdomena (shop.mycompany.com) — dla Apache nie ma różnicy, różnią się tylko wpis DNS (krok 1) i wystawienie certyfikatu (krok 5). site2 to po prostu krótka nazwa witryny: tak nazwano katalog /var/www/site2 i plik konfiguracyjny site2.conf. Z domeną nie ma to nic wspólnego, Apache bierze adres wyłącznie z ServerName; nazwa może być dowolna — dla shop.mycompany.com wygodnie jest wziąć shop: katalog /var/www/shop, konfiguracja shop.conf.
1. DNS. W panelu DNS u rejestratora domeny proszę utworzyć wpis A na IP tego serwera:
Po kilku minutach proszę sprawdzić: dig +short site2.example.com powinno zwrócić IP serwera.
2. Katalog witryny.
3. Vhost. Blok wkleja się do terminala w całości — ścieżka do gniazda PHP-FPM ustalana jest automatycznie:
4. Proszę włączyć witrynę i sprawdzić konfigurację przed przeładowaniem:
5. SSL. certbot został już zainstalowany przez automatyczną konfigurację; DNS musi w tym momencie wskazywać na serwer:
Trzecią i kolejne domeny dodaje się tak samo — proszę powtórzyć kroki 1–5, zmieniając domenę i katalog.
Host nie pasuje do żadnego ServerName (wejście po IP albo cudza domena skierowana na Pana/Pani serwer), Apache wydaje pierwszą alfabetycznie włączoną witrynę z /etc/apache2/sites-enabled/. Standardowy 000-default automatyczna konfiguracja wyłącza, więc tym „dyżurnym” pozostaje vhost panelu (arciveo-monitor.conf) — na witryny otwierane pod własnymi nazwami nie ma to wpływu. Jeśli po IP ma otwierać się inna witryna, proszę nazwać jej plik tak, aby był pierwszy alfabetycznie (na przykład 000-site2.conf).
site2_error.log i site2_access.log w /var/log/apache2/.
.htaccess (kontroler frontowy), a zagnieżdżona witryna zwracałaby coś innego, niż się Pan/Pani spodziewa. Proszę trzymać witryny obok siebie: /var/www/monitor, /var/www/site2.
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ć;security-watch-all.sh → /usr/local/bin/ (chmod +x) — uruchamia cron/security_watch.php panelu w imieniu właściciela witryny (strona „Zdarzenia bezpieczeństwa”, wiersz 2-57/5 w crontabie powyżej); security_watch.php wchodzi już w skład panelu i nie trzeba go instalować osobno;fleet-push-all.sh → /usr/local/bin/ (chmod +x) — wysyła podsumowanie serwera do panelu klienta przez cron/fleet_push.php panelu (wiersz 3,18,33,48 powyżej);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.