FAQ

Це посібник зі встановлення, налаштування та обслуговування Arcivéo Monitor. Розділи згруповано: загальний огляд, розгортання панелі, підключення інструментів безпеки, вбудовані модулі та діагностика. Команди можна копіювати кнопкою праворуч.

З чого почати

01. Встановлення панелі — оберіть спосіб

Встановлення панелі — на окремих покрокових сторінках. Оберіть спосіб:

Не впевнені — обирайте автоматичне. Цей довідник лишається єдиним джерелом щодо SSL, інструментів, cron та діагностики — install-сторінки посилаються на його розділи, нічого не дублюючи.

Огляд

02. Що таке Arcivéo Monitor

Arcivéo Monitor — панель безпеки сервера. Збирає дані від встановлених інструментів (Fail2ban, UFW, Lynis, ModSecurity, AIDE, ClamAV, Auditd, CrowdSec, Suricata, Falco та ін.) і відображає їх у єдиному інтерфейсі з дашбордом, картою атак і детальними сторінками для кожного інструмента.

Монітор не є активним засобом захисту — він не блокує атаки самостійно. Його завдання — агрегувати інформацію від уже працюючих інструментів і подати її у зручному вигляді.

03. Як монітор працює на сервері

Монітор працює лише локально — його потрібно встановити на тому самому сервері, який він моніторить. Жодного SSH чи віддаленого API немає.

Усі команди (fail2ban-client, ufw status, ipset list тощо) панель виконує від імені користувача вебсервера (зазвичай www-data, на хостинг-панелях — обліковий запис сайту) з вузьким набором прав sudo — лише на конкретні утиліти, без загального root-доступу. Результати парсяться та відображаються у браузері.

Для кількох серверів встановлюйте монітор на кожному окремо, з унікальним доменом.

04. Як обчислюється Оцінка безпеки

Оцінка починається з максимуму та знижується за кожну виявлену проблему:

  • UFW не активний — −30
  • Fail2ban не запущено (немає активних jail) — −25
  • Немає ключів WebAuthn — −15
  • Lynis hardening index < 60 — −20; 60–79 — −10
  • IPset ipsum не завантажено — −10
  • Загрози виявлено ClamAV — −20
  • Зміни файлів AIDE — −15
  • SSL прострочено — −30, спливає <14 днів — −15, <30 днів — −5
  • CrowdSec встановлено, але не запущено — −5
  • Suricata встановлено, але не запущено — −5
  • СУБД/кеш (MySQL, PostgreSQL, Redis…) доступні ззовні — −10
  • Дозволено вхід root через SSH (PermitRootLogin yes) — −20
  • Очікують встановлення security-оновлення — −5

Підсумок: 80+ = Захищено, 60–79 = Увага, <60 = Під загрозою.

Відрахування за ClamAV, AIDE, CrowdSec і Suricata застосовуються лише якщо інструмент встановлено. Lynis і AIDE без ініціалізованої бази показуються як «немає даних» і бал не знижують. Кількість атак за сьогодні виводиться на дашборді, але на Оцінку безпеки не впливає.

Налаштування та ліцензія

05. WebAuthn — двофакторна автентифікація

WebAuthn — стандарт автентифікації без пароля через апаратний ключ. Підтримує YubiKey, Touch ID, Face ID, Windows Hello, Passkey.

Після входу за паролем система запитує підтвердження через зареєстрований ключ. Навіть якщо пароль витече — без фізичного ключа чи біометрії увійти неможливо.

Для налаштування відкрийте Ключі WebAuthn у бічному меню та натисніть «Зареєструвати ключ». Зареєструйте одразу два ключі: якщо єдиний ключ загубиться або зламається, вхід у панель за ним буде неможливий.

WebAuthn працює лише через HTTPS. На HTTP-з'єднанні реєстрація та вхід за ключем недоступні.

06. Сповіщення: Telegram та Email

Панель може надсилати звіт безпеки в Telegram і на пошту (за кнопкою та за розкладом). Налаштовується в розділі «Налаштування».

Telegram. Потрібні токен бота та chat id:

  1. У Telegram напишіть @BotFather/newbot → отримайте токен виду 123456:ABC....
  2. Напишіть своєму новому боту будь-яке повідомлення (щоб він міг вам відповідати).
  3. Дізнайтеся свій chat id: напишіть боту @userinfobot або відкрийте https://api.telegram.org/bot<TOKEN>/getUpdates і знайдіть "chat":{"id":...}.
  4. Вставте токен і chat id у «Налаштування» → Telegram, натисніть «Зберегти й надіслати тест».

Email. Два способи на вибір у «Налаштування» → Email:

  • SMTP — хост, порт (465/SSL або 587/TLS), логін і пароль вашої поштової скриньки;
  • Resend — сучасний API: вкажіть API-ключ (re_...) та підтверджений домен відправника.
Кнопка «Надіслати тест» одразу перевірить канал. Розклад автоматичного звіту — через cron (розділ «Усі cron-завдання»): він викликає надсилання, а канали беруться з налаштувань.

Статус звіту: «УВАГА» або «ОК». Заголовок стає «УВАГА» лише за реальної проблеми чи дії, що очікує: знайдено загрозу ClamAV, зміни файлів в AIDE, критичні події Falco (Emergency/Alert/Critical за останні 24 год), впалий сервіс у Monit, потрібне перезавантаження, спливає SSL (≤14 днів) або чекають security-оновлення. Фоновий шум — SSH-перебори ботів, забанені fail2ban IP, алерти Suricata, попередження Lynis та вже відбиті запити ModSecurity — статус не піднімає, тож такі цифри у звіті самі по собі не означають «УВАГА».

07. Ліцензія — введення та активація

Детальні модулі моніторингу (Lynis, UFW, ModSecurity, карта атак, AIDE, ClamAV та ін.) відкриваються за наявності чинної ліцензії. Без неї дашборд, налаштування та акаунт працюють, а модулі показують картку «Потрібна ліцензія».

Після придбання в кабінеті у вас є код активації вигляду ARCIVEO-XXXX-XXXX-XXXX-XXXX. Його потрібно «активувати» на домен вашої панелі — це перетворить код на підписаний ліцензійний файл (блок [license]), який ви вставляєте в панель.

Як активувати (3 кроки):

  1. Візьміть код активації. Особистий кабінет my.arciveo.com → розділ «Ліцензії» / «Активація ліцензії» — скопіюйте код ARCIVEO-….
  2. Активуйте код на свій домен. Там же в кабінеті відкрийте «Активація ліцензії», введіть: код активації, ваш email і домен панелі (адреса, за якою відкривається монітор, напр. monitor.example.com). Натисніть активувати — система згенерує ліцензійний файл, прив'язаний до цього домену, і покаже його в полі з кнопкою «Копіювати».
  3. Вставте ключ у панель. Скопіюйте весь текст ліцензії → у панелі відкрийте «Налаштування» → блок «Ліцензія», вставте і натисніть «Зберегти». Модулі розблокуються одразу.

Панель перевіряє ключ криптографічно: підпис, прив'язку до домену та термін дії.

Домен під час активації має точно збігатися з адресою панелі. Візьміть його з константи APP_URL у config.php і введіть лише ім'я хоста — без https:// і без префікса www. Активація одноразова: код перетворюється на ліцензію для введеного домену і повторно не активується — за помилки в домені ключ не підійде вашій панелі, а код буде витрачено. Тому вводьте домен уважно.
Термін минув або змінився домен — у шапці панелі з'явиться попередження. Ліцензія прив'язана до домену назавжди і на інший домен не переноситься: на новий термін чи новий домен потрібен новий ключ (купується в кабінеті й активується одноразово).

08. Файл config.php — усі налаштування панелі

Усі основні параметри панелі задано в одному файлі config.php у корені (поряд із текою public/) звичайними константами define(). Файл створюється під час встановлення; правити його вручну потрібно рідко — переважно при зміні домену, перенесенні чи підключенні до іншої бази. Після будь-якої правки перезапустіть PHP-FPM (інакше через OPcache зміни не застосуються).

Підставте свої значення у підсвічені місця; решту залиште як є:

// --- База даних --- define('DB_HOST', 'localhost'); // залишити define('DB_NAME', 'db_name'); // що задали при створенні БД define('DB_USER', 'user'); // що задали при створенні БД define('DB_PASS', 'db_password'); // що задали при створенні БД define('DB_CHARSET', 'utf8mb4'); // залишити // --- Застосунок --- define('APP_URL', 'https://monitor.example.com'); // адреса панелі, без слеша в кінці define('TIMEZONE', 'Europe/Kyiv'); // ваш часовий пояс // --- Час сесії --- define('SESSION_LIFETIME', 28800); // простій до повторного входу, сек (28800 = 8 год)

База даних. Реквізити підключення до MySQL/MariaDB:

  • DB_HOST — хост СУБД, майже завжди localhost;
  • DB_NAME — ім'я бази даних панелі;
  • DB_USER — користувач БД (доступ лише до своєї бази);
  • DB_PASS — пароль цього користувача;
  • DB_CHARSET — кодування з'єднання, залиште utf8mb4.

Застосунок.

  • APP_URL — повна адреса панелі (напр. https://monitor.example.com). Має збігатися з доменом, на який активовано ліцензію — інакше ключ буде відхилено (див. розділ «Ліцензія»);
  • TIMEZONE — часовий пояс PHP: впливає лише на те, як панель показує дати й час. На час запуску cron-завдань не впливає — там діє пояс системи (див. «Усі cron-завдання»).

Час сесії. SESSION_LIFETIME — таймаут простою сесії в секундах (ковзний: оновлюється при активності). Типово 28800 = 8 годин; після цього часу бездіяльності панель попросить увійти знову. Наприклад, 3600 = 1 година, 86400 = доба.

Журналювання помилок. Помилки ніколи не показуються відвідувачам, а записуються у logs/php_errors.log — їх видно на сторінці «Логи застосунку». Ці рядки (display_errors=0, log_errors=1, шлях error_log) зазвичай змінювати не потрібно — налаштування задано прямо у файлі й не залежать від php.ini.

config.php — секретний файл. У ньому пароль БД. Лежить він у корені панелі (поряд із public/), а в цієї панелі вебкорінь (DocumentRoot) — саме корінь панелі, не public/. Сам по собі файл не «витікає»: у кореневому .htaccess для нього стоїть явна заборона (Require all denied) — сервер повертає 403. Навіть без цього правила вихідник не витік би: це PHP — сервер його виконує, а не віддає текстом. Про всяк випадок: не викладайте його в публічні репозиторії й не передавайте у підтримку з реальним паролем. Права на файл — 640.
При перенесенні чи відновленні доступу цей файл — головне джерело реквізитів: ім'я БД, користувач і пароль беруться саме звідси (див. розділи «Оновлення та перенесення панелі» і «Відновлення доступу»).

Інструменти безпеки

09. Брандмауер UFW

UFW (Uncomplicated Firewall) — простий інтерфейс до nftables/iptables. Закриває всі вхідні порти, крім явно дозволених. Сторінка «Брандмауер UFW» показує стан і правила.

sudo apt install ufw # Дозволити SSH (обов'язково ДО ввімкнення!) і веб sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Закрити БД ззовні (доступ лише локально) sudo ufw deny 3306 # Увімкнути і перевірити sudo ufw enable sudo ufw status verbose
Перед ufw enable обов'язково дозвольте SSH (ufw allow OpenSSH), інакше втратите доступ до сервера.
«Зовнішня експозиція» на дашборді враховує UFW: порт, закритий правилом deny, не вважається доступним ззовні.
Skipping adding existing rule — це не помилка. UFW так повідомляє, що точно таке правило вже є, і повторно його не додає. Під час повторного запуску автоналаштування (воно ідемпотентне) це штатне повідомлення — реагувати не потрібно.

10. Встановлення Fail2ban

Автоматично блокує IP після перевищення кількості невдалих спроб входу. Аналізує логи SSH, nginx, Apache та інших сервісів.

sudo apt install fail2ban sudo systemctl enable --now fail2ban # Перевірити статус: sudo fail2ban-client status
Робоча конфігурація (jail.local з десятками jail'ів та автобаном з ipsum) — у наступному розділі.

11. Робоча конфігурація Fail2ban + ipsum

Базове встановлення — вище. Тут — робоча конфігурація, що дає десятки активних jail та тисячі блокувань: загальні налаштування, ключові jail і автобан шкідливих IP зі списку ipsum.

Файл /etc/fail2ban/jail.local — загальні налаштування та найважливіші jail:

[DEFAULT] bantime = 1w findtime = 900 maxretry = 3 backend = systemd banaction = nftables-multiport ignoreip = 127.0.0.1/8 ::1 <YOUR_IP> <TRUSTED_NETS> # Прогресивний бан: кожен повтор — довше bantime.increment = true bantime.factor = 2 bantime.maxtime = 5w bantime.rndtime = 300 [sshd] enabled = true maxretry = 5 bantime = -1 # перманентний бан за брутфорс SSH findtime = 3600 # Рецидивісти: хто отримав кілька банів — баниться назавжди [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 # Веб-сервіси (apache-*, nginx-*, php-url-fopen, phpmyadmin-syslog): [nginx-http-auth] enabled = true port = http,https [apache-badbots] enabled = true port = http,https # … та решта jail за сервісами (dovecot, exim, postfix-sasl, # mysqld-auth, vsftpd, portscan, pam-generic) — enabled = true
У ignoreip обов’язково впишіть свій IP та довірені мережі, інакше можна забанити самого себе. Після правок: sudo fail2ban-client reload.

Автозавантаження блок-листа ipsum — до root-крону (sudo crontab -e): level 1 (100+ тисяч IP) вантажиться в набір ipsum, який відсікається на файрволі (докладніше — у розділі «Блок-лист IPset»):

# 04:00 — оновлення ipset ipsum (level 1, максимальне охоплення): 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1
Набір повинен називатися ipsum — саме його читає дашборд (картка «IPset ipsum»). Рівні: levels/1.txt — максимальне охоплення, levels/3.txt — точніше (3+ джерела).

Чому «Монітор безпеки» поділено на дві зони. Захист працює на двох рівнях, і дашборд їх не змішує:

  • Реальні атаки (реактив) — усе, що зловив fail2ban: живі спроби зламу (jail sshd, apache-*, nginx-* тощо) та злісні рецидивісти (jail recidive — ті, кого вже банили кілька разів). Це IP, які реально до вас ломилися — вони на карті атак і «Часовій шкалі».
  • Превентивний блок (проактив) — публічний блок-лист відомих шкідливих IP ipset ipsum, що відсікається на файрволі правилом DROP. Ці адреси здебільшого вашого сервера й не торкалися — їх ріжуть заздалегідь; лічильник «IPset ipsum» показує, скільки відсічено превентивно.

Різниця проста: реактив — «ці атакували й отримали бан», превентив — «цих заблокували ще до спроби». Раніше в recidive штучно заганявся list-3 ipsum (звідси старий поділ «спискові recidive»); тепер recidive — лише справжні рецидивісти, а превентив цілком на файрволі.

12. Блок-список IPset (ipsum)

ipsum — публічний список шкідливих IP, що оновлюється щодня. Монітор показує кількість завантажених адрес на дашборді та карті атак і враховує її в Оцінці безпеки (−10, якщо набір не завантажено).

Мінімальний варіант без fail2ban — окремий набір ipsum з блокуванням через iptables:

# Створити набір (один раз): sudo ipset create ipsum hash:ip # Скрипт оновлення /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, щодня о 4:00): 0 4 * * * /usr/local/bin/update-ipsum.sh
Розширений варіант із fail2ban-recidive — у розділі «Робоча конфігурація Fail2ban + ipsum».
ipset зберігається в пам'яті й губиться під час перезавантаження. Лише щоденний крон залишить набір порожнім із моменту перезавантаження до наступного запуску (дашборд покаже 0). Завантажуйте набір ще й під час старту — винесіть завантаження в скрипт і повісьте на @reboot. Заразом команда create … -exist задає ліміт maxelem 300000 (за замовчуванням 65536 — level 1 не вміщується, буде «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 — щодня о 04:00 І під час кожного старту: 0 4 * * * /usr/local/bin/load-ipsum.sh @reboot sleep 60 && /usr/local/bin/load-ipsum.sh
Як це влаштовано при автовстановленні. Скрипт завантажує повний список level 1 (100+ тисяч IP) у набір ipsum і, якщо файрволом керує інсталятор (свіжий VPS — профілі «Повна»/«Полегшена»), підключає набір до UFW правилом DROP — трафік із цих IP реально блокується. Правило стоїть після ESTABLISHED,RELATED, тому поточні з'єднання (зокрема ваш SSH) не розриваються — ріжуться лише нові підключення зі списку. Набір відновлюється під час завантаження сервісу ipsum-load.service до файрвола (інакше UFW не піднявся б) та оновлюється кроном о 04:00. На вже налаштованому сервері (панель, власний файрвол) інсталятор у файрвол не втручається — там ipsum залишається списком для дашборда й карти атак, а правило DROP за бажанням додається вручну (мінімальний варіант з iptables … --match-set ipsum … -j DROP — вище). При автовстановленні вручну робити нічого не потрібно.

13. Встановлення CrowdSec

Сучасна заміна Fail2ban з колективним threat intelligence: блокування від спільноти плюс власні правила. Потребує окремого 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 для iptables/nftables: sudo apt install crowdsec-firewall-bouncer-iptables # Перевірити статус: sudo systemctl status crowdsec sudo cscli decisions list sudo cscli bouncers list
Статус «Не запущено» на панелі = сервіс встановлено, але службу не активовано (монітор перевіряє її через systemctl is-active crowdsec). Запустити: sudo systemctl enable --now crowdsec; у разі збою дивіться sudo journalctl -u crowdsec -n 30. Те саме правило для будь-якого сервісу зі статусом «Не запущено» (Suricata, Falco, Monit, MySQL).
«0 сценаріїв» або «0 bouncers» на дашборді. CrowdSec з коробки постачається майже порожнім — без колекцій він нічого не виявляє, а без зареєстрованого bouncer'а блокування не застосовуються до фаєрвола. Доставте базові колекції та переконайтеся, що bouncer у списку:
# Базові колекції (Linux + SSH + веб-сервер): sudo cscli collections install crowdsecurity/linux crowdsecurity/sshd crowdsecurity/base-http-scenarios sudo systemctl reload crowdsec # Bouncer має бути у списку та зі статусом активного підключення: sudo cscli bouncers list
У лозі bouncer'а stream halted / блокування не застосовуються. Це осиротілий api-ключ: bouncer було видалено з cscli bouncers list, але його старий ключ залишився в /etc/crowdsec/bouncers/*.yaml. Перереєструйте bouncer і пропишіть свіжий ключ:
sudo cscli bouncers add fw-bouncer # виведе новий api_key # впишіть цей ключ у api_key: в /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml sudo systemctl restart crowdsec-firewall-bouncer
Автовстановлення (профіль «Повний захист») саме встановлює колекції та реєструє firewall-bouncer — вручну це потрібно лише при ручному встановленні або після ручного втручання в CrowdSec.

14. Встановлення AIDE

AIDE (Advanced Intrusion Detection Environment) створює знімок файлової системи й під час кожної перевірки повідомляє про зміни в /etc, /bin, /usr. Після встановлення обов'язкова ініціалізація бази (aideinit).

sudo apt install aide # Ініціалізація бази (5–15 хвилин): sudo aideinit sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db # Ubuntu 24.04: каталог /var/lib/aide створюється в режимі 700 (власник _aide), # і панель (www-data) не бачить базу → показує «Не ініціалізована». # Відкрити каталог на прохід (файли бази лишаються 600): sudo chmod 755 /var/lib/aide # Перша перевірка ІЗ ЗАПИСОМ у лог, який читає монітор. # На Ubuntu/Debian aide потребує явного --config (інакше «missing configuration»; # бінарник aide.wrapper у нових версіях не постачається): sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Під час aideinit термінал 5–15 хвилин стоїть на рядку Running aide --init... — це нормально (хешування всієї ФС, навантаження на диск). Не переривайте Ctrl+C. Якщо процес «висить», але нічого не пише — можливо, він чекає на відповідь на прихований запит Overwrite existing aide.db.new [Yn]? (натисніть Y). Перевірити активність з іншої сесії: pgrep -af aide.
Помилка aideinit: «21_aide_spamassassin … printf: invalid number» (return code 20) — відомий баг конфіг-сніпета AIDE в Ubuntu 22.04. База не створюється. Винесіть зламаний сніпет і повторіть:
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
Статуси на дашборді. «Не ініціалізована» = панель не бачить файл бази: або aideinit не запускався, або (Ubuntu 24.04) каталог /var/lib/aide створено в режимі 700 і недоступний для www-data — лікується командою sudo chmod 755 /var/lib/aide (див. блок вище). «Перевірок не було» = база є, але перевірка ще не виконувалась — це не помилка. Результати монітор читає з /var/log/aide/aide.log.
Регулярна перевірка → лог для панелі. Штатний /etc/cron.daily/aide на нових Ubuntu/Debian може не писати /var/log/aide/aide.log в потрібному вигляді (і aide.wrapper у них уже немає). Надійніше додати власний крон з явним --config — він пише лог від root у режимі 644, і монітор читає його без додаткових груп:
# sudo crontab -e — щоденна перевірка о 02:00: 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # Запустити зараз, не чекаючи розкладу: sudo bash -c 'aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1'
Автовстановлення уже робить усе це: chmod 755 /var/lib/aide і крон перевірки о 02:00 — вручну нічого не потрібно.
Першу ініціалізацію робіть на чистому сервері — до встановлення вебзастосунків. Після легітимних змін перестворюйте базу: sudo aideinit && sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db.

15. Встановлення ClamAV

Антивірусний сканер для Linux. Особливо корисний для перевірки /var/www на PHP-шели та шкідливий код.

sudo apt install clamav clamav-daemon sudo systemctl enable --now clamav-daemon # Оновити базу сигнатур: sudo freshclam # Просканувати теку вручну: sudo clamscan -r /var/www --infected
Демон clamd показує «Неактивний» після enable --now? Три типові причини:

1. У конфізі залишився рядок Example — clamd відмовляється стартувати, доки він там є:

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

2. Не завантажено базу сигнатур — clamd не стартує без неї:

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

3. Просто завантажується — clamd вантажить ~8 млн сигнатур у пам'ять 30–60 с. Зачекайте й перевірте: systemctl is-active clamav-daemon (статус activating → ще вантажить).

Діагностика: sudo journalctl -u clamav-daemon -n 30 --no-pager.
На дашборді «Файлів перевірено: 0» / «Останнє сканування: —»? Демон clamd лише тримає сигнатури в пам'яті, сам він нічого не сканує за розкладом. Панель показує результати планового сканування, тому потрібен крон, який сканує та пише лог. Автовстановлення додає обгортку /usr/local/bin/clamav-scan.sh і крон о 01:30 — після першого запуску заповняться «Файлів перевірено» та «Останнє сканування». Запустити одразу, не чекаючи розкладу: sudo /usr/local/bin/clamav-scan.sh.

16. Встановлення Linux Malware Detect (maldet)

Linux Malware Detect (LMD) — сканер шкідливого ПЗ для веб-загроз: PHP-шели, веб-бекдори, завантажувачі. Використовує рушій ClamAV і доповнює його власними сигнатурами.

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 # Оновити сигнатури: sudo maldet -u # Сканувати /var/www: sudo maldet -a /var/www
LMD і ClamAV добре працюють у парі. Останній звіт: maldet --report.
Під час встановлення можливий рядок update-rc.d: error: unable to read /etc/init.d/maldet — він безпечний. maldet не використовує init.d, оновлення сигнатур і сканування запускаються через /etc/cron.daily/maldet. Якщо нижче видно installation completed — все встановилося.
На сторінці LMD показує «Не встановлено», хоча він встановлений? maldet ставиться не через apt, а в /usr/local/maldetect, і за увімкненого open_basedir його наявність перевіряється через shell — див. розділ «Сторінка порожня, хоча дані на сервері є».

17. Встановлення Suricata

Мережева система виявлення вторгнень: аналізує трафік на рівні пакетів і знає тисячі сигнатур атак. Доповнює ModSecurity (той працює на рівні HTTP, Suricata — на рівні TCP/IP).

sudo add-apt-repository ppa:oisf/suricata-stable sudo apt update && sudo apt install suricata # Завантажити актуальні правила: sudo suricata-update sudo systemctl enable --now suricata
Suricata «Активна», але панель не показує сповіщення / кількість подій 0? Suricata пише /var/log/suricata/eve.json під root у режимі 750 на каталог, і вебсервер (www-data) не може його прочитати. Відкрийте каталог на прохід — файли всередині залишаються захищеними:
sudo chmod o+rx /var/log/suricata
Автовстановлення робить це саме — вручну не потрібно.

18. Встановлення Falco

Перехоплює системні виклики через eBPF/kernel module і виявляє аномалії в реальному часі: shell із nginx, читання /etc/passwd вебпроцесом, запис у /bin тощо.

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
Монітор читає події Falco через journalctl -u falco (без sudo — через групу systemd-journal). Переконайтеся, що www-data є в цій групі — див. «Налаштування sudo» (п.2) на сторінці ручного встановлення.
«0 подій за 24 години» — це норма, а не помилка. Falco працює на основі подій: він мовчить, поки все гаразд, і записує подію лише за аномалії (shell із вебпроцесу, читання /etc/passwd, запис у системні каталоги). Нуль критичних за добу на спокійному сервері — здоровий стан.
Для панелі надійніший файловий вивід. Читання через journalctl потребує прав на журнал; щоб панель бачила події стабільно, автовстановлення вмикає у Falco file_output/var/log/falco/falco.log і службі ставить UMask=0022 (лог читається вебсервером). Вручну на новому встановленні це налаштовувати не потрібно.

19. Встановлення ModSecurity (WAF)

ModSecurity — вебфаєрвол (WAF) для Apache або Nginx. Блокує атаки на рівні застосунку: SQL-ін'єкції, XSS, обхід шляхів, сканери.

# Apache: sudo apt install libapache2-mod-security2 sudo a2enmod security2 # Набір правил OWASP Core Rule Set: sudo apt install modsecurity-crs # ОБОВ'ЯЗКОВО: без цього файлу рушій правил вимкнено 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 # Перевірка: має повернути 403 curl -s -o /dev/null -w '%{http_code}\n' "https://monitor.example.com/?id=1%20UNION%20SELECT%201,2--"
Встановлення пакета саме по собі нічого не захищає. Apache підключає конфіги рядком IncludeOptional /etc/modsecurity/*.conf, а пакет кладе лише modsecurity.conf-recommended — під маску *.conf він не потрапляє. Якщо не скопіювати його в modsecurity.conf, SecRuleEngine залишається Off: модуль завантажено, правила CRS завантажено, але трафік не перевіряється й аудит-лог не створюється. Проміжний режим DetectionOnly лише записує події в лог, не блокуючи запити — панель показує його жовтим.

Доступ панелі до аудит-логу. Лог /var/log/apache2/modsec_audit.log належить root (права 640), вебкористувач його не прочитає. Панель бере дані через обгортку — створіть її:

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 # у /etc/sudoers.d/monitor (користувач = той, під яким працює PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec
Обгортка бере останню директиву SecRuleEngine без відступу: рядки з відступом розташовані всередині блоків <LocationMatch>/<Directory> (наприклад, вимкнення WAF для phpMyAdmin) і глобального режиму не визначають.
Користувач у sudoers має збігатися з користувачем FPM-пулу: на звичайному Apache/Debian це www-data, у HestiaCP пул сайту працює від власника сайту (наприклад, admin) — перевірте grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.
Якщо сайт стоїть за Nginx-проксі (HestiaCP), Apache бачить клієнтом сам проксі — панель бере справжню IP-адресу атакувальника із заголовка X-Forwarded-For. У статистику потрапляють лише транзакції зі спрацьованим правилом: директива SecAuditLogRelevantStatus пише в аудит-лог будь-які відповіді 4xx/5xx, тому туди потрапляють і звичайні 403/500 — подіями WAF панель їх не вважає.
Блок ---RULES--- потрібен розділу «Усі активні правила» — панель показує не лише спрацьовані, а взагалі всі завантажені правила CRS + кастомні. Три шляхи в циклі for f in … — типові місця для CRS-правил і локальних доповнень; якщо у вас інше розташування (пакет ставить файли у свій каталог, або кастомні правила лежать не в /etc/modsecurity/custom-rules.conf), знайдіть справжні шляхи командою sudo grep -rl 'IncludeOptional\|^Include ' /etc/apache2/mods-enabled/security2.conf /etc/apache2/conf-enabled/*.conf 2>/dev/null і підставте їх у список. Якщо обгортка стара (без цієї секції) — розділ просто покаже попередження «недоступно», решта сторінки працює як раніше.

20. Встановлення Auditd

Auditd (Linux Audit Daemon) фіксує системні виклики на рівні ядра: входи та виходи, sudo-команди, невдалі спроби автентифікації, зміни файлів. Монітор показує входи, невдалі спроби та sudo-команди за сьогодні.

sudo apt install auditd audispd-plugins sudo systemctl enable --now auditd # Перевірити статус та події: sudo systemctl status auditd sudo ausearch -m USER_LOGIN -ts today
Монітор читає події через ausearch (/usr/sbin/ausearch) і за потреби з /var/log/audit/audit.log командою tail. Обидва мають бути в sudoers.

21. Встановлення Monit

Стежить за сервісами (nginx, php-fpm, mysql тощо) і перезапускає їх у разі падіння. Може надсилати сповіщення на email.

sudo apt install monit sudo systemctl enable --now monit # Конфіги: sudo nano /etc/monit/monitrc ls /etc/monit/conf.d/
Монітор отримує список сервісів через monit status. У /etc/monit/monitrc має бути увімкнений HTTP-інтерфейс (блок set httpd з allow localhost), інакше monit status поверне помилку.
На дашборді «0 сервісів під наглядом»? Дві причини. (1) HTTP-інтерфейс вимкнено — у monitrc рядок set httpd закоментовано (за замовчуванням він іде як # set httpd port 2812 …). Розкоментуйте блок і дозвольте localhost. (2) Сам собою увімкнений httpd нічого не відстежує — Monit рахує лише те, що описано check-стансами; без них список порожній навіть за робочого інтерфейсу. Мінімальний робочий конфіг:
# /etc/monit/conf.d/00-httpd — HTTP-інтерфейс для localhost: set httpd port 2812 use address localhost allow localhost # приклади check-стансів (що відстежувати): 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 # перевірити синтаксис (Control file syntax OK) sudo systemctl reload monit sudo monit status
Автовстановлення розміщує готовий conf.d з httpd на 2812 і набором перевірок — на новій установці налаштовувати вручну не потрібно.
Сервіс у статусі «З помилками»? Монітор лише показує стан і навмисно не перезапускає сервіси з вебпанелі (це було б віддаленим виконанням root-команд у панелі безпеки). Діагностика та перезапуск — через SSH за допомогою Monit:
sudo monit status <service> # причина помилки sudo monit restart <service> # перезапуск через Monit # якщо Monit не піднімає сервіс — дивіться його власний юніт: sudo systemctl status <unit> --no-pager sudo journalctl -u <unit> -n 50 --no-pager

22. Встановлення PSAD (виявлення сканування портів)

PSAD аналізує журнал iptables і виявляє сканування портів та мережеві атаки, присвоюючи кожному джерелу рівень загрози (1–5). Доповнює fail2ban і Suricata.

sudo apt install psad # PSAD читає лог iptables — потрібно ввімкнути логування (UFW робить це самостійно). # Для чистого iptables додайте правила LOG у ланцюжки INPUT/FORWARD. sudo psad --sig-update sudo systemctl enable --now psad
Monitor читає дані через psad --Status (потрібен у sudoers). Без логування iptables сторінка буде порожньою — це нормально, поки не було сканувань.

23. AppArmor / SELinux (контроль доступу)

Mandatory Access Control обмежує, до яких файлів і ресурсів може звертатися програма, навіть якщо її зламали. В Ubuntu/Debian за замовчуванням використовується AppArmor (зазвичай уже встановлений і активний).

# AppArmor (Ubuntu/Debian): sudo apt install apparmor apparmor-utils sudo systemctl enable --now apparmor sudo aa-status # перевірити профілі
Монітор читає статус через aa-status (потрібен у sudoers). Показує кількість профілів у режимі enforce/complain і процеси без профілю.

«Профілів завантажено» більше, ніж enforce + complain — це нормально. У AppArmor 4.x (Ubuntu 24.04 і новіше) з’явився режим unconfined: профіль завантажено в ядро, але він нічого не обмежує. Ubuntu так позначає десятки профілів для програм, що використовують user namespaces (браузери, torrent-клієнти тощо). Коли такі профілі є, картка «Профілів завантажено» стає бурштиновою і показує їхню кількість — наприклад unconfined: 90 при 120 завантажених і 26 в enforce. Реально захищають лише профілі в enforce; на Ubuntu 22.04 (AppArmor 3.x) цього режиму немає і цифри завжди збігаються.

sudo aa-status | grep -E "profiles are" # розподіл за режимами sudo aa-enforce /etc/apparmor.d/profile-name # перевести профіль в enforce
Переводити в enforce профілі, які Ubuntu навмисно залишила в unconfined, варто лише свідомо: їх вимкнено не помилково, а тому що інакше ламається робота самих програм. Профілі в complain — інша річ: там правила вже написані й лише не застосовуються.

24. Встановлення debsums (цілісність пакетів)

debsums перевіряє, чи файли встановлених пакетів збігаються з контрольними сумами з репозиторію — виявляє підмінені системні бінарники (доповнює AIDE). Повна перевірка триває 1–2 хвилини, тому запускається за cron, а панель читає результат із data/debsums/debsums.log і сама розкладає за категоріями (важливі лише бінарники та бібліотеки).

Завдання — у root-крон (sudo crontab -e). Готова обгортка debsums-scan.sh кладеться в /usr/local/bin/ (chmod +x; див. зведення cron-завдань) і сама пише звіт у data/debsums/ панелі.

sudo apt install debsums # Cron-строка (ежедневно 4:30): 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Обгортка debsums-scan.sh сама знаходить data/ панелі — шлях прописувати не потрібно.

Зміни в /etc/ (конфіги) та /usr/share/ (ресурси) на сервері зазвичай нормальні — панель позначає їх окремим кольором. Тривожними є зміни бінарників і бібліотек (/bin, /sbin, /usr/lib тощо) — картка «Бінарники / бібліотеки» показує саме їх.

25. Налаштування звітів Lynis

Lynis запускається вручну або через cron. Звіт має зберігатися в папку data/lynis/ проєкту — монітор читає файл lynis-report.dat.

# Одноразовий запуск (підставте свій шлях до кореня панелі): sudo lynis audit system --report-file /path/to/monitor/data/lynis/lynis-report.dat # Щоденний аудит — cron-рядок (готова обгортка lynis-scan.sh у /usr/local/bin/, див. зведення): 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1
Після першого запуску сторінка «Аудит Lynis» одразу покаже hardening index, попередження та рекомендації.
Кнопка «Запустити аудит» на сторінці Lynis. Вона запускає lynis-scan.sh у фоні прямо з панелі (не чекаючи cron): показує «Сканування…» і після завершення сама оновлює звіт. Для цього вебкористувачу потрібен рядок sudoers на запуск скрипта — інсталятор додає його автоматично у /etc/sudoers.d/monitor. Якщо панель встановлювалася вручну/раніше, допишіть його тим самим користувачем, що вже вказаний у файлі:
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

26. Налаштування звітів Logwatch

Logwatch має зберігати щоденні звіти в папку data/logwatch/ проєкту у форматі .txt. Монітор показує останній звіт та архів.

# Щодня (6:00) — cron-рядок (готова обгортка logwatch_daily.sh у /usr/local/bin/, див. зведення): 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1

Модулі панелі

27. Мережевий монітор (вбудований)

Мережевий монітор не потребує встановлення — це вбудована сторінка панелі. Вона показує мережевий стан сервера з локальних джерел:

  • інтерфейси та трафік — з /proc/net/dev;
  • стан лінків (UP/DOWN) та IP — через ip;
  • з'єднання та порти, що слухають, — через ss;
  • мережеві події ядра за 24 год — через journalctl -k.

Перші три джерела працюють без sudo, тому інтерфейси, трафік, з'єднання та порти видно одразу. Блок «Події ядра» використовує journalctl -k — він читається через групу systemd-journal («Налаштування sudo», п.2), sudo не потрібен. Перевірити, що все доступне вебкористувачу:

# Проверка от имени www-data (под ним работает 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
Блок «Мережеві події ядра» показує події мережевого стека ядра (зміна лінка up/down, помилки несучої, «network unreachable»). Записи брандмауера UFW BLOCK сюди не потрапляють — вони на сторінках «Брандмауер UFW» та «Карта атак». Порожній блок із зеленою галкою = за добу мережевих збоїв не було.

28. Диск і SMART

Вбудована сторінка показує три речі:

  • Файлові системи — заповнення розділів (df); шкала червоніє при ≥90%;
  • Накопичувачі — список дисків (lsblk), лише реальні (loop/snap приховані);
  • Здоров'я (SMART) — статус диска й атрибути (smartctl).

Місце та список пристроїв працюють одразу, без налаштування. Для SMART потрібен пакет smartmontools. Веб-процес не має прямого доступу до дискових пристроїв, тому SMART знімається за cron у файл data/disk/smart.txt, а панель його читає.

Завдання — у root-крон (sudo crontab -e). Готова обгортка smart-scan.sh кладеться в /usr/local/bin/ (chmod +x; див. зведення cron-завдань) і сама пише в data/disk/ панелі.

sudo apt install smartmontools # Cron-рядок (кожні 30 хвилин): */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1

Обгортка smart-scan.sh сама знаходить data/ панелі — шлях прописувати не потрібно. Всередині lsblk -e7,11 виключає loop/cdrom.

На віртуальних дисках (QEMU/KVM і подібних) зазвичай доступний лише загальний статус «здоров'я: OK», а температура, години роботи та перерозподілені сектори можуть бути порожніми — це нормально. На фізичному сервері відображаються всі атрибути.

29. Продуктивність (CPU/RAM/Мережа/Диск)

Сторінка показує історію навантаження сервера за останні 24 години — Load Average, завантаженість CPU та очікування I/O, RAM/Swap, мережевий трафік (приймання/передавання), дисковий I/O (читання/запис), заповнення диска та inodes, відкриті файлові дескриптори і MySQL-з’єднання, а також поточну кількість TCP-з’єднань і процесів.

Дані збирає cron/collect_metrics.php — раз на 5 хвилин записує один «сирий» знімок лічильників (/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') у таблицю БД system_metrics; відсотки та швидкості сторінка обчислює сама за різницею між сусідніми знімками (заповнення диска/inodes/дескрипторів/MySQL-з’єднання — миттєві значення, без перерахунку). Sudo не потрібне — джерела читаються без прав root. Точки, старші за 24 години, видаляються автоматично під час кожного запису.

# Cron-рядок (кожні 5 хвилин): */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1

Обгортка collect-metrics-all.sh (див. зведення cron-завдань) сама знаходить усі встановлені на сервері інстанси панелі та запускає cron/collect_metrics.php кожного від імені власника сайту.

Доки колектор не спрацював хоча б двічі (перші ~10 хвилин після встановлення), сторінка показує «дані збираються» — графікам потрібна щонайменше одна пара сусідніх точок, щоб обчислити швидкості та відсотки.

Сповіщення про навантаження (розділ «Налаштування» → «Сповіщення про навантаження») — коли перевищено поріг CPU/RAM/диска/inodes, панель надсилає сповіщення в Telegram/Email (ті самі канали, що й щоденний звіт — окремо вмикати їх для сповіщень не потрібно), і ще одне — коли метрика повернулася до норми. Повторно під час утримання порогу не спамить: наступне сповіщення надійде лише після циклу «відновилося → знову перевищило».

Пороги перевіряє той самий collect_metrics.php під час кожного запуску (раз на 5 хвилин) — окремий cron не потрібен. Стан «уже сповістили / ще ні» зберігається у data/alerts_state.json, пороги — у налаштуваннях панелі.

30. Карта атак (GeoIP)

Сторінка «Карта атак» визначає країну за IP командою geoiplookup. Без пакета GeoIP країни не визначатимуться і точки на карті не з’являться:

sudo apt install geoip-bin geoip-database # Перевірка: geoiplookup 8.8.8.8
Sudo не потрібне — база /usr/share/GeoIP/GeoIP.dat доступна для читання всім, результати кешуються в tmp/geoip_cache.json. Сама карта (Leaflet + плитки OpenStreetMap) завантажується в браузері — потрібен інтернет на комп’ютері, де відкрито панель.

31. Зовнішня експозиція, оновлення та автооновлення

Дві вбудовані картки дашборда, що показують не «увімк./вимк.» інструмента, а реальну захищеність сервера. Встановлення не потребують, читаються локально без sudo.

Зовнішня експозиція — скільки сервісів слухають усі інтерфейси (0.0.0.0/[::]) і доступні ззовні. Підсвічує червоним, якщо назовні стирчать СУБД чи кеш (MySQL, PostgreSQL, Redis, MongoDB, Memcached, Elasticsearch) — це пряма діра (−10 до Оцінки безпеки). Джерело: ss -tuln.

Якщо картка червона — закрийте СУБД для зовнішнього світу: прив’яжіть до 127.0.0.1 (bind-address у конфізі MySQL/PostgreSQL, bind 127.0.0.1 у Redis) або закрийте порт у UFW.
«Відкритий порт» ≠ «доступний ззовні». Сервіс, що слухає 127.0.0.1 (loopback), видно лише самому серверу — ззовні на нього не потрапити, навіть якщо порт «відкритий». Тому Postfix на порту 25, прив’язаний до loopback, безпечний: автоналаштування ставить inet_interfaces = loopback-only (плюс нейтральний smtpd_banner — закриває зауваження Lynis MAIL-8818 про розкриття версії). Картка «Зовнішня експозиція» рахує назовні лише те, що слухає 0.0.0.0/[::]; loopback-сервіси туди не потрапляють.
Lynis MAIL-8818 вручну (якщо ставили пошту самі): у /etc/postfix/main.cf задайте smtpd_banner = $myhostname ESMTP (без версії та ОС) і inet_interfaces = loopback-only, потім sudo systemctl restart postfix.

Оновлення безпеки — скільки security-патчів чекають установлення й чи потрібне перезавантаження після оновлення ядра (−5 до Оцінки безпеки за наявності патчів). Джерело: /usr/lib/update-notifier/apt-check, файл /var/run/reboot-required. Детальний список — на сторінці «Оновлення безпеки».

# Встановити оновлення: sudo apt update && sudo apt upgrade # Перевірити, що слухає назовні: ss -tuln | grep -E '0\.0\.0\.0|\[::\]'
Картка оновлень працює на Ubuntu/Debian (update-notifier-common). Якщо apt-check відсутній — монітор рахує патчі через apt-get -s upgrade.

Автооновлення безпеки (unattended-upgrades) — на сторінці «Оновлення безпеки» окрема картка показує, чи ввімкнено автоматичне встановлення security-патчів і коли воно запускалося востаннє. Sudo не потрібен — статус читається через apt-config dump.

sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # включить # Проверить, что включено: apt-config dump | grep Unattended-Upgrade

Обслуговування

32. Резервне копіювання

Резервна копія — головна страховка: втрата даних гірша за будь-який злам. Потрібні дві речі — резервна копія сервера/сайтів та окремо резервна копія БД панелі (там користувачі, ключі WebAuthn, налаштування, ліцензія).

Варіант A — HestiaCP: вкладка Backup у користувача → кнопка створення резервної копії (або за розкладом у налаштуваннях сервера). Копія включає сайти та їхні БД.

Варіант B — вручну (cron): дамп БД + архів каталогу data/ панелі:

# root-крон (sudo crontab -e) — щоденна резервна копія о 2:30 (підставте свої імена/шляхи): 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 # Видаляти архіви старші за 14 днів: 0 3 * * * find /var/backups -name 'monitor-*' -mtime +14 -delete
Резервна копія на тому самому сервері рятує від помилок, але не від втрати сервера. Копіюйте архіви на зовнішнє сховище (інший сервер, S3, rclone у хмару). Перевіряйте, що відновлення справді працює.

33. Оновлення та перенесення панелі

Оновлення до нової версії. Спершу зробіть резервну копію. Потім перезалийте файли коду, зберігши свої дані:

  • перезаписати (код): public/, includes/, assets/, cron/, database/, а також кореневі .htaccess (фронт-контролер — маршрутизацію не можна лишати від старої версії), manifest.json, sw.js;
  • не чіпати: config.php (дані БД), data/ (звіти), logs/, tmp/ (сесії та кеш).
# Після заливання — скинути кеш PHP (якщо ввімкнено opcache): sudo systemctl reload php*-fpm
FileZilla пише SSH_FX_PERMISSION_DENIEDPermission denied. Файли панелі належать www-data (так їх виставили під час встановлення), а SFTP-клієнт підключається під вашим власним користувачем, у якого немає права запису. Віддавати www-data всю панель «щоб працювало» — саме те, що призводить до цієї помилки; нижче три способи, будь-який розв'язує проблему.
# Варіант A (рекомендовано) — розділити власників: код ваш, робочі теки вебсервера. # Вебсервер права запису в КОД панелі не отримує зовсім: 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 # Варіант B — ACL поверх поточних власників (нічого не переносимо): 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 # Варіант C — через групу www-data. Простіший, але запис у файли панелі # отримує й вебсервер (за вразливості в PHP код можна підмінити): 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
Чому варіант A безпечний. Панель пише лише у три каталоги — data/ (звіти), tmp/ (сесії та кеш), logs/; вони лишаються за www-data. Решта — код, і вебсерверу він потрібен лише на читання, яке дає група www-data з правами 644. Побічний виграш: за вразливості в PHP файли панелі вже не переписати. На хостинг-панелях (HestiaCP і подібні) варіант A не потрібен: там файли сайту й так належать акаунту, під яким ви заходите через SFTP, а вебсервер читає їх за групою.
Пастка варіанта B: будь-який наступний chmod по файлах скидає ACL-маску, і доступ мовчки зникає. Якщо після «наведення ладу в правах» заливання знову впирається в Permission denied — повторіть обидві команди setfacl.
Біт 2 у варіанті C — це setgid: файли, завантажені через SFTP, лишаються в групі www-data, інакше панель не зможе їх перезаписати. Після варіанта C перепідключіться у FileZilla — нова група застосовується лише при новому вході. Перевірка: id deploy (має з'явитися група www-data) і ls -ld /path/to/monitor (drwxrwsr-x — літера s означає, що setgid встановлено).

Перенесення на інший сервер:

  1. На новому сервері підніміть сайт + HTTPS (див. сторінку ручного встановлення).
  2. Скопіюйте всі файли панелі разом із config.php, data/.
  3. Перенесіть БД: mysqldump на старому → імпорт на новому; виправте дані БД у config.php.
  4. Повторіть на новому сервері: sudoers, членство у групі adm, cron-завдання.
  5. Ліцензія прив'язана до домену — якщо домен той самий, ключ продовжить працювати.

34. Відновлення доступу (втрачено ключ, пароль, IP-блокування)

Якщо ви не можете увійти — усе виправляється безпосередньо в БД із сервера. Відкрийте БД (ім'я — з config.php):

sudo mysql MY_DB

Втрачено ключ WebAuthn (не проходить другий фактор) — вимкніть 2FA, увійдіть за паролем, зареєструйте новий ключ:

UPDATE users SET webauthn_enabled = 0;

Забули пароль — задайте новий хеш (згенеруйте його на сервері та підставте):

# Згенерувати хеш нового пароля: php -r "echo password_hash('NEW_PASSWORD', PASSWORD_BCRYPT), \"\n\";" # У БД (вставте отриманий хеш): # UPDATE users SET password = '$2y$10$...' WHERE username = 'admin';

Заблокували себе IP-фільтром — вимкніть обмеження:

UPDATE settings SET value = '0' WHERE name = 'ip_restriction_enabled';
Доступ до БД є завжди: sudo mysql на сервері або phpMyAdmin / розділ БД у панелі хостингу. Після відновлення знову ввімкніть WebAuthn та IP-фільтр.

35. Усі cron-завдання в одному місці

Зведення завдань — у root-cron сервера (додаються через sudo crontab -e). Залиште лише рядки тих інструментів, які використовуєте; підправте шляхи під свій сервер.

# Серверний cron монітора (root) — впишіть через: sudo crontab -e # 01:30 — скан ClamAV за небезпечними шляхами (web, home, temp) → картки «Файлів перевірено» та «Останнє сканування» 30 1 * * * /usr/local/bin/clamav-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 02:00 — перевірка цілісності файлів AIDE (потрібен явний --config) 0 2 * * * /usr/bin/aide --config /etc/aide/aide.conf --check > /var/log/aide/aide.log 2>&1 # при старті — відновити права /var/lib/aide (пакетний tmpfiles-файл # aide-common.conf скидає їх у 0700, і панель перестає бачити базу) @reboot chmod 755 /var/lib/aide # 03:00 — аудит безпеки Lynis 0 3 * * * /usr/local/bin/lynis-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:00 — оновлення блок-списку ipsum (level 1) 0 4 * * * /usr/local/bin/load-ipsum.sh >> /path/to/monitor/logs/cron.log 2>&1 # набір ipsum при старті піднімає сервіс ipsum-load.service (ДО фаєрвола, інакше # UFW не побачить набір у before.rules) — не cron. Тут лише щоденний рефреш вище. # 06:00 — звіт Logwatch 0 6 * * * /usr/local/bin/logwatch_daily.sh >> /path/to/monitor/logs/cron.log 2>&1 # кожні 30 хв — перевірка дисків SMART */30 * * * * /usr/local/bin/smart-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 04:30 — цілісність пакетів debsums 30 4 * * * /usr/local/bin/debsums-scan.sh >> /path/to/monitor/logs/cron.log 2>&1 # 08:00 — звіт за розкладом на Email і Telegram 0 8 * * * /usr/local/bin/daily-report-all.sh >> /path/to/monitor/logs/cron.log 2>&1 # щогодини — оновлення списків пакетів (для картки «Оновлення безпеки») 0 * * * * /usr/bin/apt-get update -qq >/dev/null 2>&1 # кожні 5 хв — знімок ресурсів (CPU/RAM/мережа/диск) для сторінки «Продуктивність» */5 * * * * /usr/local/bin/collect-metrics-all.sh >> /path/to/monitor/logs/cron.log 2>&1
Подробиці щодо кожного — у відповідних розділах. Завдання резервного копіювання (попередній розділ) додаються в цей самий cron. Після правок перевірте: sudo crontab -l і що cron-служба активна.
Час cron = часовий пояс сервера, а не TIMEZONE з config.php. Константа TIMEZONE впливає лише на PHP (як панель показує дати), але cron-демон запускає завдання за системним часом ОС. Якщо пояс сервера не збігається з вашим, звіт «08:00» надійде не в той час. Приклад: сервер стоїть в іншому поясі (Europe/Berlin, UTC+2), а ви — у Києві (UTC+3) → звіт «08:00» надійде о 09:00 за вашим часом. Перевірте й за потреби приведіть пояс системи до свого:
# Перевірити поточний пояс сервера: timedatectl # Встановити свій пояс (приклад) і перезапустити cron: sudo timedatectl set-timezone Europe/Kyiv sudo systemctl restart cron
Після цього рядок 0 8 * * * спрацює о 08:00 за місцевим часом. Інакше зсувати довелося б сам cron, але під час переходу на зимовий/літній час зсув знову розійдеться — тому правильніше налаштувати пояс системи.
Готові скрипти-обгортки. Їхні робочі копії та зразок crontab (crontab.txt) лежать у теці system/ поруч із проєктом, поза public_html. Це не частина сайту — у вебкорінь їх завантажувати не потрібно; розмістіть на сервері за системними шляхами (як у crontab вище):
  • lynis-scan.sh/usr/local/bin/ (chmod +x) — запускає lynis audit system, на час скану ставить прапорець /tmp/lynis-running і копіює lynis-report.dat у data/lynis/ панелі;
  • logwatch_daily.sh/usr/local/bin/ (chmod +x) — формує щоденний звіт Logwatch (sshd, fail2ban, sudo, postfix) у data/logwatch/;
  • smart-scan.sh/usr/local/bin/ (chmod +x) — знімає стан дисків (smartctl) у data/disk/;
  • debsums-scan.sh/usr/local/bin/ (chmod +x) — перевіряє цілісність пакетів (debsums) у data/debsums/;
  • clamav-scan.sh/usr/local/bin/ (chmod +x) — антивірусний скан ClamAV за небезпечними шляхами (web, home, temp); пише зведення у /var/log/clamav/scan.log, звідки його читає сторінка ClamAV (рядок 01:30 у crontab вище);
  • load-ipsum.sh/usr/local/bin/ (chmod +x) — оновлює ipset-набір ipsum (level 1) на місці, не розриваючи чинних правил файрвола (рядок 04:00 у crontab вище);
  • daily-report-all.sh/usr/local/bin/ (chmod +x) — запускає звіт cron/daily_report.php панелі (рядок 08:00 у crontab вище);
  • daily_report.php — уже входить до панелі (cron/daily_report.php), запускається через daily-report-all.sh, окремо ставити не потрібно;
  • collect-metrics-all.sh/usr/local/bin/ (chmod +x) — запускає cron/collect_metrics.php панелі (сторінка «Продуктивність», рядок */5 у crontab вище); collect_metrics.php уже входить до панелі, окремо ставити не потрібно;
  • crontab.txt (system/cron/) — зразок завдань; потрібні рядки впишіть через sudo crontab -e.
Шлях до скрипта в crontab має збігатися з тим, куди ви його поклали.
Як покласти скрипт у /usr/local/bin/. Напряму з FileZilla туди не записати — каталог належить root, і SFTP-клієнт отримає SSH_FX_PERMISSION_DENIED. Порядок такий: спершу залити файл у /tmp (туди пишуть усі), потім перенести його на місце однією командою:
# у FileZilla: у полі «Віддалений сайт» ввести /tmp і завантажити туди скрипт, # потім по SSH (install одразу ставить власника й права, chown/chmod не потрібні): sudo install -o root -g root -m 755 /tmp/lynis-scan.sh /usr/local/bin/lynis-scan.sh rm -f /tmp/lynis-scan.sh # перевірка: файл на місці, права rwxr-xr-x, синтаксис цілий bash -n /usr/local/bin/lynis-scan.sh && ls -l /usr/local/bin/lynis-scan.sh
Не переплутайте каталоги: потрібен /tmp у корені сервера — не /var/tmp і не tmp/ усередині самої панелі (останній належить www-data і закритий від вашого користувача). У дереві FileZilla /tmp — гілка верхнього рівня, поруч із var, а не всередині неї.
Ставили сервер автоналаштуванням? Ці обгортки та їхні cron-завдання уже встановлені скриптом (у /usr/local/bin/, лог — /var/log/arciveo-cron.log) — вручну нічого робити не потрібно.
Де скрипти шукають панель. Обгортки доменно-нейтральні: знаходять інсталяції панелі, перебираючи /home/*/web/*/public_html та /var/www/*, і кладуть звіти в їхні data/. Якщо панель лежить за іншим шляхом — додайте його в рядок for app in … всередині скриптів, інакше звіти Lynis/SMART/debsums/Logwatch у панель не потраплять.
cron.log і права доступу. Файл logs/cron.log першим створює root-cron — він належатиме root, і вкладка «Журнал cron» у панелі не зможе його ні прочитати, ні очистити. Створіть файл заздалегідь від імені вебкористувача (власник каталогу сайту; в HestiaCP це акаунт, напр. admin) — тоді root-cron лише дописуватиме, не змінюючи власника:
# створити заздалегідь від вебкористувача (до додавання cron-рядків): sudo -u OWNER touch /path/to/monitor/logs/cron.log # якщо cron.log уже створено root-cron — віддати вебкористувачу: sudo chown OWNER:OWNER /path/to/monitor/logs/cron.log sudo chmod 644 /path/to/monitor/logs/cron.log
Дізнатися власника каталогу: stat -c %U /path/to/monitor.
Керування з панелі. У розділі «Система» є сторінка «Crontab» — можна переглядати й додавати завдання без SSH. Панель редагує лише завдання, додані через неї саму (окремий блок у root-crontab, позначений службовими коментарями); усе, що вже стоїть у crontab (список вище), показано там read-only списком «Інші завдання сервера» з кнопкою «Скопіювати в редактор» — вона лише переносить розклад/команду у форму додавання, вихідний рядок не чіпає. Щоб «перевести» наявне завдання під керування панелі — скопіюйте його в редактор, збережіть, потім видаліть старий рядок вручну (sudo crontab -e), інакше воно виконуватиметься двічі.
Разове налаштування на сервері. Сторінці потрібен привілейований скрипт-обгортка — не голий sudo crontab (це була б пряма ескалація до root будь-ким, хто отримає доступ до сесії панелі), а вузький скрипт із двома командами (list/set), що чіпає лише свій блок між службовими коментарями. Установіть один раз:
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
Вебкористувач може відрізнятися від www-data — перевірте, під ким працює пул PHP-FPM сайту (ps -o user= -C php-fpm), і підставте його в рядок sudoers.
Новий файл залився не тим власником — сторінка відповідає «Access denied.». Якщо файл public/crontab_monitor.php завантажено через FTP/SFTP під іншим системним користувачем (наприклад, root), ніж решта файлів сайту, вебсервер не зможе його прочитати. Звірте власника й права із сусіднім файлом і приведіть у відповідність:
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

Діагностика

36. Інструмент установлено, але показує «Не встановлено»

Монітор визначає наявність інструментів через dpkg-query — базу пакетів APT. Якщо інструмент установлено не через apt (вручну, зі snap або з вихідних кодів), dpkg його не бачить.

# Перевірити через dpkg: dpkg -l fail2ban | grep '^ii' dpkg -l auditd | grep '^ii' # Знайти шлях до бінарника: which ufw fail2ban-client auditctl # Тест sudo від www-data: sudo -u www-data sudo fail2ban-client status sudo -u www-data sudo ufw status verbose

37. Усунення проблем (500, немає даних)

Помилка 500 — перевірте логи PHP, nginx та самого монітора:

tail -50 /var/log/nginx/error.log tail -50 /var/log/php*-fpm.log # Логи монітора: tail -50 logs/monitor_$(date +%Y-%m-%d).log # Права на теки: ls -la data/ tmp/ logs/
Панель на хостинг-панелі (HestiaCP, ISPmanager, cPanel)? Там PHP працює не під www-data, а під обліковим записом користувача (наприклад admin — власник каталогу сайту). Усі sudo-правила та членство у групах (adm, systemd-journal) потрібно прописувати на цього користувача, інакше модулі покажуть «Не активний / 0» за працюючих сервісів. Дізнатися реального користувача PHP: ps -o user= -C php-fpm | sort -u або власник каталогу сайту stat -c '%U' /path/to/monitor. Далі в усіх командах нижче підставляйте його замість www-data. Автовстановлення визначає веб-користувача саме та прописує sudoers на нього.

Дані не відображаються — майже завжди незадані sudo-права. Перевірте конкретну команду від імені веб-користувача (замініть www-data на свого). Прапорець -n = без пароля, як у PHP — якщо просить пароль, отже правила в sudoers немає:

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
Модуль пише «Не активний» / «0», хоча інструмент працює (наприклад sudo aa-status у терміналі показує профілі, а сторінка «AppArmor» — «Неактивний»). Причина: у веб-користувача немає sudo-права на команду цього модуля. Перевірте її зі списку вище: якщо просить пароль — додайте відсутній рядок до /etc/sudoers.d/monitor («Налаштування sudo»). Часті «нові» команди: /usr/sbin/aa-status (MAC), /usr/sbin/psad --Status (PSAD).
Якщо конкретна сторінка (Falco, ModSecurity, Auditd, відкриті порти UFW) порожня — звірте зі списком у розділі про sudo: імовірно, не дозволено apache2ctl, ausearch, aa-status чи ss, або веб-користувач не в групах adm/systemd-journal (звідти читаються логи fail2ban/auth/modsec і journalctl — Falco та події ядра).

38. Сторінка порожня, хоча дані на сервері є

Симптом: на сервері дані є (через shell видно), а сторінка показує «немає даних» або хибний статус — наприклад AIDE пише «Не ініціалізована», хоча базу створено.

Причина — open_basedir: багато панелей і хостингів обмежують пул PHP-FPM каталогом домену, тому PHP-функції file_exists(), file_get_contents(), filemtime() за системними шляхами (/var/lib/aide, /var/log, /proc…) блокуються. Монітор обходить це, читаючи такі шляхи штатними системними командами (cat, test, stat).

# Чи видно файл через shell (так читає монітор): sudo -u www-data bash -lc 'test -e /var/lib/aide/aide.db && echo VISIBLE || echo NO' # Поточне значення open_basedir для пулу домену: grep -ri open_basedir /etc/php/*/fpm/pool.d/ 2>/dev/null
Якщо shell «бачить» файл (VISIBLE), а сторінка ні — це open_basedir. Правильне рішення — читання системними командами (уже зроблено для AIDE та Мережевого монітора). Розширювати open_basedir на /var, /proc не потрібно і менш безпечно.

39. SSL-сторінка не працює

Монітор перевіряє сертифікати, підключаючись до доменів напряму через порт 443. Якщо домен недоступний із самого сервера або порт закритий фаєрволом — перевірка не пройде.

# Перевірити сертифікат вручну: echo | openssl s_client -connect monitor.example.com:443 2>/dev/null \ | openssl x509 -noout -dates # Перевірити доступність: curl -I https://monitor.example.com
Домени монітор бере автоматично з конфігів nginx (/etc/nginx/sites-enabled/, /etc/nginx/conf.d/) та Apache (/etc/apache2/sites-enabled/) плюс поточний хост із HTTP_HOST.
Автовизначення піддоменів. Піддомени визначаються автоматично з публічних логів Certificate Transparency і перевіряються по мережі — навіть якщо розміщені на інших серверах. Вручну нічого додавати не потрібно.

40. Видно лише одну БД з кількох

Монітор під'єднується до MySQL під користувачем із config.php, який має доступ лише до власної бази. MySQL показує в information_schema тільки бази з привілеями — тому решта не видно.

Щоб монітор бачив усі БД, надайте цьому користувачу право лише на читання (один раз від root; підставте ім'я користувача з config.php):

sudo mysql -u root GRANT SELECT, PROCESS, SHOW DATABASES ON *.* TO 'DB_USER'@'localhost'; FLUSH PRIVILEGES; EXIT;
SELECT ON *.* дає лише право читання — змінити, видалити чи створити щось неможливо, це безпечно для моніторингу.
Без цього GRANT панель бачить лише власну базу — це не помилка, а обмеження прав. Жодного sudo mysql панель не використовує: список баз береться через її власне PDO-під'єднання.

41. PostgreSQL не відображається на сторінці «База даних»

PostgreSQL потребує доступу на рівні користувача postgres, якого веб-користувач панелі не має. Відкривати з PHP широкий sudo psql небезпечно — натомість панель викликає вузьку обгортку без параметрів, яка лише виводить версію, кількість з'єднань і список баз з розмірами. Створіть її:

sudo tee /usr/local/bin/monitor-pgstat >/dev/null <<'EOF' #!/bin/sh # Arciveo 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 # у /etc/sudoers.d/monitor (користувач = той, під яким працює PHP-FPM): # www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
Якщо PostgreSQL не використовуєте — приберіть рядок monitor-pgstat із sudoers (крок 13 ручного встановлення) і сам скрипт не створюйте: картка PostgreSQL просто залишиться неактивною.

42. Спрацював алерт — що робити

Панель показує, що відбувається; нижче — що робити в типових ситуаціях. Загальний принцип: не панікувати, звірити з легітимною активністю (ваші дії, оновлення, резервні копії) і реагувати за серйозністю.

  • Карта атак / багато банів fail2ban — це норма для будь-якого сервера в інтернеті (боти постійно перебирають SSH/веб). Головне, щоб бани спрацьовували. Переконайтеся, що вхід через SSH — лише за ключем (пароль вимкнено), а ваша IP-адреса в ignoreip.
  • ModSecurity заблокував запити — WAF відбиває атаки на сайт, це його робота. Якщо блокується ваш легітимний трафік (хибне спрацювання) — знайдіть rule id у деталях і додайте виняток у конфіг CRS.
  • AIDE: змінено файли — звірте список із тим, що ви робили (оновлення пакетів, правка конфігів — норма). Зміни системних бінарників, яких ви не торкалися, — привід насторожитися. Після легітимних змін оновіть базу AIDE.
  • debsums: змінено бінарники/бібліотеки (поза /etc, поза /usr/share) — потенційно підміна. Звірте пакет: debsums PACKAGE_NAME, за сумніву перевстановіть його (apt install --reinstall).
  • ClamAV / maldet: виявлено загрозу — перевірте файл у карантині, не відкривайте його. Якщо це вебшел у каталозі сайту — ізолюйте сервер і шукайте точку входу (вразливий плагін, витік доступів).
  • Falco: критичні події (запуск shell у контейнері, доступ до чутливих файлів) — розберіть подію: чий процес, що запускав. Часто це легітимна адмін-активність.
  • Зовнішня експозиція: червоним СУБД/кеш — негайно закрийте: прив'яжіть сервіс до 127.0.0.1 або закрийте порт в UFW. Це справжня діра.
  • SSL спливає / сплив — продовжте сертифікат (Let's Encrypt продовжується сам; якщо ні — перевірте certbot renew або налаштування в панелі).
  • Оновлення безпеки очікують — установіть: sudo apt update && sudo apt upgrade; після оновлення ядра перезавантажте сервер.
Ознаки реального зламу (невідомі процеси/користувачі, змінені бінарники, вихідний спам, невідомі cron-завдання): відключіть сервер від зовнішнього доступу, зробіть резервну копію для аналізу і, якщо дані критичні, розгортайте чистий сервер із довіреної резервної копії — надійно вичистити руткіт складно.
Arcivéo - Security Monitor © 2026