FAQ

Toto je průvodce instalací, konfigurací a údržbou nástroje Arcivéo Security Monitor. Sekce jsou rozděleny do skupin: obecný přehled, nasazení panelu, připojení bezpečnostních nástrojů, vestavěné moduly a diagnostika. Příkazy lze kopírovat tlačítkem vpravo.

Kde začít

01. Instalace panelu — vyberte způsob

Instalace panelu je popsána na samostatných stránkách krok za krokem. Vyberte způsob:

Pokud si nejste jistí, zvolte automatickou. Tento průvodce zůstává jediným zdrojem informací o SSL, nástrojích, cronu a diagnostice — instalační stránky odkazují na jeho sekce a nic neduplikují.

Přehled

02. Co je Arcivéo Security Monitor

Arcivéo Security Monitor — dashboard zabezpečení serveru. Sbírá data z nainstalovaných nástrojů (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco aj.) a zobrazuje je v jednotném rozhraní s dashboardem, mapou útoků a podrobnými stránkami ke každému nástroji.

Monitor není aktivní ochranný prostředek — sám o sobě útoky neblokuje. Jeho úkolem je agregovat informace z již běžících nástrojů a přehledně je zobrazit.

03. Jak monitor na serveru funguje

Monitor pracuje pouze lokálně — musí být nainstalován na stejném serveru, který sleduje. Žádné SSH ani vzdálené API neexistuje.

Všechny příkazy (fail2ban-client, ufw status, ipset list atd.) spouští panel pod uživatelem webového serveru (obvykle www-data, na hostingových panelech účet webu) s úzkou sadou práv sudo — jen pro konkrétní nástroje, bez obecného přístupu root. Výsledky se parsují a zobrazují v prohlížeči.

Dva rytmy práce. Stránky panelu se dotazují nástrojů ve chvíli otevření — vždy vidíte aktuální stav. Kromě toho běží na pozadí úlohy podle plánu (cron):

  • každých 5 minut — snímek zatížení pro stránku „Výkon“;
  • každých 5 minut — senzor bezpečnostních událostí: nové bany, hlášení IDS, zastavená ochrana, otevřený port (kapitola „Bezpečnostní události“);
  • jednou denně — bezpečnostní zpráva na Telegram a e-mail a také náročné kontroly (Lynis, AIDE, ClamAV, debsums, Logwatch);
  • každých 15 minut — přehled serveru do zákaznického účtu, pokud je zapnutý.

Úplný seznam úloh je v kapitole „Všechny cron úlohy na jednom místě“.

Pro více serverů instalujte monitor na každý zvlášť, s vlastní doménou. Abyste je viděli v jednom seznamu, zapněte přehled serverů (kapitola „Přehled serverů v zákaznickém účtu“).

04. Jak se počítá skóre zabezpečení

Skóre začíná na maximu a snižuje se za každý zjištěný problém:

  • UFW není aktivní — −30
  • Fail2ban neběží (žádný aktivní jail) — −25
  • Žádné klíče WebAuthn — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum není načten — −10
  • Hrozby nalezené ClamAV — −20
  • Změny souborů AIDE — −15
  • SSL vypršel — −30, vyprší za <14 dní — −15, <30 dní — −5
  • CrowdSec je nainstalován, ale neběží — −5
  • Suricata je nainstalována, ale neběží — −5
  • Databáze/cache (MySQL, PostgreSQL, Redis…) jsou dostupné zvenčí — −10
  • Povolené přihlášení roota přes SSH (PermitRootLogin yes) — −20
  • Povolené přihlášení heslem přes SSH (PasswordAuthentication yes) — −10
  • Drobná nastavení SSH: zapnutý X11Forwarding, MaxAuthTries nad 3 nebo sshd_config čitelný pro všechny účty — −5
  • Zabezpečení webového serveru: odpovědi prozrazují verzi webového serveru nebo PHP, je zapnutá metoda TRACE nebo chybí hlavička Strict-Transport-Security či X-Frame-Options — −5
  • Čekají bezpečnostní aktualizace — −5

Výsledek: 80+ = Zabezpečeno, 60–79 = Pozor, <60 = Ohroženo.

Srážky za ClamAV, AIDE, CrowdSec a Suricata se uplatňují jen tehdy, je-li nástroj nainstalován. Lynis a AIDE bez inicializované databáze se zobrazují jako „bez dat“ a skóre nesnižují. Počet útoků za dnešek se zobrazuje na dashboardu, ale skóre zabezpečení neovlivňuje. Zabezpečení webového serveru se nepočítá, pokud na kontrolu neodpověděl žádný web.

Nastavení a licence

05. WebAuthn — dvoufaktorové ověření

WebAuthn — standard ověření bez hesla pomocí hardwarového klíče. Podporuje YubiKey, Touch ID, Face ID, Windows Hello, Passkey.

Po přihlášení heslem systém vyžádá potvrzení pomocí zaregistrovaného klíče. I když heslo unikne — bez fyzického klíče nebo biometrie se nelze přihlásit.

Nastavení otevřete v postranní nabídce v sekci Klíče WebAuthn a klikněte na „Zaregistrovat klíč“. Zaregistrujte si rovnou dva klíče: pokud se jediný klíč ztratí nebo poškodí, přihlášení do panelu jím nebude možné.

WebAuthn funguje pouze přes HTTPS. Na spojení HTTP není registrace ani přihlášení klíčem dostupné.

06. Oznámení: Telegram, Email, webhook a push

Kanály jsou čtyři: Telegram, Email, webhook a push v prohlížeči. Jsou na sobě nezávislé — zapněte kterékoli, klidně všechny čtyři. Stejnými kanály chodí denní bezpečnostní zpráva, upozornění na zatížení i nálezy senzoru událostí; nastavují se jednou, zde, v sekci „Nastavení“.

Telegram. Potřebujete token bota a chat id:

  1. V Telegramu napište @BotFather → /newbot → dostanete token ve tvaru 123456:ABC....
  2. Napište svému novému botovi libovolnou zprávu (aby vám mohl odpovídat).
  3. Zjistěte své chat id: napište botovi @userinfobot, nebo otevřete https://api.telegram.org/bot<TOKEN>/getUpdates a najděte "chat":{"id":...}.
  4. Vložte token a chat id do „Nastavení“ → Telegram a klikněte na „Uložit a odeslat test“.

Email. Na výběr jsou dva způsoby v „Nastavení“ → Email:

  • SMTP — hostitel, port (465/SSL nebo 587/TLS), přihlašovací jméno a heslo vaší poštovní schránky;
  • Resend — moderní API: zadejte API klíč (re_...) a ověřenou doménu odesílatele.

Webhook. Jediná adresa přijímající POST pokryje Slack, Discord, Mattermost, n8n i vlastní obsluhu. „Nastavení“ → Webhook: vložte adresu a zapněte přepínač.

  • do Slacku a Mattermostu odchází {"text": …}, do Discordu {"content": …} (Discord odmítá zprávy delší než 2000 znaků, text se proto zkracuje);
  • každá jiná adresa dostane strukturovaný JSON: text, event, severity, source, count, host, ts — text zprávy není nutné znovu rozebírat.

Push oznámení. Zpráva přijde přímo do prohlížeče, a je-li panel přidaný na domovskou obrazovku telefonu, jako běžné oznámení aplikace — bez bota a bez poštovního serveru mezi tím. „Nastavení“ → Push oznámení: zapněte přepínač a na každém zařízení, které má oznámení dostávat, stiskněte „Připojit toto zařízení“. Počitadlo „Připojená zařízení“ ukazuje, kolik jich je.

Push funguje pouze přes HTTPS (stejně jako WebAuthn) a povolení je potřeba dvakrát: nejprve v prohlížeči — dotaz se objeví po stisknutí „Připojit toto zařízení“ — a poté v samotném operačním systému. Je-li ve Windows vypnutý hlavní přepínač Nastavení → Systém → Oznámení, prohlížeč povolení udělí, panel ohlásí odeslání a na obrazovce se přesto nic neobjeví. Totéž způsobí režim „Nerušit“ a vypnutá oznámení prohlížeče v macOS (Nastavení systému → Oznámení).
Každý kanál má vlastní tlačítko „Odeslat test“, které jej ihned ověří. Plán automatické zprávy zajišťuje cron (kapitola „Všechny cron úlohy“): cron spustí odeslání a kanály se berou z nastavení.

Stav hlášení: „POZOR“ nebo „OK“. Nadpis se změní na „POZOR“ jen při skutečném problému nebo čekající akci: nalezena hrozba ClamAV, změny souborů v AIDE, kritické události Falco (Emergency/Alert/Critical za posledních 24 h), spadlá služba v Monit, je nutný restart, vyprší SSL (≤14 dní) nebo čekají bezpečnostní aktualizace. Provozní šum — SSH pokusy o prolomení od botů, IP zabanované fail2ban, alerty Suricata, varování Lynis a už odražené požadavky ModSecurity — stav nezvyšuje, takže tato čísla v hlášení sama o sobě neznamenají „POZOR“.

07. Licence — zadání a aktivace

Podrobné moduly monitoringu (Lynis, UFW, ModSecurity, mapa útoků, AIDE, ClamAV aj.) se otevřou, pokud máte platnou licenci. Bez ní fungují dashboard, nastavení a účet, ale moduly zobrazují kartu „Vyžadována licence“.

Po nákupu v účtu máte aktivační kód ve tvaru ARCIVEO-XXXX-XXXX-XXXX-XXXX. Ten je potřeba „aktivovat“ na doménu vašeho panelu — tím se kód promění v podepsaný licenční soubor (blok [license]), který vložíte do panelu.

Jak aktivovat (3 kroky):

  1. Vezměte aktivační kód. Účet my.arciveo.com → sekce „Licence“ / „Aktivace licence“ — zkopírujte kód ARCIVEO-….
  2. Aktivujte kód na svou doménu. Tamtéž v účtu otevřete „Aktivace licence“, zadejte: aktivační kód, svůj e-mail a doménu panelu (adresa, na které se monitor otevírá, např. monitor.example.com). Klikněte na aktivovat — systém vygeneruje licenční soubor navázaný na tuto doménu a zobrazí jej v poli s tlačítkem „Kopírovat“.
  3. Vložte klíč do panelu. Zkopírujte celý text licence → v panelu otevřete „Nastavení“ → blok „Licence“, vložte a klikněte na „Uložit“. Moduly se okamžitě odemknou.

Panel klíč kryptograficky ověřuje: podpis, navázání na doménu a dobu platnosti.

Doména při aktivaci se musí přesně shodovat s adresou panelu. Vezměte ji z konstanty APP_URL v config.php a zadejte pouze název hostitele — bez https:// a bez prefixu www. Aktivace je jednorázová: kód se promění v licenci pro zadanou doménu a znovu se neaktivuje — při chybě v doméně klíč vašemu panelu nebude odpovídat a kód bude spotřebován. Doménu proto zadávejte pozorně.
Platnost vypršela nebo se změnila doména — v záhlaví panelu se objeví upozornění. Licence je navázaná na doménu natrvalo a na jinou doménu se nepřenáší: na nové období nebo novou doménu je potřeba nový klíč (kupuje se v účtu a aktivuje se jednorázově).

08. Soubor config.php — veškeré nastavení panelu

Všechny základní parametry panelu jsou uvedeny v jednom souboru config.php v kořenovém adresáři (vedle složky public/) jako běžné konstanty define(). Soubor se vytvoří při instalaci; upravovat ho ručně je potřeba jen zřídka — hlavně při změně domény, přenosu nebo připojení k jiné databázi. Po každé úpravě restartujte PHP-FPM (jinak se kvůli OPcache změny neuplatní).

Do zvýrazněných míst doplňte své hodnoty; zbytek nechte tak, jak je:

// --- Databáze --- define('DB_HOST', 'localhost'); // ponechat define('DB_NAME', 'db_name'); // co jste zadali při vytváření DB define('DB_USER', 'user'); // co jste zadali při vytváření DB define('DB_PASS', 'db_password'); // co jste zadali při vytváření DB define('DB_CHARSET', 'utf8mb4'); // ponechat // --- Aplikace --- define('APP_URL', 'https://monitor.example.com'); // adresa panelu, bez lomítka na konci define('TIMEZONE', 'Europe/Prague'); // vaše časové pásmo // --- Doba platnosti relace --- define('SESSION_LIFETIME', 28800); // nečinnost do opětovného přihlášení, s (28800 = 8 h)

Databáze. Údaje pro připojení k MySQL/MariaDB:

  • DB_HOST — hostitel databáze, téměř vždy localhost;
  • DB_NAME — název databáze panelu;
  • DB_USER — uživatel DB (přístup jen k vlastní databázi);
  • DB_PASS — heslo tohoto uživatele;
  • DB_CHARSET — kódování připojení, ponechte utf8mb4.

Aplikace.

  • APP_URL — úplná adresa panelu (např. https://monitor.example.com). Musí se shodovat s doménou, na kterou je licence aktivovaná — jinak bude klíč odmítnut (viz oddíl „Licence“);
  • TIMEZONE — časové pásmo PHP: ovlivňuje pouze to, jak panel zobrazuje datum a čas. Na dobu spuštění úloh cron nemá vliv — tam platí pásmo systému (viz „Všechny úlohy cron“).

Doba platnosti relace. SESSION_LIFETIME — časový limit nečinnosti relace v sekundách (plovoucí: obnovuje se při aktivitě). Výchozí hodnota 28800 = 8 hodin; po této době nečinnosti panel vyzve k opětovnému přihlášení. Například 3600 = 1 hodina, 86400 = den.

Protokolování chyb. Chyby se návštěvníkům nikdy nezobrazují, ale zapisují se do logs/php_errors.log — jsou vidět na stránce „Protokoly aplikace“. Tyto řádky (display_errors=0, log_errors=1, cesta error_log) obvykle není potřeba měnit — nastavení je zadáno přímo v souboru a nezávisí na php.ini.

config.php je tajný soubor. Obsahuje heslo k DB. Leží v kořenovém adresáři panelu (vedle public/) a webový kořen (DocumentRoot) tohoto panelu je právě kořen panelu, nikoli public/. Samotný soubor „neuniká“: v kořenovém .htaccess je pro něj nastaven výslovný zákaz (Require all denied) — server vrací 403. I bez tohoto pravidla by zdrojový kód neunikl: je to PHP — server ho vykonává, nevrací jako text. Pro jistotu: nezveřejňujte ho ve veřejných repozitářích a neposílejte ho podpoře se skutečným heslem. Oprávnění souboru — 640.
Při přenosu nebo obnovení přístupu je tento soubor hlavním zdrojem údajů: název DB, uživatel a heslo se berou právě odsud (viz oddíly „Aktualizace a přenos panelu“ a „Obnovení přístupu“).

09. API pouze pro čtení (JSON a Prometheus)

Panel je chráněn přihlášením heslem a, pokud je zapnutý, IP filtrem. Programu nevyhovuje ani jedno, proto mají externí systémy vlastní vstup — dvě adresy pouze pro čtení zabezpečené tokenem. Token na serveru nic nemění: dá se jím pouze získat ukazatele.

Zapnutí — „Nastavení“ → „API pouze pro čtení“: přepínač „Zapnout API“; token se vytvoří automaticky při prvním uložení. Tlačítko „Nový token“ vydá jiný a v tutéž chvíli odstřihne všechny, kdo používali předchozí.

  • /api/status.php — JSON: bezpečnostní skóre, stav modulů, poslední měření zatížení včetně nejnáročnějších procesů a bezpečnostní události za posledních 24 hodin;
  • /api/metrics.php — táž čísla v textovém formátu Prometheus (metriky arciveo_*: arciveo_security_score, arciveo_fail2ban_banned, arciveo_cpu_busy_pct a další).
curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/status.php curl -H "Authorization: Bearer <TOKEN>" https://monitor.example.com/api/metrics.php

Pokud váš klient neumí nastavit hlavičku, token se přijímá i jako parametr — ?token=…. Počítejte s tím, že v této podobě skončí v přístupovém logu webového serveru, hlavička je proto vhodnější.

Prometheus. Hotový blok pro scrape_configs:

scrape_configs: - job_name: arciveo metrics_path: /api/metrics.php scheme: https authorization: credentials: <TOKEN> static_configs: - targets: ['monitor.example.com']
Odpověď se ukládá do cache na 5 minut: za těmito čísly stojí totéž náročné dotazování nástrojů jako za nástěnkou. Časté dotazování tedy server nic nestojí — hodnoty se prostě opakují až do dalšího obnovení — ale interval kratší než minuta také nemá smysl.
401 — token je špatný nebo nebyl předán. 404 s textem api disabled — API je v nastavení vypnuté. Odmítnuté požadavky se zapisují do protokolu aplikace spolu s IP odesílatele, takže hádání tokenu je vidět na stránce „Protokoly aplikace“.

10. Přehled serverů v zákaznickém účtu

Panel se instaluje na každý server zvlášť a na otázku „jak se daří tomuto stroji“ odpovídá dobře. Na otázku „jak se daří všem mým strojům“ neodpovídá — proto může každý panel posílat krátký přehled do zákaznického účtu, kde jsou servery vidět v jednom seznamu.

Co si vzít v zákaznickém účtu my.arciveo.com → sekce „Moje servery“: vydává se tam token (ve tvaru fk_…) a je uvedena adresa příjemce https://my.arciveo.com/api/fleet.php. Token je jeden na účet — stejný pro všechny vaše servery.

Co nastavit v panelu — „Nastavení“ → „Přehled serverů“: adresa příjemce, token, název serveru (jak bude v seznamu podepsán; necháte-li prázdné, vezme se doména panelu) a přepínač „Posílat přehled“. Tlačítko „Odeslat nyní“ ověří spojení okamžitě, bez čekání na plán.

Dál přehled odchází cronem, každých 15 minut:

# každých 15 minut — přehled serveru do zákaznického účtu 3,18,33,48 * * * * /usr/local/bin/fleet-push-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Co přesně odchází: název a doména serveru, operační systém, doba běhu, verze PHP; bezpečnostní skóre; stav modulů (UFW, počet jailů Fail2ban, bany za dnešek, zda běží CrowdSec, Suricata a Falco, hrozby ClamAV, změny AIDE, index Lynis, čekající aktualizace, zda je nutný restart, dny do vypršení certifikátu, počet nebezpečně otevřených portů); poslední měření zatížení (load, CPU, RAM, disk, inody); počitadla událostí za posledních 24 hodin a poslední kritická událost. Protokoly, hesla ani obsah souborů přehled neobsahuje.

Posílá server, zákaznický účet se neptá. Do vaší sítě proto není třeba otevírat vstup zvenčí a panel uzavřený IP filtrem se hlásí také. Uzel se pozná podle domény panelu, seznam se tedy po restartu ani po změně IP nezdvojí.
Server označený v zákaznickém účtu jako mlčící znamená, že přehled dlouho nedorazil. Zkontrolujte popořadě: přepínač „Posílat přehled“, řádek cronu (sudo crontab -l) a co odpoví tlačítko „Odeslat nyní“. Chyby odesílání se zapisují do protokolu aplikace se značkou FLEET — tam je vidět, zda byl odmítnut token (HTTP 401), nebo zda vůbec nevzniklo spojení.

Bezpečnostní nástroje

11. Firewall UFW

UFW (Uncomplicated Firewall) — jednoduché rozhraní k nftables/iptables. Uzavře všechny příchozí porty kromě výslovně povolených. Stránka „Firewall UFW“ zobrazuje stav a pravidla.

sudo apt install ufw # Povolit SSH (nutně PŘED zapnutím!) a web sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Uzavřít DB zvenčí (přístup jen lokálně) sudo ufw deny 3306 # Zapnout a zkontrolovat sudo ufw enable sudo ufw status verbose
Před ufw enable nezapomeňte povolit SSH (ufw allow OpenSSH), jinak přijdete o přístup k serveru.
„Vnější expozice“ na dashboardu zohledňuje UFW: port uzavřený pravidlem deny se nepovažuje za dostupný zvenčí.
Skipping adding existing rule — to není chyba. UFW tím oznamuje, že přesně takové pravidlo už existuje, a znovu ho nepřidává. Při opakovaném spuštění automatického nastavení (je idempotentní) jde o běžné hlášení — není třeba na ně reagovat.

12. Instalace Fail2ban

Automaticky blokuje IP adresu po překročení počtu neúspěšných pokusů o přihlášení. Analyzuje logy SSH, nginx, Apache a dalších služeb.

sudo apt install fail2ban sudo systemctl enable --now fail2ban # Zkontrolovat stav: sudo fail2ban-client status
Funkční konfigurace (jail.local s desítkami jailů a automatickým banem z ipsum) — v následující sekci.

13. Funkční konfigurace Fail2ban + ipsum

Základní instalace je výše. Zde je funkční konfigurace, která dává desítky aktivních jailů a tisíce blokování: obecné nastavení, klíčové jaily a automatický ban škodlivých IP ze seznamu ipsum.

Soubor /etc/fail2ban/jail.local — obecné nastavení a nejdůležitější jaily:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # Progresivní ban: každé opakování je delší bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # trvalý ban za brute-force SSH findtime = 3600 # Recidivisté: kdo dostal několik banů — banuje se natrvalo [recidive] enabled = true logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = -1 findtime = 86400 maxretry = 2 [http-get-dos] enabled = true maxretry = 100 findtime = 300 bantime = 1w # Webové služby (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … a ostatní jaily podle služeb (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
Do ignoreip nezapomeňte zapsat svou IP a důvěryhodné sítě, jinak si můžete zablokovat sám sebe. Po úpravách: sudo fail2ban-client reload.

Automatické načítání blok-listu ipsum — do root cronu (sudo crontab -e): level 1 (100+ tisíc IP) se načítá do sady ipsum, která se odřezává na firewallu (podrobněji v sekci „Blok-list IPset“):

# 04:00 — aktualizace ipset ipsum (level 1, maximální pokrytí): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
Sada se musí jmenovat ipsum — právě ji čte dashboard (karta „IPset ipsum“). Úrovně: levels/1.txt — maximální pokrytí, levels/3.txt — přesnější (3+ zdroje).

Proč je „Monitor bezpečnosti“ rozdělen do dvou zón. Ochrana funguje na dvou úrovních a dashboard je nemíchá:

  • Reálné útoky (reaktivní) — vše, co zachytil fail2ban: živé pokusy o průnik (jaily sshd, apache-*, nginx-* apod.) a zlomyslní recidivisté (jail recidive — ti, kdo už byli několikrát zabanováni). Jsou to IP, které se k vám skutečně dobývaly — jsou na mapě útoků a na „Časové ose“.
  • Preventivní blokace (proaktivní) — veřejný blok-list známých škodlivých IP ipset ipsum, odřezávaný na firewallu pravidlem DROP. Tyto adresy se vašeho serveru z větší části ani nedotkly — jsou odříznuty předem; počítadlo „IPset ipsum“ ukazuje, kolik jich bylo preventivně odříznuto.

Rozdíl je jednoduchý: reaktivní — „tito zaútočili a dostali ban“, preventivní — „tito byli zablokováni ještě před pokusem“. Dříve se do recidive uměle nahnal list-3 ipsum (odtud staré dělení „seznamoví recidivisté“); nyní jsou v recidive jen skuteční recidivisté a prevence je celá na firewallu.

14. Blokovací seznam IPset (ipsum)

ipsum — veřejný seznam škodlivých IP, aktualizovaný denně. Monitor zobrazuje počet načtených adres na dashboardu a mapě útoků a zohledňuje jej ve Skóre bezpečnosti (−10, pokud sada není načtena).

Minimální varianta bez fail2ban — samostatná sada ipsum s blokováním přes iptables:

# Vytvořit sadu (jednou): sudo ipset create ipsum hash:ip # Aktualizační skript /usr/local/bin/update-ipsum.sh: #!/bin/bash ipset flush ipsum for ip in $(curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/3.txt); do ipset add ipsum "$ip" 2>/dev/null done iptables -C INPUT -m set --match-set ipsum src -j DROP 2>/dev/null \ || iptables -I INPUT -m set --match-set ipsum src -j DROP # Cron (sudo crontab -e, denně ve 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
Rozšířená varianta s fail2ban-recidive — v sekci „Funkční konfigurace Fail2ban + ipsum“.
ipset žije v paměti a při restartu se ztrácí. Samotný denní cron nechá sadu prázdnou od okamžiku restartu až do dalšího spuštění (dashboard ukáže 0). Načítejte sadu i při startu — přesuňte načítání do skriptu a navažte jej na @reboot. Zároveň příkaz create … -exist nastaví limit maxelem 300000 (výchozích 65536 — level 1 se nevejde, objeví se „Hash is full“):
# /usr/local/bin/load-ipsum.sh #!/bin/bash curl -s https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt \ | grep -v '^#' | sed 's/^/add ipsum /' \ | (echo "create ipsum hash:ip hashsize 131072 maxelem 300000 -exist"; echo "flush ipsum"; cat) \ | ipset restore -exist # sudo crontab -e — denně ve 04:00 A při každém startu: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
Jak to funguje při automatické instalaci. Skript načte celý seznam level 1 (100+ tisíc IP) do sady ipsum a pokud firewall spravuje instalátor (čistý VPS — profily „Plná“/„Odlehčená“), připojí sadu k UFW pravidlem DROP — provoz z těchto IP se reálně blokuje. Pravidlo je za ESTABLISHED,RELATED, takže stávající spojení (včetně vašeho SSH) se nepřeruší — blokují se jen nová připojení ze seznamu. Sada se obnovuje při spuštění služby ipsum-load.service před firewallem (jinak by se UFW nezvedl) a aktualizuje se cronem ve 04:00. Na již nakonfigurovaném serveru (panel, vlastní firewall) instalátor do firewallu nezasahuje — tam ipsum zůstává seznamem pro dashboard a mapu útoků a pravidlo DROP se v případě potřeby přidá ručně (minimální varianta s iptables … --match-set ipsum … -j DROP — výše). Při automatické instalaci není třeba nic dělat ručně.

15. Instalace CrowdSec

Moderní náhrada Fail2ban s kolektivní threat intelligence: bany od komunity plus vlastní pravidla. Pro aplikaci banů na firewall vyžaduje samostatný bouncer.

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash sudo apt install crowdsec sudo systemctl enable --now crowdsec # Bouncer pro iptables/nftables: sudo apt install crowdsec-firewall-bouncer-iptables # Kontrola stavu: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
Stav „Neběží“ v panelu = služba je nainstalována, ale není aktivní (monitor ji ověřuje přes systemctl is-active crowdsec). Spuštění: sudo systemctl enable --now crowdsec; při pádu se podívejte na sudo journalctl -u crowdsec -n 30. Totéž platí pro jakoukoli službu ve stavu „Neběží“ (Suricata, Falco, Monit, MySQL).
„0 scénářů“ nebo „0 bouncers“ na dashboardu. CrowdSec je po instalaci téměř prázdný — bez kolekcí nic nedetekuje a bez registrovaného bounceru se bany na firewall neaplikují. Doinstalujte základní kolekce a ověřte, že je bouncer v seznamu:
# Základní kolekce (Linux + SSH + webový server): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer musí být v seznamu a se stavem aktivního připojení: sudo cscli bouncers list
V logu bounceru stream halted / bany se neaplikují. Jde o osiřelý api-klíč: bouncer byl odstraněn z cscli bouncers list, ale jeho starý klíč zůstal v /etc/crowdsec/bouncers/*.yaml. Zaregistrujte bouncer znovu a zapište čerstvý klíč:
sudo cscli bouncers add fw-bouncer # vypíše nový api_key # zapište tento klíč do api_key: v /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml sudo systemctl restart crowdsec-firewall-bouncer
Automatická instalace (profil „Kompletní ochrana“) sama nainstaluje kolekce a zaregistruje firewall-bouncer — ručně je to potřeba jen při ruční instalaci nebo po ručním zásahu do CrowdSec.

16. Instalace AIDE

AIDE (Advanced Intrusion Detection Environment) vytvoří snímek souborového systému a při každé kontrole hlásí změny v /etc, /bin, /usr. Po instalaci je nutná inicializace databáze (aideinit).

sudo apt install aide # Inicializace databáze (5–15 minut): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: adresář /var/lib/aide se vytvoří v režimu 700 (vlastník _aide), # a panel (www-data) databázi nevidí → zobrazuje „Neinicializována“. # Otevřete adresář pro průchod (soubory databáze zůstávají 600): sudo chmod 755 /var/lib/aide # První kontrola SE ZÁPISEM do logu, který čte monitor. # Na Ubuntu/Debian aide vyžaduje explicitní --config (jinak „missing configuration“; # binárka aide.wrapper se v nových verzích nedodává): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Během aideinit terminál 5–15 minut stojí na řádku Running aide --init... — to je normální (hashování celého FS, zátěž disku). Nepřerušujte Ctrl+C. Pokud proces „visí“, ale nic nevypisuje — možná čeká na odpověď na skrytý dotaz Overwrite existing aide.db.new [Yn]? (stiskněte Y). Aktivitu ověříte z jiné relace: pgrep -af aide.
Chyba aideinit: „21_aide_spamassassin … printf: invalid number“ (return code 20) — známý bug konfiguračního snippetu AIDE v Ubuntu 22.04. Databáze se nevytvoří. Vyřaďte poškozený snippet a zopakujte:
sudo mv /etc/aide/aide.conf.d/21_aide_spamassassin /etc/aide/21_aide_spamassassin.disabled sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
Stavy na dashboardu. „Neinicializována“ = panel nevidí soubor databáze: buď se aideinit nespustil, nebo (Ubuntu 24.04) je adresář /var/lib/aide vytvořen v režimu 700 a nedostupný pro www-data — vyřeší sudo chmod 755 /var/lib/aide (viz blok výše). „Bez kontrol“ = databáze existuje, ale kontrola ještě neproběhla — to není chyba. Výsledky čte monitor z /var/log/aide/aide.log.
Pravidelná kontrola → log pro panel. Standardní /etc/cron.daily/aide na nových Ubuntu/Debian nemusí zapisovat /var/log/aide/aide.log v požadované podobě (a aide.wrapper v nich už není). Spolehlivější je přidat vlastní cron s explicitním --config — ten zapisuje log pod rootem v režimu 644 a monitor jej čte bez dalších skupin:
# sudo crontab -e — každodenní kontrola ve 02:00: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # Spustit hned, bez čekání na rozvrh: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Automatická instalace už tohle všechno dělá: chmod 755 /var/lib/aide a cron kontroly ve 02:00 — ručně není potřeba nic.
První inicializaci provádějte na čistém serveru — před instalací webových aplikací. Po legitimních změnách databázi znovu vytvořte: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.

17. Instalace ClamAV

Antivirový skener pro Linux. Zvlášť užitečný pro kontrolu /var/www na PHP shelly a škodlivý kód.

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # Aktualizovat databázi signatur: sudo freshclam # Prohledat složku ručně: sudo clamscan -r /var/www --infected
Démon clamd ukazuje „Neaktivní“ po enable --now? Tři typické příčiny:

1. V konfiguraci zůstal řádek Example — clamd se odmítá spustit, dokud tam je:

sudo sed -i '/^Example/d' /etc/clamav/clamd.conf sudo systemctl restart clamav-daemon

2. Není stažena databáze signatur — clamd se bez ní nespustí:

sudo systemctl stop clamav-freshclam sudo freshclam sudo systemctl start clamav-freshclam sudo systemctl restart clamav-daemon

3. Prostě se načítá — clamd nahrává ~8 mil. signatur do paměti 30–60 s. Počkejte a zkontrolujte: systemctl is-active clamav-daemon (stav activating → ještě nahrává).

Diagnostika: sudo journalctl -u clamav-daemon -n 30 --no-pager.
Na dashboardu „Zkontrolováno souborů: 0“ / „Poslední kontrola: —“? Démon clamd jen drží signatury v paměti, sám podle plánu nic neskenuje. Panel zobrazuje výsledky plánované kontroly, proto je potřeba cron, který skenuje a zapisuje log. Automatická instalace nasadí wrapper /usr/local/bin/clamav-scan.sh a cron v 01:30 — po prvním spuštění se doplní „Zkontrolováno souborů“ a „Poslední kontrola“. Spustit hned, bez čekání na plán: sudo /usr/local/bin/clamav-scan.sh.

18. Instalace Linux Malware Detect (maldet)

Linux Malware Detect (LMD) — skener škodlivého softwaru zaměřený na webové hrozby: PHP shelly, webové backdoory, downloadery. Využívá jádro ClamAV a doplňuje jej vlastními signaturami.

wget https://www.rfxn.com/downloads/maldetect-current.tar.gz tar -xzf maldetect-current.tar.gz dir=$(ls -d maldetect-*/ | head -1) && cd "$dir" && sudo bash install.sh && cd ~ rm -rf maldetect-* maldetect-current.tar.gz # Aktualizace signatur: sudo maldet -u # Skenovat /var/www: sudo maldet -a /var/www
LMD a ClamAV spolu fungují dobře v páru. Poslední report: maldet --report.
Při instalaci se může objevit řádek update-rc.d: error: unable to read /etc/init.d/maldet — je neškodný. maldet nepoužívá init.d, aktualizace signatur a skeny se spouští přes /etc/cron.daily/maldet. Pokud níže vidíte installation completed — vše se nainstalovalo.
Na stránce se u LMD píše „Nenainstalováno“, i když je nainstalován? maldet se neinstaluje přes apt, ale do /usr/local/maldetect, a při zapnutém open_basedir se jeho přítomnost ověřuje přes shell — viz sekce „Stránka je prázdná, i když data na serveru jsou“.

19. Instalace Suricata

Síťový systém detekce průniků: analyzuje provoz na úrovni paketů a zná tisíce signatur útoků. Doplňuje ModSecurity (ten pracuje na úrovni HTTP, Suricata na úrovni TCP/IP).

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # Stažení aktuálních pravidel: sudo suricata-update sudo systemctl enable --now suricata
Suricata je „Aktivní“, ale panel nezobrazuje výstrahy / počet událostí je 0? Suricata zapisuje /var/log/suricata/eve.json pod uživatelem root v režimu 750 na adresář a webový server (www-data) jej nemůže přečíst. Otevřete adresář pro průchod — soubory uvnitř zůstávají chráněné:
sudo chmod o+rx /var/log/suricata
Automatická instalace to provede sama — ručně to není potřeba.

20. Instalace Falco

Zachytává systémová volání přes eBPF/kernel module a odhaluje anomálie v reálném čase: shell z nginx, čtení /etc/passwd webovým procesem, zápis do /bin atd.

curl -fsSL https://falco.org/repo/falcosecurity-packages.asc > /tmp/falco.asc gpg --dearmor < /tmp/falco.asc | sudo tee /usr/share/keyrings/falco-archive-keyring.gpg > /dev/null sudo chmod 644 /usr/share/keyrings/falco-archive-keyring.gpg && rm /tmp/falco.asc echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://download.falco.org/packages/deb stable main" \ | sudo tee /etc/apt/sources.list.d/falcosecurity.list sudo apt update && sudo apt install falco sudo systemctl enable --now falco
Monitor čte události Falco přes journalctl -u falco (bez sudo — přes skupinu systemd-journal). Ujistěte se, že www-data je v této skupině — viz „Nastavení sudo“ (bod 2) na stránce ruční instalace.
„0 událostí za 24 hodin“ je normální stav, ne chyba. Falco je event-driven: mlčí, dokud je vše v pořádku, a událost zapíše jen při anomálii (shell z webového procesu, čtení /etc/passwd, zápis do systémových adresářů). Nula kritických událostí za den na klidném serveru je zdravý stav.
Pro panel je spolehlivější výstup do souboru. Čtení přes journalctl vyžaduje oprávnění k žurnálu; aby panel viděl události stabilně, automatická instalace zapíná u Falco file_output → /var/log/falco/falco.log a službě nastavuje UMask=0022 (log čte webový server). Při nové instalaci to není třeba nastavovat ručně.

21. Instalace ModSecurity (WAF)

ModSecurity — webový firewall (WAF) pro Apache nebo Nginx. Blokuje útoky na úrovni aplikace: SQL injection, XSS, průchod adresáři, skenery.

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # Sada pravidel OWASP Core Rule Set: sudo apt install modsecurity-crs # POVINNÉ: bez tohoto souboru je engine pravidel vypnutý sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf sudo apache2ctl configtest && sudo systemctl reload apache2 # Kontrola: musí vrátit 403 curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
Samotná instalace balíčku nic nechrání. Apache načítá konfigurace řádkem IncludeOptional /etc/modsecurity/*.conf, ale balíček dodává jen modsecurity.conf-recommended — pod masku *.conf nespadá. Pokud ho nezkopírujete do modsecurity.conf, zůstává SecRuleEngine na Off: modul je načtený, pravidla CRS jsou načtená, ale provoz se nekontroluje a audit log se nevytváří. Přechodný režim DetectionOnly pouze zapisuje události do logu, aniž by požadavky blokoval — panel ho zobrazuje žlutě.

Přístup panelu k audit logu. Log /var/log/apache2/modsec_audit.log patří rootovi (práva 640), webový uživatel jej nepřečte. Panel získává data přes obalovací skript — vytvořte jej:

sudo tee /usr/local/bin/monitor-modsec >/dev/null <<'EOF' #!/bin/sh echo "ENGINE=$(grep -hE '^SecRuleEngine[[:space:]]+' /etc/modsecurity/*.conf 2>/dev/null | tail -1 | awk '{print $2}')" echo "---LOG---" tail -n 3000 /var/log/apache2/modsec_audit.log 2>/dev/null echo "---RULES---" for f in /etc/modsecurity/crs/rules/*.conf /usr/share/modsecurity-crs/rules/*.conf /etc/modsecurity/custom-rules.conf; do [ -f "$f" ] && { echo "===FILE:$(basename "$f")==="; cat "$f"; } done EOF sudo chown root:root /usr/local/bin/monitor-modsec sudo chmod 755 /usr/local/bin/monitor-modsec # v /etc/sudoers.d/monitor (uživatel = ten, pod kterým běží PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
Obalovací skript bere poslední direktivu SecRuleEngine bez odsazení: odsazené řádky jsou uvnitř bloků <LocationMatch>/<Directory> (například vypnutí WAF pro phpMyAdmin) a globální režim neurčují.
Uživatel v sudoers se musí shodovat s uživatelem FPM poolu: na běžném Apache/Debianu je to www-data, v HestiaCP běží pool webu pod vlastníkem webu (například admin) — zkontrolujte grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
Pokud web stojí za Nginx proxy (HestiaCP), Apache vidí jako klienta samotnou proxy — panel bere reálnou IP adresu útočníka z hlavičky X-Forwarded-For. Do statistik se dostanou jen transakce s uplatněným pravidlem: direktiva SecAuditLogRelevantStatus zapisuje do audit logu jakékoli odpovědi 4xx/5xx, takže se tam dostanou i běžné 403/500 — panel je za události WAF nepovažuje.
Blok ---RULES--- potřebuje sekce „Všechna aktivní pravidla“ — panel zobrazuje nejen uplatněná, ale vůbec všechna načtená pravidla CRS + vlastní. Tři cesty v cyklu for f in … jsou typická místa pro pravidla CRS a lokální doplňky; pokud máte jiné rozložení (balíček ukládá soubory do svého adresáře, nebo vlastní pravidla neleží v /etc/modsecurity/custom-rules.conf), najděte reálné cesty příkazem sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null a doplňte je do seznamu. Pokud je obalovací skript starý (bez této sekce) — sekce jen zobrazí varování „nedostupné“, zbytek stránky funguje jako dříve.

22. Instalace Auditd

Auditd (Linux Audit Daemon) zaznamenává systémová volání na úrovni jádra: přihlášení a odhlášení, sudo příkazy, neúspěšné pokusy o autentizaci, změny souborů. Monitor zobrazuje dnešní přihlášení, neúspěšné pokusy a sudo příkazy.

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # Ověření stavu a událostí: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
Monitor čte události přes ausearch (/usr/sbin/ausearch) a v případě potřeby ze souboru /var/log/audit/audit.log příkazem tail. Oba musí být v sudoers.

23. Instalace Monit

Sleduje služby (nginx, php-fpm, mysql atd.) a při jejich pádu je restartuje. Umí posílat upozornění na e-mail.

sudo apt install monit sudo systemctl enable --now monit # Konfigurace: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
Monitor získává seznam služeb přes monit status. V souboru /etc/monit/monitrc musí být zapnuté HTTP rozhraní (blok set httpd s allow localhost), jinak monit status vrátí chybu.
Na dashboardu „0 sledovaných služeb“? Dvě příčiny. (1) HTTP rozhraní je vypnuté — v souboru monitrc je řádek set httpd zakomentovaný (výchozí podoba je # set httpd port 2812 …). Odkomentujte blok a povolte localhost. (2) Samotné zapnuté httpd nic nesleduje — Monit počítá jen to, co je popsáno v check stanzách; bez nich je seznam prázdný i při funkčním rozhraní. Minimální funkční konfigurace:
# /etc/monit/conf.d/00-httpd — HTTP rozhraní pro localhost: set httpd port 2812 use address localhost allow localhost # příklady check stanz (co sledovat): check process sshd with pidfile /run/sshd.pid start program = "/usr/bin/systemctl start ssh" stop program = "/usr/bin/systemctl stop ssh" check filesystem rootfs with path / if space usage > 90% then alert
sudo monit -t # ověřit syntaxi (Control file syntax OK) sudo systemctl reload monit sudo monit status
Automatická instalace vloží hotový conf.d s httpd na portu 2812 a sadou kontrol — na nové instalaci není potřeba nic nastavovat ručně.
Služba je ve stavu „S chybami“? Monitor pouze zobrazuje stav a záměrně nerestartuje služby z webového panelu (bylo by to vzdálené spouštění root příkazů v bezpečnostním panelu). Diagnostika a restart — přes SSH pomocí Monit:
sudo monit status <service> # příčina chyby sudo monit restart <service> # restart přes Monit # pokud Monit službu nespustí — podívejte se na její vlastní unit: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

24. Instalace PSAD (detekce skenování portů)

PSAD analyzuje protokol iptables a odhaluje skenování portů a síťové útoky, přičemž každému zdroji přiřadí úroveň hrozby (1–5). Doplňuje fail2ban a Suricata.

sudo apt install psad # PSAD čte log iptables — je potřeba zapnout logování (UFW to dělá samo). # Pro čisté iptables přidejte pravidla LOG do řetězců INPUT/FORWARD. sudo psad --sig-update sudo systemctl enable --now psad
Monitor čte data přes psad --Status (musí být v sudoers). Bez logování iptables bude stránka prázdná — to je normální, dokud neproběhlo žádné skenování.

25. AppArmor / SELinux (řízení přístupu)

Mandatory Access Control omezuje, k jakým souborům a prostředkům může program přistupovat, i když byl napaden. V Ubuntu/Debian se ve výchozím nastavení používá AppArmor (obvykle je již nainstalován a aktivní).

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # zkontrolovat profily
Monitor čte stav přes aa-status (musí být v sudoers). Zobrazuje počet profilů v režimu enforce/complain a procesy bez profilu.

„Načtených profilů“ je více než enforce + complain — to je v pořádku. V AppArmor 4.x (Ubuntu 24.04 a novější) přibyl režim unconfined: profil je načten v jádře, ale nic neomezuje. Ubuntu takto označuje desítky profilů pro programy využívající user namespaces (prohlížeče, torrentové klienty a podobně). Když takové profily existují, karta „Načtených profilů“ zežloutne a zobrazí jejich počet — například unconfined: 90 při 120 načtených a 26 v enforce. Reálně chrání jen profily v enforce; na Ubuntu 22.04 (AppArmor 3.x) tento režim není a čísla vždy sedí.

sudo aa-status | grep -E "profiles are" # rozdělení podle režimů sudo aa-enforce /etc/apparmor.d/profile-name # převést profil do enforce
Převádět do enforce profily, které Ubuntu záměrně ponechalo v unconfined, se vyplatí jen s rozmyslem: nejsou vypnuté omylem, ale proto, že jinak se naruší fungování samotných programů. Profily v complain jsou jiná věc: tam jsou pravidla už napsaná a jen se neuplatňují.

26. Instalace debsums (integrita balíčků)

debsums ověřuje, že soubory nainstalovaných balíčků odpovídají kontrolním součtům z repozitáře — odhalí podvržené systémové binárky (doplňuje AIDE). Úplná kontrola trvá 1–2 minuty, proto se spouští přes cron a panel čte výsledek z data/debsums/debsums.log a sám jej rozdělí do kategorií (podstatné jsou jen binárky a knihovny).

Úloha patří do root-cronu (sudo crontab -e). Hotový obal debsums-scan.sh se umístí do /usr/local/bin/ (chmod +x; viz přehled cron-úloh) a sám zapíše zprávu do data/debsums/ panelu.

sudo apt install debsums # Cron-řádek (denně 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Obal debsums-scan.sh si sám najde data/ panelu — cestu není třeba zadávat.

Změny v /etc/ (konfigurace) a /usr/share/ (zdroje) na serveru bývají obvykle v pořádku — panel je označí zvláštní barvou. Znepokojivé jsou změny binárek a knihoven (/bin, /sbin, /usr/lib apod.) — karta „Binárky / knihovny“ ukazuje právě je.

27. Nastavení reportů Lynis

Lynis se spouští ručně nebo přes cron. Report se musí ukládat do složky data/lynis/ projektu — monitor čte soubor lynis-report.dat.

# Jednorázové spuštění (doplňte vlastní cestu ke kořeni panelu): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # Denní audit — cron řádek (hotový wrapper lynis-scan.sh v /usr/local/bin/, viz přehled): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
Po prvním spuštění stránka „Audit Lynis“ ihned zobrazí hardening index, varování a doporučení.
Tlačítko „Spustit audit“ na stránce Lynis. Spustí lynis-scan.sh na pozadí přímo z panelu (bez čekání na cron): zobrazí „Skenování…“ a po dokončení samo aktualizuje report. K tomu potřebuje webový uživatel řádek v sudoers pro spuštění skriptu — instalátor jej přidá automaticky do /etc/sudoers.d/monitor. Pokud jste panel instalovali ručně/dříve, dopište jej týmž uživatelem, který už je v souboru uveden:
u=$(sudo awk '/NOPASSWD/ && !/lynis-scan/ {print $1; exit}' /etc/sudoers.d/monitor) [ -n "$u" ] && echo "$u ALL=(ALL) NOPASSWD: /usr/local/bin/lynis-scan.sh" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c && sudo chmod 440 /etc/sudoers.d/monitor

28. Nastavení reportů Logwatch

Logwatch musí ukládat denní reporty do složky data/logwatch/ projektu ve formátu .txt. Monitor zobrazuje poslední report a archiv.

# Denně (6:00) — cron-řádek (hotový wrapper logwatch_daily.sh v /usr/local/bin/, viz souhrn): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

Moduly panelu

29. Síťový monitor (vestavěný)

Síťový monitor nevyžaduje instalaci — je to vestavěná stránka panelu. Zobrazuje síťový stav serveru z lokálních zdrojů:

  • rozhraní a provoz — z /proc/net/dev;
  • stav linek (UP/DOWN) a IP — přes ip;
  • spojení a naslouchající porty — přes ss;
  • síťové události jádra za 24 h — přes journalctl -k.

První tři zdroje fungují bez sudo, takže rozhraní, provoz, spojení a porty jsou vidět ihned. Blok „Události jádra“ používá journalctl -k — čte se přes skupinu systemd-journal („Nastavení sudo“, bod 2), sudo není potřeba. Ověření, že vše je dostupné webovému uživateli:

# Kontrola pod uživatelem www-data (pod ním běží PHP): sudo -u www-data bash -c 'cat /proc/net/dev' sudo -u www-data bash -c 'ip -o link show' sudo -u www-data bash -c 'ss -s' sudo -u www-data journalctl -k --no-pager -n 5
Blok „Síťové události jádra“ zobrazuje události síťového zásobníku jádra (změna linky up/down, chyby nosné, „network unreachable“). Záznamy firewallu UFW BLOCK sem nepatří — jsou na stránkách „Brána firewall UFW“ a „Mapa útoků“. Prázdný blok se zeleným zaškrtnutím = za posledních 24 h nedošlo k žádnému síťovému výpadku.

30. Disk a SMART

Vestavěná stránka zobrazuje tři věci:

  • Souborové systémy — zaplnění oddílů (df); ukazatel zčervená při ≥90 %;
  • Úložiště — seznam disků (lsblk), pouze reálné (loop/snap jsou skryté);
  • Stav (SMART) — stav disku a atributy (smartctl).

Místo a seznam zařízení fungují ihned, bez nastavení. Pro SMART je potřeba balíček smartmontools. Webový proces nemá přímý přístup k diskovým zařízením, proto se SMART snímá přes cron do souboru data/disk/smart.txt a dashboard jej čte.

Úloha patří do root-cronu (sudo crontab -e). Hotový wrapper smart-scan.sh se umístí do /usr/local/bin/ (chmod +x; viz přehled cron-úloh) a sám zapisuje do data/disk/ dashboardu.

sudo apt install smartmontools # Cron-řádek (každých 30 minut): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Wrapper smart-scan.sh si sám najde data/ dashboardu — cestu není nutné zadávat. Uvnitř lsblk -e7,11 vylučuje loop/cdrom.

Na virtuálních discích (QEMU/KVM a podobných) je obvykle dostupný jen obecný stav „stav: OK“, zatímco teplota, hodiny provozu a přemapované sektory mohou být prázdné — to je normální. Na fyzickém serveru se zobrazují všechny atributy.

31. Výkon (CPU/RAM/Síť/Disk)

Stránka zobrazuje historii zatížení serveru za posledních 24 hodin — Load Average, vytížení CPU a čekání na I/O, RAM/Swap, síťový provoz (příjem/odesílání), diskové I/O (čtení/zápis), zaplnění disku a inodů, otevřené souborové deskriptory a MySQL připojení, plus aktuální počet TCP připojení a procesů. Výchozí je okno 24 hodin: tlačítka nahoře je přepnou na 7 dnů nebo 30 dnů.

Data sbírá cron/collect_metrics.php — jednou za 5 minut zapíše jeden „surový“ snímek čítačů (/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 tabulky DB system_metrics; procenta a rychlosti si stránka počítá sama z rozdílu mezi sousedními snímky (zaplnění disku/inodů/deskriptorů/MySQL připojení jsou okamžité hodnoty, bez přepočtu). Sudo není potřeba — zdroje se čtou bez práv roota.

Dvě hloubky uchovávání. „Surové“ pětiminutové snímky žijí jeden den (plus hodina rezervy, aby nejstarší bod grafu měl ještě předchůdce pro výpočet). Každá dokončená hodina se složí do jediného řádku; tato hodinová řada se uchovává 30 dnů a právě ji čtou pohledy „7 dnů“ a „30 dnů“. Měsíc historie tak stojí zhruba 720 řádků místo přibližně 8600.

V obdobích 7 a 30 dnů se zobrazují hodinové průměry, nikoli jednotlivá měření — pětiminutová špička se v tomto měřítku vyhladí a stránka na to upozorňuje. U Load Average uchovává hodinový řádek jak průměr, tak špičku hodiny, takže graf ukazuje obě čáry. Hned po aktualizaci jsou dlouhá období prázdná („pro toto období zatím není historie“) — hodinová řada se začne shromažďovat od té chvíle.
# Cron řádek (každých 5 minut): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Obal collect-metrics-all.sh (viz přehled cron úloh) sám najde všechny nainstalované instance panelu na serveru a spustí cron/collect_metrics.php každé z nich jménem vlastníka webu.

Dokud kolektor neproběhl alespoň dvakrát (prvních ~10 minut po instalaci), stránka zobrazuje „data se sbírají“ — grafy potřebují alespoň jednu dvojici sousedních bodů, aby mohly spočítat rychlosti a procenta.

Nejnáročnější procesy. Pod grafy jsou dvě tabulky s pěti procesy, které nejvíce vytěžují CPU:

  • „Procesy v posledním měření“ — co zatěžovalo server ve chvíli posledního snímku (čas je v záhlaví karty);
  • „Procesy ve špičce dne“ — týchž pět, ale z měření s nejvyšším Load Average za posledních 24 hodin. To je odpověď na otázku „co to bylo v noci“, když už špička v grafu dávno pominula.

Obě tabulky vždy popisují posledních 24 hodin, i když grafy ukazují měsíc: snímek procesů nesou pouze pětiminutové řádky a ty se neuchovávají déle než den.

Vlastní procesy měření (ps, PHP skript sběru a řetěz cron/sudo nad ním) se ze seznamu vylučují — jinak by stály v čele každého snímku: ps ve chvíli spuštění ukazuje téměř 100 % CPU. Ostatní cron úlohy spuštěné ve stejnou minutu se naopak objeví — přesně kvůli tomu tabulka existuje.

Upozornění na zatížení (sekce „Nastavení“ → „Upozornění na zatížení“) — při překročení prahu pro CPU/RAM/disk/inody pošle panel oznámení všemi zapnutými kanály (Telegram, Email, webhook, push — stejnými jako u denní zprávy; pro upozornění není třeba zapínat nic zvlášť) a další, jakmile se metrika vrátí do normálu. Dokud práh trvá, nespamuje: další oznámení přijde až po cyklu „vrátilo se do normálu → znovu překročeno“.

Prahy kontroluje tentýž collect_metrics.php při každém spuštění (jednou za 5 minut) — samostatný cron není potřeba. Stav „již upozorněno / ještě ne“ se ukládá do data/alerts_state.json, prahy — v nastavení panelu.

32. Bezpečnostní události (senzor každých 5 minut)

Denní zpráva odpovídá na otázku „jak se serveru daří“. Senzor odpovídá na jinou — „co se právě stalo“. Každých 5 minut se dotáže rychlých zdrojů a zaznamená jen to, co se od předchozí kontroly změnilo; stránka „Bezpečnostní události“ v nabídce zobrazuje seznam nálezů.

Pomalých kontrol — Lynis, debsums, aktualizace balíčků, platnost SSL — se senzor nedotýká: jejich čísla se stejně mění jednou denně a zůstávají v gesci denní zprávy.

Čeho si všímá — devět zdrojů:

  • Fail2ban — nové bany (porovnává se seznam zablokovaných adres, odblokování tedy událostí není a platný ban se hlásí přesně jednou);
  • CrowdSec — nová rozhodnutí;
  • Falco — události úrovně Emergency, Alert a Critical;
  • Suricata — nová hlášení; označení [Priority: 1] zvedá nález na kritický;
  • ClamAV — nové řádky FOUND v protokolu kontroly;
  • AIDE — změny souborů podle poslední kontroly (tedy ne častěji, než jak často sama běží podle svého plánu);
  • SSH — úspěšné přihlášení jako root (kritické) a přihlášení z adresy, která se dosud neobjevila (varování);
  • Ochranné služby — UFW, Fail2ban, CrowdSec, Suricata, Falco: jedna zpráva, když se služba zastaví, a jedna, když opět běží;
  • Porty — port, který se stal dostupným zvenčí; je-li za ním databáze nebo cache, jde o kritický nález.

Nástroj, který není nainstalovaný nebo jehož protokol panel nepřečte, prostě mlčí — to není chyba ani událost.

První kontrola nic neodesílá. Každý zdroj si drží značku „kam už se přečetlo“ (soubor data/secwatch_state.json) a první průchod jen tuto značku zapíše. Jinak by po zapnutí sledování přišlo oznámení o všem, co protokoly nasbíraly za měsíce.

Nastavení — „Nastavení“ → „Sledování událostí“:

  • Zapnout sledování — dokud je vypnuté, cron úloha běží naprázdno a seznam se neplní;
  • Oznamovat od — „Varování“ nebo „Kritické“. Nálezy pod prahem se do seznamu dostanou stejně, ale ne do oznámení;
  • Pauza, min — minimální odstup mezi oznámeními, výchozí hodnota 15;
  • Tiché hodiny — okno ve tvaru 23-7, kdy se varování neodesílají.
Kritické nálezy odcházejí okamžitě — nezdrží je ani pauza, ani tiché hodiny: právě kvůli nim senzor po 5 minutách existuje. Pojistka tu přesto je: nejvýše 6 oznámení za hodinu, pro případ, že by nějaký zdroj začal „blikat“.

Oznámení chodí stejnými kanály jako denní zpráva (Telegram, Email, webhook, push) — nic dalšího zapínat netřeba. Všechny nálezy se zapisují do seznamu bez ohledu na to, zda oznámení odešlo, a uchovávají se 90 dnů.

Seznam událostí. Filtry: období (24 hodin, 7, 30 nebo 90 dnů), závažnost a zdroj; zobrazuje se posledních 500 záznamů. Tlačítko „Zkontrolovat nyní“ spustí přesně tentýž průchod jako cron — hodí se hned po nastavení, abyste nečekali pět minut; uvede také důvod, když žádné oznámení neodešlo („pod prahem závažnosti“, „tiché hodiny“, „není nastaven žádný kanál oznámení“). Červené počitadlo u položky nabídky je počet kritických událostí za posledních 24 hodin.

Karta adresy. Kliknutí na řádek v seznamu událostí nebo v bloku Související adresy otevře vše, co je o jedné adrese známo: časovou osu jejích událostí, zemi a na prvním řádku závěr. Řádek seznamu otevře kartu, pokud se událost týká právě jedné adresy; je-li jich více, odkazem jsou samotné adresy uvnitř řádku. Závěry jsou čtyři:

  • Přístup možný — z adresy proběhlo úspěšné přihlášení a tatáž adresa byla zachycena i jinou ochranou, případně hned po přihlášení zareagovaly AIDE, ClamAV nebo se otevřel nový port. Jediný případ, který stojí za okamžitou kontrolu;
  • Přihlášení z této adresy — přihlášení je, nic jiného ne. Obvykle jde o vlastníka z nového místa, a proto se karta nebarví červeně;
  • Zablokována — adresa byla zachycena a zablokována: ochrana odvedla svou práci, není co dělat;
  • Vyžaduje kontrolu — detekce jsou, blokování nebylo. Pokud se adresa vrací, uzavřete ji ručně.

Pod časovou osou je blok Co se ve stejnou dobu dělo na serveru: události, které adresu vůbec nemají. AIDE neví, kdo soubor změnil, ClamAV neví, kdo přinesl nakažený. Zobrazeny jsou ty, které spadají do aktivity adresy a šesti hodin po ní. Právě spojení přihlášení s tím, co následovalo, odlišuje pokus od skutečného přístupu.

Souvislost se staví podle adresy. Útočník, který adresu mění, ji přetrhne. Karta ukazuje, co ochrany viděly, a nebere na sebe rozlišení průniku od vašeho vlastního přihlášení z nového místa.

Plán. Úloha patří do crontabu roota (sudo crontab -e), posunutá o 2 minuty oproti sběru metrik, aby obě nestartovaly zároveň:

# každých 5 minut — kontrola bezpečnostních událostí 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Spouštějte kontrolu jen přes wrapper, nikdy přímo přes php cron/security_watch.php. Wrapper najde všechny instalace panelu na serveru a spustí kontrolu jménem vlastníka webu — s přesně těmi právy sudo, která panel používá z webu. Přímé volání z crontabu roota by vytvořilo stavový soubor data/secwatch_state.json vlastněný root a tlačítko „Zkontrolovat nyní“ by přestalo fungovat.
Pokud jste server připravovali automatickou instalací, úloha už je přidaná — zbývá jen zapnout sledování v nastavení.

33. Webový server: požadavky a kódy odpovědí

Stránka „Webový server“ rozebírá přístupový log a ukazuje, kolik bylo požadavků, jaká část skončila chybou a kdo je posílal. ModSecurity odpovídá na otázku „co bylo zablokováno“, tato stránka na otázku „co vůbec na web přišlo“.

Co je vidět: počet požadavků, RPS, podíl chyb, samostatné počitadlo 5xx a objem odeslaných dat; graf požadavků po hodinách; rozložení kódů 2xx/3xx/4xx/5xx; časté adresy, časté IP, časté chyby (kód plus cesta) a klienty (User-Agent). Období: 24 hodin nebo 7 dnů.

Zdrojem je přístupový log ve formátu combined, hodí se tedy jak Nginx, tak Apache a žádný další modul není potřeba. Panel hledá log mezi standardními soubory:

  • /var/log/nginx/access.log
  • /var/log/apache2/access.log
  • /var/log/apache2/other_vhosts_access.log
  • /var/log/httpd/access_log

Kromě nich panel prohledává soubory *access*.log a *requests*.log v adresářích /var/log/nginx/, /var/log/apache2/ a /var/log/httpd/. Najde se tak i log, který web zapisuje do vlastního souboru direktivou CustomLog — například arciveo-monitor_requests.log, který vytváří instalátor Arcivéo.

Čte se jen jeden log: když Nginx stojí před Apache, sečtení dvou logů by počítalo každý požadavek dvakrát. Bere se první log ze seznamu výše, do kterého se zapisovalo za poslední den (soubory nalezené podle masky se zkoušejí po něm, od nejčerstvějších); pokud se za den nezapisovalo do žádného, bere se nejčerstvější neprázdný. Log vyprázdněný logrotate nebo zbylý po vypnutém webovém serveru proto nezakryje ten živý. Čte se poslední úsek logu (3 MB) a výsledek se ukládá do cache na 5 minut — na vytíženém webu proto zvolené období nemusí být pokryté celé; skutečný záběr je uveden nad grafem.

„Panel nemůže číst log webového serveru“. Příčinou jsou téměř vždy práva: logy i jejich adresář patří skupině adm a webový uživatel v ní není. Instalátor Arcivéo jej do této skupiny přidá; po ruční instalaci pomůže malý wrapper od roota, kterému je dovolena jediná věc — vypsat log (stránka ModSecurity funguje stejně). Wrapper vybírá log podle stejných pravidel jako panel. Příkaz se vypisuje přímo na stránce; zde je také. Vložte jej celý — jde o jediný příkaz:
sudo tee /usr/local/bin/monitor-weblog >/dev/null <<'EOF' && sudo chmod 755 /usr/local/bin/monitor-weblog && echo 'www-data ALL=(root) NOPASSWD: /usr/local/bin/monitor-weblog' | sudo tee /etc/sudoers.d/monitor-weblog >/dev/null && sudo visudo -c #!/bin/sh L="/var/log/nginx/access.log /var/log/apache2/access.log /var/log/apache2/other_vhosts_access.log /var/log/httpd/access_log $(ls -t /var/log/nginx/*access*.log /var/log/apache2/*access*.log /var/log/apache2/*requests*.log /var/log/httpd/*access_log 2>/dev/null)" for f in $L; do [ -r "$f" ] && [ -n "$(find "$f" -size +0 -mmin -1440 2>/dev/null)" ] && exec tail -c 3000000 "$f"; done for f in $(ls -t $L 2>/dev/null); do [ -r "$f" ] && [ -s "$f" ] && exec tail -c 3000000 "$f"; done EOF

Webový uživatel se může od www-data lišit — ověřte, pod kterým uživatelem běží PHP-FPM pool webu (ps -o user= -C php-fpm), a doplňte jej do řádku sudoers. Pokud název logu neobsahuje ani access, ani requests, doplňte jeho cestu na začátek řádku L=… uvnitř wrapperu.

„Pro zvolené období nejsou žádné záznamy“ — log byl přečten, ale nenašly se v něm odpovídající řádky: buď web skutečně nikdo neotevřel, nebo se log právě přetočil (logrotate) a začíná znovu.

Pokusy o známé exploity. Panel porovnává požadavky z logu se signaturami zhruba dvaceti rozšířených exploitů: PHP-CGI, průchod adresáři v Apache, PHPUnit, Log4Shell, chyby routerů, kamer a VPN bran. U každého pokusu odpoví, zda může na tomto serveru fungovat, a opírá se o fakta: nainstalované verze Apache a PHP, přítomnost Javy a kód, kterým server odpověděl na dotaz na soubor. Červeně je označeno jen to, co skutečně může fungovat.

Zabezpečení webového serveru. Panel se dotáže každého webu na serveru přes 127.0.0.1 a zjistí, co dostane návštěvník: zda je vidět verze webového serveru a PHP, zda je zapnutá metoda TRACE a zda jsou k dispozici ochranné hlavičky Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy a Content-Security-Policy. Weby se berou z adresy, na které je panel otevřen, a ze souborů virtuálních hostitelů, pokud je panel může číst. Výsledek se obnovuje každých 10 minut.

Pokud něco chybí, pod tabulkou se objeví jeden příkaz. Vytvoří samostatný soubor zz-arciveo-hardening.conf a webový server znovu načte až po úspěšném testu konfigurace; hlavičky, které web už posílá sám, se nezdvojují. CSP se nenabízí jako jeden řádek: zásady se sestavují pro konkrétní web, jinak přestane načítat vlastní skripty, styly a písma. Vrácení změny na Apache:

sudo a2disconf zz-arciveo-hardening && sudo systemctl reload apache2
Podpis na chybových stránkách (ServerSignature) se neoznačuje, pokud je verze webového serveru už skrytá: bez verze ukazuje jen název serveru a název hostitele.

34. Mapa útoků (GeoIP)

Stránka „Mapa útoků“ určuje zemi podle IP příkazem geoiplookup. Bez balíčku GeoIP se země neurčí a body se na mapě neobjeví:

sudo apt install geoip-bin geoip-database # Kontrola: geoiplookup 8.8.8.8
Sudo není potřeba — databázi /usr/share/GeoIP/GeoIP.dat čtou všichni, výsledky se ukládají do mezipaměti v tmp/geoip_cache.json. Samotná mapa (Leaflet + dlaždice OpenStreetMap) se načítá v prohlížeči — na počítači, kde je otevřený dashboard, je potřeba internet.

35. Vnější expozice, aktualizace a automatické aktualizace

Dvě vestavěné karty dashboardu, které nezobrazují „zap/vyp“ nástroje, ale skutečné zabezpečení serveru. Nevyžadují instalaci, čtou se lokálně bez sudo.

Vnější expozice — kolik služeb naslouchá na všech rozhraních (0.0.0.0/[::]) a je dostupných zvenčí. Zvýrazní červeně, pokud jsou navenek vystaveny databáze nebo cache (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — to je přímá díra (−10 ke Skóre zabezpečení). Zdroj: ss -tuln.

Pokud je karta červená — uzavřete databázi před vnějším světem: navažte ji na 127.0.0.1 (bind-address v konfiguraci MySQL/PostgreSQL, bind 127.0.0.1 v Redis) nebo zavřete port v UFW.
„Otevřený port“ ≠ „dostupný zvenčí“. Služba naslouchající na 127.0.0.1 (loopback) je viditelná jen samotnému serveru — zvenčí se k ní nedostanete, i když je port „otevřený“. Proto je Postfix na portu 25 navázaný na loopback bezpečný: automatické nastavení nastaví inet_interfaces = loopback-only (plus neutrální smtpd_banner — uzavírá poznámku Lynis MAIL-8818 o odhalení verze). Karta „Vnější expozice“ počítá jako vnější jen to, co naslouchá na 0.0.0.0/[::]; loopback služby se do ní nezahrnují.
Lynis MAIL-8818 ručně (pokud jste poštu nastavovali sami): v /etc/postfix/main.cf nastavte smtpd_banner = $myhostname ESMTP (bez verze a OS) a inet_interfaces = loopback-only, poté sudo systemctl restart postfix.

Bezpečnostní aktualizace — kolik bezpečnostních záplat čeká na instalaci a zda je po aktualizaci jádra potřeba restart (−5 ke Skóre zabezpečení, pokud jsou k dispozici záplaty). Zdroj: /usr/lib/update-notifier/apt-check, soubor /var/run/reboot-required. Podrobný seznam — na stránce „Bezpečnostní aktualizace“.

# Nainstalovat aktualizace: sudo apt update && sudo apt upgrade # Zkontrolovat, co naslouchá navenek: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
Karta aktualizací funguje na Ubuntu/Debian (update-notifier-common). Pokud apt-check chybí — monitor počítá záplaty přes apt-get -s upgrade.

Automatické bezpečnostní aktualizace (unattended-upgrades) — na stránce „Bezpečnostní aktualizace“ samostatná karta ukazuje, zda je zapnutá automatická instalace bezpečnostních záplat a kdy proběhla naposledy. Sudo není potřeba — stav se čte přes apt-config dump.

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # zapnout # Zkontrolovat, co je zapnuté: apt-config dump | grep Unattended-Upgrade

Údržba

36. Zálohování

Záloha je hlavní pojistka: ztráta dat je horší než jakýkoli průnik. Potřebujete dvě věci — zálohu serveru/webů a zvlášť zálohu databáze panelu (jsou v ní uživatelé, klíče WebAuthn, nastavení, licence).

Varianta A — HestiaCP: záložka Backup u uživatele → tlačítko vytvoření zálohy (nebo dle plánu v nastavení serveru). Záloha zahrnuje weby a jejich databáze.

Varianta B — ručně (cron): dump databáze + archiv adresáře data/ panelu:

# root-cron (sudo crontab -e) — denní záloha ve 2:30 (doplňte vlastní názvy/cesty): 30 2 * * * mysqldump -u root MY_DB | gzip > /var/backups/monitor-db-$(date +\%F).sql.gz 40 2 * * * tar czf /var/backups/monitor-data-$(date +\%F).tar.gz -C /path/to/monitor data # Mazat archivy starší než 14 dní: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
Záloha na tomtéž serveru vás ochrání před chybami, ale ne před ztrátou serveru. Kopírujte archivy na externí úložiště (jiný server, S3, rclone do cloudu). Ověřujte, že obnovení skutečně funguje.

37. Aktualizace a přenos panelu

Aktualizace na novou verzi. Nejprve si vytvořte zálohu. Poté znovu nahrajte soubory kódu a zachovejte svá data:

  • přepsat (kód): public/, includes/, assets/, cron/, database/ a také kořenové .htaccess (front-controller — směrování nelze ponechat ze staré verze), manifest.json, sw.js;
  • nesahat na: config.php (údaje k DB), data/ (reporty), logs/, tmp/ (relace a cache).
# Po nahrání — vyprázdnit cache PHP (pokud je zapnutý opcache): sudo systemctl reload php*-fpm
FileZilla hlásí SSH_FX_PERMISSION_DENIED — Permission denied. Soubory panelu patří uživateli www-data (tak byly nastaveny při instalaci), zatímco SFTP klient se připojuje pod vaším vlastním uživatelem, který nemá právo zápisu. Dát www-data celý panel „aby to fungovalo“ — právě to vede k této chybě; níže jsou tři způsoby, kterýkoli problém vyřeší.
# Varianta A (doporučeno) — rozdělit vlastníky: kód váš, pracovní složky webového serveru. # Webový server nezíská právo zápisu ke KÓDU panelu vůbec: sudo chown -R deploy:www-data /path/to/monitor sudo chown -R www-data:www-data /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo find /path/to/monitor -type d -exec chmod 755 {} \; sudo find /path/to/monitor -type f -exec chmod 644 {} \; sudo chmod 750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs sudo chmod 640 /path/to/monitor/config.php # Varianta B — ACL nad stávajícími vlastníky (nic nepřenášíme): sudo apt install -y acl sudo setfacl -R -m u:deploy:rwX /path/to/monitor sudo setfacl -R -d -m u:deploy:rwX /path/to/monitor # Varianta C — přes skupinu www-data. Jednodušší, ale právo zápisu k souborům # panelu získá i webový server (při zranitelnosti v PHP lze kód vyměnit): sudo usermod -aG www-data deploy sudo find /path/to/monitor -type d -exec chmod 2775 {} \; sudo find /path/to/monitor -type f -exec chmod 664 {} \; sudo chmod 640 /path/to/monitor/config.php sudo chmod 2750 /path/to/monitor/data /path/to/monitor/tmp /path/to/monitor/logs
Proč je varianta A bezpečná. Panel zapisuje jen do tří adresářů — data/ (reporty), tmp/ (relace a cache), logs/; ty zůstávají uživateli www-data. Zbytek je kód a webový server jej potřebuje jen ke čtení, které umožňuje skupina www-data s právy 644. Vedlejší výhoda: při zranitelnosti v PHP už soubory panelu nepřepíšete. Na hostingových panelech (HestiaCP a podobných) varianta A není potřeba: tam soubory webu tak jako tak patří účtu, pod kterým se přihlašujete přes SFTP, a webový server je čte přes skupinu.
Past varianty B: jakýkoli následný chmod na souborech resetuje ACL masku a přístup tiše zmizí. Pokud po „úklidu v právech“ nahrávání znovu narazí na Permission denied — zopakujte oba příkazy setfacl.
Bit 2 ve variantě C je setgid: soubory nahrané přes SFTP zůstávají ve skupině www-data, jinak je panel nedokáže přepsat. Po variantě C se ve FileZille připojte znovu — nová skupina se projeví až při novém přihlášení. Kontrola: id deploy (musí se objevit skupina www-data) a ls -ld /path/to/monitor (drwxrwsr-x — písmeno s znamená, že setgid je nastaven).

Přenos na jiný server:

  1. Na novém serveru zprovozněte web + HTTPS (viz stránka ruční instalace).
  2. Zkopírujte všechny soubory panelu spolu s config.php, data/.
  3. Přeneste DB: mysqldump na starém → import na novém; upravte údaje k DB v config.php.
  4. Zopakujte na novém serveru: sudoers, členství ve skupině adm, cron úlohy.
  5. Licence je vázaná na doménu — pokud je doména stejná, klíč bude fungovat dál.

38. Druhý web na tomto serveru (další doména)

Panel už běží a na témže serveru je potřeba ještě jeden web — s vlastní doménou vedle monitoru. Po automatickém nastavení je server běžný Apache + PHP-FPM, web tedy potřebuje tři věci: vlastní adresář, vlastní vhost a vlastní certifikát. Panelu se přitom nedotýkáme: sleduje celý server, druhá instance pro druhou doménu není potřeba.

Tato část platí pro server bez hostingového panelu. Pokud máte nainstalovaný HestiaCP nebo podobný panel, přidejte doménu v něm, ne ručně. A pokud plánujete mnoho webů (navíc s poštou), nainstalujte panel před automatickým nastavením: skript ho rozpozná a přepne se do aditivního režimu, zatímco panel nainstalovaný později přestaví konfiguraci Apache, firewallu a pošty.
Co v příkazech dosadit. site2.example.com je adresa nového webu. Může to být jak samostatná doména (mycompany.com), tak subdoména (shop.mycompany.com) — pro Apache v tom není rozdíl, liší se jen DNS záznam (krok 1) a vydání certifikátu (krok 5). site2 je jen krátký název webu: tak se jmenují adresář /var/www/site2 a konfigurační soubor site2.conf. S doménou nijak nesouvisí, Apache bere adresu výhradně z ServerName; název může být jakýkoli — pro shop.mycompany.com se například hodí shop: adresář /var/www/shop, konfigurace shop.conf.

1. DNS. V panelu DNS u registrátora domény vytvořte záznam A na IP tohoto serveru:

# Subdoména (shop.mycompany.com): Typ: A Jméno: shop Hodnota: 203.0.113.10 TTL: 3600 # Samostatná doména (mycompany.com) — dva záznamy, aby fungovala i adresa s www: Typ: A Jméno: @ Hodnota: 203.0.113.10 TTL: 3600 Typ: A Jméno: www Hodnota: 203.0.113.10 TTL: 3600

Za několik minut ověřte: dig +short site2.example.com musí vrátit IP serveru.

2. Adresář webu.

sudo mkdir -p /var/www/site2 sudo chown -R www-data:www-data /var/www/site2

3. Vhost. Blok se vkládá do terminálu celý — cesta k soketu PHP-FPM se zjistí sama:

PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # automatické zjištění soketu PHP-FPM sudo tee /etc/apache2/sites-available/site2.conf > /dev/null <<'EOF' <VirtualHost *:80> ServerName site2.example.com # Samostatná doména: odstraňte # z řádku níže, aby se web otevíral i s www. # Pro subdoménu tento řádek není potřeba. #ServerAlias www.site2.example.com DocumentRoot /var/www/site2 <Directory /var/www/site2> Options -Indexes +FollowSymLinks AllowOverride All Require all granted </Directory> <FilesMatch \.php$> SetHandler "proxy:unix:__PHPSOCK__|fcgi://localhost" </FilesMatch> ErrorLog ${APACHE_LOG_DIR}/site2_error.log CustomLog ${APACHE_LOG_DIR}/site2_access.log combined </VirtualHost> EOF sudo sed -i "s#__PHPSOCK__#${PHPSOCK}#" /etc/apache2/sites-available/site2.conf

4. Zapněte web a před znovunačtením ověřte konfiguraci:

sudo a2ensite site2.conf sudo apache2ctl configtest # očekáváno: Syntax OK sudo systemctl reload apache2

5. SSL. certbot už automatické nastavení nainstalovalo; DNS musí v tuto chvíli směřovat na server:

# Subdoména — jedna adresa: sudo certbot --apache -d site2.example.com # Samostatná doména — rovnou i s www (oba záznamy A z kroku 1 musí směřovat na server # a www musí být v ServerAlias, jinak certbot druhou adresu neověří): sudo certbot --apache -d site2.example.com -d www.site2.example.com

Třetí a další domény se přidávají stejně — zopakujte kroky 1–5 se změněnou doménou a adresářem.

Kdo odpovídá na „cizí“ požadavky. Pokud Host neodpovídá žádnému ServerName (přístup přes IP nebo cizí doména nasměrovaná na váš server), Apache vydá abecedně první zapnutý web z /etc/apache2/sites-enabled/. Standardní 000-default automatické nastavení vypíná, takže tuto „službu“ drží vhost panelu (arciveo-monitor.conf) — na weby otevírané pod vlastním jménem to nemá vliv. Pokud se má přes IP otevírat jiný web, pojmenujte jeho soubor tak, aby byl abecedně první (například 000-site2.conf).
Ochrana platí pro celý server: UFW, Fail2ban, CrowdSec, ModSecurity a Suricata už běží a nový web pokrývají automaticky, nastavovat je zvlášť není třeba. Porty 80/443 jsou také už otevřené. Web má vlastní logy: site2_error.log a site2_access.log v /var/log/apache2/.
Adresář nového webu neumisťujte dovnitř adresáře panelu — webový kořen panelu řídí vlastní .htaccess (front controller) a vnořený web by vracel něco jiného, než očekáváte. Držte weby vedle sebe: /var/www/monitor, /var/www/site2.

39. Obnovení přístupu (ztracený klíč, heslo, blok podle IP)

Pokud se nemůžete přihlásit — vše se opraví přímo v databázi na serveru. Otevřete databázi (název — z config.php):

sudo mysql MY_DB

Ztracený klíč WebAuthn (neprojde druhý faktor) — vypněte 2FA, přihlaste se heslem a zaregistrujte nový klíč:

UPDATE users SET webauthn_enabled = 0;

Zapomněli jste heslo — nastavte nový hash (vygenerujte ho na serveru a doplňte):

# Vygenerovat hash nového hesla: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # V databázi (vložte získaný hash): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

Zablokovali jste se IP filtrem — vypněte omezení:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
Přístup k databázi máte vždy: sudo mysql na serveru, nebo phpMyAdmin / sekce databází v panelu hostingu. Po obnovení znovu zapněte WebAuthn a IP filtr.

40. Všechny cron úlohy na jednom místě

Souhrn úloh je v root cronu serveru (přidávají se přes sudo crontab -e). Ponechte jen řádky nástrojů, které používáte; cesty upravte podle svého serveru.

# Serverový cron monitoru (root) — vložte přes: sudo crontab -e # 01:30 — sken ClamAV v nebezpečných cestách (web, home, temp) → karty „Zkontrolováno souborů“ a „Poslední skenování“ 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — kontrola integrity souborů AIDE (nutný explicitní --config) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # při startu — obnovit práva /var/lib/aide (balíčkový tmpfiles soubor # aide-common.conf je resetuje na 0700 a panel přestane vidět databázi) @reboot chmod 755 /var/lib/aide # 03:00 — bezpečnostní audit Lynis 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — aktualizace blokovacího seznamu ipsum (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # sadu ipsum při startu nahrává služba ipsum-load.service (PŘED firewallem, jinak # UFW sadu v before.rules neuvidí) — není to cron. Zde je jen denní refresh výše. # 06:00 — report Logwatch 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # každých 30 min — kontrola disků SMART */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — integrita balíčků debsums 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — plánovaný report na Email a Telegram 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # každou hodinu — obnova seznamů balíčků (pro kartu „Bezpečnostní aktualizace“) 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # každých 5 min — snímek zdrojů (CPU/RAM/síť/disk) pro stránku „Výkon“ */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # každých 5 min, posunuto oproti snímku výše — senzor bezpečnostních událostí: # nové bany, hlášení IDS, zastavená ochrana, otevřený port. # Dokud je sledování v nastavení vypnuté, úloha nedělá nic. 2-57/5 * * * * /usr/local/bin/security-watch-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # každých 15 min — přehled serveru do zákaznického účtu, aby bylo více serverů # vidět v jednom seznamu. Dokud je přehled vypnutý, úloha nedělá nic. 3,18,33,48 * * * * /usr/local/bin/fleet-push-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Podrobnosti ke každému najdete v příslušných sekcích. Zálohovací úlohy (předchozí sekce) se přidávají do stejného cronu. Po úpravách zkontrolujte: sudo crontab -l a že je služba cron aktivní.
Čas cronu = časové pásmo serveru, ne TIMEZONE z config.php. Konstanta TIMEZONE ovlivňuje jen PHP (jak panel zobrazuje data), ale cron démon spouští úlohy podle systémového času OS. Pokud se pásmo serveru neshoduje s vaším, report „08:00“ přijde v jinou dobu. Příklad: server je v jiném pásmu (Europe/London, UTC+1) a vy v Praze (UTC+2) → report „08:00“ vám přijde v 09:00 podle vás. Zkontrolujte a v případě potřeby srovnejte pásmo systému se svým:
# Zkontrolovat aktuální pásmo serveru: timedatectl # Nastavit své pásmo (příklad) a restartovat cron: sudo timedatectl set-timezone Europe/Prague sudo systemctl restart cron
Poté se řádek 0 8 * * * spustí v 08:00 místního času. Jinak byste museli posouvat samotný cron, ale při přechodu na zimní/letní čas by se posun zase rozešel — proto je správnější nastavit pásmo systému.
Hotové obalové skripty. Jejich pracovní kopie a vzor crontabu (crontab.txt) jsou ve složce system/ vedle projektu, mimo public_html. Toto není součást webu — do webového kořene je nahrávat netřeba; umístěte je na server podle systémových cest (jako v crontabu výše):
  • lynis-scan.sh → /usr/local/bin/ (chmod +x) — spouští lynis audit system, po dobu skenu nastaví příznak /tmp/lynis-running a zkopíruje lynis-report.dat do data/lynis/ panelu;
  • logwatch_daily.sh → /usr/local/bin/ (chmod +x) — vytváří denní report Logwatch (sshd, fail2ban, sudo, postfix) do data/logwatch/;
  • smart-scan.sh → /usr/local/bin/ (chmod +x) — snímá stav disků (smartctl) do data/disk/;
  • debsums-scan.sh → /usr/local/bin/ (chmod +x) — kontroluje integritu balíčků (debsums) do data/debsums/;
  • clamav-scan.sh → /usr/local/bin/ (chmod +x) — antivirový sken ClamAV v nebezpečných cestách (web, home, temp); zapisuje souhrn do /var/log/clamav/scan.log, odkud jej čte stránka ClamAV (řádek 01:30 v crontabu výše);
  • load-ipsum.sh → /usr/local/bin/ (chmod +x) — aktualizuje ipset sadu ipsum (level 1) na místě, aniž by narušil aktivní pravidla firewallu (řádek 04:00 v crontabu výše);
  • daily-report-all.sh → /usr/local/bin/ (chmod +x) — spouští report cron/daily_report.php panelu (řádek 08:00 v crontabu výše);
  • daily_report.php — už je součástí panelu (cron/daily_report.php), spouští se přes daily-report-all.sh, samostatně jej instalovat netřeba;
  • collect-metrics-all.sh → /usr/local/bin/ (chmod +x) — spouští cron/collect_metrics.php panelu (stránka „Výkon“, řádek */5 v crontabu výše); collect_metrics.php už je součástí panelu, samostatně jej instalovat netřeba;
  • security-watch-all.sh → /usr/local/bin/ (chmod +x) — spouští cron/security_watch.php panelu jménem vlastníka webu (stránka „Bezpečnostní události“, řádek 2-57/5 v crontabu výše); security_watch.php je již součástí panelu a není třeba jej instalovat zvlášť;
  • fleet-push-all.sh → /usr/local/bin/ (chmod +x) — posílá přehled serveru do zákaznického účtu prostřednictvím cron/fleet_push.php panelu (řádek 3,18,33,48 výše);
  • crontab.txt (system/cron/) — vzor úloh; potřebné řádky vložte přes sudo crontab -e.
Cesta ke skriptu v crontabu se musí shodovat s tím, kam jste jej umístili.
Jak umístit skript do /usr/local/bin/. Přímo z FileZilly tam zapsat nelze — adresář patří root a SFTP klient dostane SSH_FX_PERMISSION_DENIED. Postup je takový: nejprve nahrajte soubor do /tmp (tam zapisují všichni), poté jej přesuňte na místo jedním příkazem:
# ve FileZille: do pole „Vzdálený server“ zadejte /tmp a nahrajte tam skript, # poté přes SSH (install rovnou nastaví vlastníka a práva, chown/chmod netřeba): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # kontrola: soubor na místě, práva rwxr-xr-x, syntaxe v pořádku bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
Nezaměňte adresáře: potřebujete /tmp v kořeni serveru — ne /var/tmp ani tmp/ uvnitř samotného panelu (ten patří www-data a je pro vašeho uživatele uzavřený). Ve stromu FileZilly je /tmp větev nejvyšší úrovně, vedle var, ne uvnitř ní.
Instalovali jste server automatickým nastavením? Tyto obaly a jejich cron úlohy už jsou nainstalovány skriptem (v /usr/local/bin/, log — /var/log/arciveo-cron.log) — ručně není třeba nic dělat.
Kde skripty hledají panel. Obaly jsou doménově neutrální: instalace panelu najdou procházením /home/*/web/*/public_html a /var/www/* a reporty ukládají do jejich data/. Pokud panel leží na jiné cestě — přidejte ji do řádku for app in … uvnitř skriptů, jinak se reporty Lynis/SMART/debsums/Logwatch do panelu nedostanou.
cron.log a přístupová práva. Soubor logs/cron.log vytvoří první root cron — bude patřit root a záložka „Log cronu“ v panelu jej nebude moci přečíst ani vyčistit. Vytvořte soubor předem jménem webového uživatele (vlastník adresáře webu; na HestiaCP je to účet, např. admin) — pak bude root cron jen dopisovat, aniž by měnil vlastníka:
# vytvořit předem pod webovým uživatelem (před přidáním cron řádků): sudo -u OWNER touch /path/to/monitor/logs/cron.log # pokud cron.log už vytvořil root cron — předat webovému uživateli: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
Zjistit vlastníka adresáře: stat -c %U /path/to/monitor.
Správa z panelu. V sekci „Systém“ je stránka „Crontab“ — úlohy lze prohlížet a přidávat bez SSH. Panel edituje pouze úlohy přidané přes něj samotný (samostatný blok v root-crontabu označený servisními komentáři); vše, co už v crontabu je (seznam výše), se zobrazuje jako read-only seznam „Ostatní úlohy serveru“ s tlačítkem „Zkopírovat do editoru“ — to jen přenese rozvrh/příkaz do formuláře pro přidání, původní řádek nechá být. Chcete-li „převést“ existující úlohu pod správu panelu — zkopírujte ji do editoru, uložte, poté starý řádek smažte ručně (sudo crontab -e), jinak se bude provádět dvakrát.
Jednorázové nastavení na serveru. Stránka potřebuje privilegovaný obalový skript — ne holý sudo crontab (to by byla přímá eskalace na root pro každého, kdo získá přístup k relaci panelu), ale úzký skript se dvěma příkazy (list/set), který se dotýká jen svého bloku mezi servisními komentáři. Nainstalujte jednou:
sudo install -m 0755 -o root -g root /dev/stdin /usr/local/sbin/arciveo-cron <<'ARCIVEO_CRON_EOF' #!/bin/bash set -euo pipefail BEGIN='# >>> ARCIVEO-CRON-MANAGED (edited from the panel; do not edit by hand) >>>' END='# <<< ARCIVEO-CRON-MANAGED <<<' cmd=${1:-} case "$cmd" in list) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} list" >&2; exit 2; } crontab -l -u root 2>/dev/null || true ;; set) [ "$#" -eq 1 ] || { echo "usage: ${0##*/} set (body on stdin)" >&2; exit 2; } body=$(cat) if grep -qF "$BEGIN" <<<"$body" || grep -qF "$END" <<<"$body"; then echo "invalid body: markers not allowed" >&2; exit 2 fi current=$(crontab -l -u root 2>/dev/null || true) tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT { if grep -qF "$BEGIN" <<<"$current"; then awk -v b="$BEGIN" '{print} $0==b{exit}' <<<"$current" else [ -n "$current" ] && printf '%s\n' "$current" echo "$BEGIN" fi printf '%s\n' "$body" echo "$END" if grep -qF "$END" <<<"$current"; then awk -v e="$END" 'f{print} $0==e{f=1}' <<<"$current" fi } > "$tmp" crontab -u root "$tmp" ;; *) echo "usage: ${0##*/} <list|set>" >&2; exit 2 ;; esac ARCIVEO_CRON_EOF echo "www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/arciveo-cron" | sudo tee -a /etc/sudoers.d/monitor sudo visudo -c
Webový uživatel se může lišit od www-data — zkontrolujte, pod kým běží PHP-FPM pool webu (ps -o user= -C php-fpm), a doplňte jej do řádku sudoers.
Nový soubor se nahrál pod jiným vlastníkem — stránka odpovídá „Access denied.“. Pokud je soubor public/crontab_monitor.php nahrán přes FTP/SFTP pod jiným systémovým uživatelem (například root) než ostatní soubory webu, webový server jej nedokáže přečíst. Porovnejte vlastníka a práva se sousedním souborem a uveďte do souladu:
ls -la public/crontab_monitor.php public/ssl_monitor.php sudo chown OWNER:OWNER public/crontab_monitor.php sudo chmod 644 public/crontab_monitor.php

Diagnostika

41. Nástroj je nainstalován, ale zobrazuje se „Nenainstalováno“

Monitor zjišťuje přítomnost nástrojů pomocí dpkg-query — databáze balíčků APT. Pokud nástroj není nainstalován přes apt (ručně, ze snapu nebo ze zdrojových kódů), dpkg jej nevidí.

# Ověřit přes dpkg: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # Najít cestu k binárce: which ufw fail2ban-client auditctl # Test sudo z www-data: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

42. Řešení potíží (500, žádná data)

Chyba 500 — zkontrolujte logy PHP, nginx a samotného monitoru:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # Logy monitoru: tail -50 logs/monitor_$(date +%Y-%m-%d).log # Práva ke složkám: ls -la data/ tmp/ logs/
Dashboard na hostingovém panelu (HestiaCP, ISPmanager, cPanel)? Tam PHP neběží pod www-data, ale pod uživatelským účtem (např. admin — vlastník adresáře webu). Všechna sudo pravidla a členství ve skupinách (adm, systemd-journal) je nutné nastavit na tohoto uživatele, jinak moduly u běžících služeb zobrazí „Neaktivní / 0“. Reálného uživatele PHP zjistíte: ps -o user= -C php-fpm | sort -u nebo vlastníka adresáře webu stat -c '%U' /path/to/monitor. Dále ve všech příkazech níže jej dosaďte místo www-data. Automatická instalace webového uživatele určí sama a sudoers nastaví na něj.

Data se nezobrazují — téměř vždy jde o nenastavená sudo práva. Zkontrolujte konkrétní příkaz jménem webového uživatele (nahraďte www-data svým). Přepínač -n = bez hesla, stejně jako PHP — pokud vyžaduje heslo, pravidlo v sudoers chybí:

sudo -u www-data sudo -n fail2ban-client status sudo -u www-data sudo -n ufw status verbose sudo -u www-data sudo -n ipset list -t ipsum sudo -u www-data sudo -n /usr/sbin/ausearch -m USER_LOGIN -ts today sudo -u www-data sudo -n /usr/sbin/aa-status sudo -u www-data sudo -n /usr/sbin/psad --Status sudo -u www-data journalctl -u falco --no-pager -n 5
Modul hlásí „Neaktivní“ / „0“, ačkoli nástroj funguje (např. sudo aa-status v terminálu profily zobrazí, ale stránka „AppArmor“ — „Neaktivní“). Příčina: webový uživatel nemá sudo právo na příkaz tohoto modulu. Ověřte jej ze seznamu výše: pokud vyžaduje heslo — doplňte chybějící řádek do /etc/sudoers.d/monitor („Nastavení sudo“). Časté „nové“ příkazy: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
Pokud je konkrétní stránka (Falco, ModSecurity, Auditd, otevřené porty UFW) prázdná — porovnejte se seznamem v sekci o sudo: pravděpodobně není povolen apache2ctl, ausearch, aa-status nebo ss, případně webový uživatel není ve skupinách adm/systemd-journal (odtud se čtou logy fail2ban/auth/modsec a journalctl — Falco a události jádra).

43. Stránka je prázdná, i když data na serveru jsou

Příznak: na serveru data existují (přes shell jsou vidět), ale stránka zobrazuje „žádná data“ nebo špatný stav — například AIDE hlásí „Neinicializováno“, ačkoli databáze je vytvořena.

Příčinou je open_basedir: mnoho panelů a hostingů omezuje pool PHP-FPM na adresář domény, takže PHP funkce file_exists(), file_get_contents(), filemtime() jsou pro systémové cesty (/var/lib/aide, /var/log, /proc…) blokovány. Monitor to obchází tím, že takové cesty čte standardními systémovými příkazy (cat, test, stat).

# Je soubor vidět přes shell (takto ho čte monitor): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # Aktuální hodnota open_basedir pro pool domény: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
Pokud shell soubor „vidí“ (VISIBLE), ale stránka ne — jde o open_basedir. Správným řešením je čtení systémovými příkazy (u AIDE a Síťového monitoru už zavedeno). Rozšiřovat open_basedir na /var, /proc není potřeba a je to méně bezpečné.

44. SSL stránka nefunguje

Monitor kontroluje certifikáty připojením k doménám přímo přes port 443. Pokud je doména nedostupná ze samotného serveru nebo je port blokován firewallem, kontrola neproběhne.

# Ruční ověření certifikátu: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # Ověření dostupnosti: curl -I https://monitor.example.com
Domény monitor přebírá automaticky z konfigurací Nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) a Apache (/etc/apache2/sites-enabled/) plus aktuální host z HTTP_HOST.
Automatická detekce subdomén. Subdomény se zjišťují automaticky z veřejných logů Certificate Transparency a ověřují se po síti — i když jsou umístěny na jiných serverech. Ručně není třeba nic přidávat.

45. Z několika databází je vidět jen jedna

Monitor se připojuje k MySQL pod uživatelem z config.php, který má přístup jen ke své databázi. MySQL zobrazuje v information_schema pouze databáze s příslušnými oprávněními — proto ostatní nejsou vidět.

Aby monitor viděl všechny databáze, udělte tomuto uživateli oprávnění jen ke čtení (jednou pod root; doplňte jméno uživatele z config.php):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* uděluje jen oprávnění ke čtení — nic nelze změnit, smazat ani vytvořit, což je pro monitorování bezpečné.
Bez tohoto GRANT vidí dashboard jen svou databázi — není to chyba, ale omezení oprávnění. Žádný sudo mysql dashboard nepoužívá: seznam databází získává přes vlastní připojení PDO.

46. PostgreSQL se nezobrazuje na stránce „Databáze“

PostgreSQL vyžaduje přístup na úrovni uživatele postgres, kterého webový uživatel panelu nemá. Otevírat z PHP široký sudo psql není bezpečné — panel místo toho volá úzkou obálku bez parametrů, která pouze vypíše verzi, počet spojení a seznam databází s velikostmi. Vytvořte ji:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo Security Monitor - read-only PostgreSQL version, connections and per-database size sudo -u postgres psql -tAc "SELECT version();" | grep -oE 'PostgreSQL [0-9.]+' echo "---" sudo -u postgres psql -tAc "SELECT count(*) FROM pg_stat_activity;" echo "---" sudo -u postgres psql -tAc "SELECT datname || '|' || pg_size_pretty(pg_database_size(datname)) FROM pg_database WHERE datistemplate = false;" EOF sudo chown root:root /usr/local/bin/monitor-pgstat sudo chmod 755 /usr/local/bin/monitor-pgstat # v /etc/sudoers.d/monitor (uživatel = ten, pod kterým běží PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
Pokud PostgreSQL nepoužíváte — odeberte řádek monitor-pgstat ze sudoers (krok 13 ruční instalace) a samotný skript nevytvářejte: karta PostgreSQL zůstane jen neaktivní.

47. Spustil se alert — co dělat

Dashboard ukazuje, co se děje; níže je co dělat v typických situacích. Obecné pravidlo: nepanikařit, ověřit oproti legitimní aktivitě (vaše akce, aktualizace, zálohy) a reagovat podle závažnosti.

  • Mapa útoků / mnoho banů fail2ban — to je norma pro každý server v internetu (boti neustále zkoušejí SSH/web). Hlavní je, aby bany fungovaly. Ujistěte se, že přihlášení přes SSH je jen klíčem (heslo vypnuté) a vaše IP je v ignoreip.
  • ModSecurity zablokoval požadavky — WAF odráží útoky na web, to je jeho práce. Pokud se blokuje váš legitimní provoz (falešný poplach), najděte rule id v detailech a přidejte výjimku do konfigurace CRS.
  • AIDE: změněné soubory — porovnejte seznam s tím, co jste dělali (aktualizace balíčků, úpravy konfigurací jsou norma). Změny systémových binárek, kterých jste se nedotkli, jsou důvod ke zpozornění. Po legitimních změnách aktualizujte databázi AIDE.
  • debsums: změněné binárky/knihovny (mimo /etc, mimo /usr/share) — potenciální podvržení. Ověřte balíček: debsums PACKAGE_NAME, při pochybnostech ho přeinstalujte (apt install --reinstall).
  • ClamAV / maldet: nalezena hrozba — zkontrolujte soubor v karanténě, neotevírejte ho. Pokud jde o web shell v adresáři webu, izolujte server a hledejte vstupní bod (zranitelný plugin, únik přístupů).
  • Falco: kritické události (spuštění shellu v kontejneru, přístup k citlivým souborům) — rozeberte událost: čí proces, co spouštěl. Často jde o legitimní administrátorskou aktivitu.
  • Externí expozice: červeně databáze/cache — okamžitě uzavřete: navažte službu na 127.0.0.1 nebo zavřete port v UFW. To je reálná díra.
  • SSL vyprší / vypršel — obnovte certifikát (Let's Encrypt se obnovuje sám; pokud ne, zkontrolujte certbot renew nebo nastavení v dashboardu).
  • Čekají bezpečnostní aktualizace — nainstalujte: sudo apt update && sudo apt upgrade; po aktualizaci jádra server restartujte.
Známky skutečného průniku (neznámé procesy/uživatelé, změněné binárky, odchozí spam, neznámé cron úlohy): odpojte server od externího přístupu, pořiďte zálohu k analýze a pokud jsou data kritická, postavte čistý server z důvěryhodné zálohy — spolehlivě vyčistit rootkit je obtížné.