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

Друга типова історія — безпека. PrestaShop, WooCommerce та OpenCart живуть на модулях від різних авторів, і старий модуль із дірою — звична річ. Боти безперервно перебирають /admin, шукають відомі вразливості й пробують паролі. Якщо поруч на тому ж сервері лежить ще сотня чужих сайтів, ви не контролюєте ні оновлення PHP, ні сусідів.

Ми переносимо магазин на окремий сервер у OVH або Hetzner і будуємо навколо нього кілька шарів захисту. Найдокладніше описуємо PrestaShop, але WooCommerce і OpenCart робимо за тією самою схемою — відрізняються лише деталі конфігурації.

Що ми робимо

На фізичному сервері ставимо Proxmox VE і розносимо магазин на окремі контейнери або віртуалки:

  • Вхідний вузол — reverse proxy (Nginx або Traefik), TLS-сертифікати Let’s Encrypt з автооновленням, rate limiting і WAF. Тільки він дивиться в інтернет.
  • Веб-частина — Nginx + PHP-FPM потрібної версії, OPcache для PHP-коду, Redis для сесій і кешу магазину.
  • База — MariaDB або MySQL в окремому контейнері, без доступу ззовні, з буферами, налаштованими під розмір каталогу.
  • Staging — копія магазину з анонімізованою базою. Тут оновлюємо PrestaShop, модулі й тему, перш ніж чіпати продакшн.
  • Моніторинг — Prometheus і Grafana: навантаження, помилки 5xx, час відповіді, місце на дисках, термін дії сертифікатів. Алерти йдуть у Telegram або на пошту.
  • Бекапи — дампи бази і каталог із медіа щодня на окреме сховище, плюс знімки контейнерів через Proxmox Backup Server.

Адмінку закриваємо окремо: перейменований каталог, доступ лише з ваших IP або через VPN, двофакторна автентифікація там, де модуль це підтримує.

Шари захисту: від провайдера до PHP

Захист від DDoS працює на кількох рівнях, і кожен ловить своє.

Провайдер. OVH і Hetzner фільтрують об’ємні атаки (UDP-флуд, SYN-флуд) на своїй мережі, ще до вашого сервера. Це входить у ціну сервера, і для більшості магазинів цього досить проти «важкої артилерії».

Cloudflare — за потреби. Він ховає справжню адресу сервера, кешує статику ближче до покупця і добре гасить атаки на рівні HTTP. Але не завжди він потрібен: якщо ваші покупці в одній країні, а атак не було, зайвий посередник лише ускладнить налагодження і дасть ще одну точку відмови. Якщо Cloudflare ставимо, то закриваємо прямий доступ до сервера — інакше його обійдуть. Зручний варіант — Cloudflare Tunnel: сервер сам підключається назовні, і порт 443 взагалі не відкритий в інтернет.

Rate limiting. Атаки на рівні застосунку зазвичай б’ють у важкі сторінки: пошук, фільтри каталогу, кошик, логін. На Nginx ставимо окремі ліміти на такі маршрути:

limit_req_zone $binary_remote_addr zone=search:10m rate=2r/s;
limit_req_zone $binary_remote_addr zone=login:10m  rate=5r/m;

location ^~ /admin-xxxxxx/ {         # каталог адмінки
    allow 198.51.100.0/24;           # офіс або VPN
    deny  all;
}
location ~* /(search|module/.+/search) {
    limit_req zone=search burst=10 nodelay;
}

WAF. ModSecurity з набором правил OWASP CRS або Coraza — блокує SQL-ін’єкції, XSS, спроби прочитати файли конфігурації. Це те, що закриває дірки в модулях, які ви ще не встигли оновити.

CrowdSec. Читає логи проксі й SSH, розпізнає поведінку: сканування, перебір паролів, відомі CVE, агресивні краулери. Бан накладає bouncer на вході. Ще один плюс CrowdSec — спільний список атакуючих адрес: адреса, яка вже сканувала тисячі інших серверів, отримує бан ще до першого запиту до вас.

Де WAF заважає і як ми з цим живемо

Чесно: WAF «з коробки» на магазині ламає речі. Найчастіше страждають модулі оплати й доставки. Callback від платіжного шлюзу приходить із JSON або підписом, схожим на «підозрілий» вміст, — і замовлення зависає в статусі «очікує оплати». Імпорт товарів з CSV, редактор описів з HTML, API маркетплейсів — теж кандидати на хибні спрацьовування.

Тому ми не вмикаємо блокування одразу. Перший тиждень WAF працює в режимі лише логування. Дивимося, що він ловить на реальному трафіку, і пишемо винятки точково: для конкретного URL callback і конкретного правила, а не «вимкнути WAF для /module/». Тоді вмикаємо блокування. Після кожного оновлення модуля оплати перевіряємо тестову транзакцію на staging.

Коли така схема — перебір: якщо у вас кілька десятків замовлень на місяць і магазин на SaaS-платформі на кшталт Shopify, власний сервер не дасть вам нічого, крім турбот. Власна інфраструктура окупається, коли магазин уже має обсяг, власні модулі або вимоги щодо того, де лежать дані.

Що ви отримуєте

  • Магазин на виділеному сервері з окремими контейнерами для веб-частини, бази й staging.
  • Root-доступ і всі паролі — у вас, а не лише в нас.
  • Налаштовані WAF і CrowdSec із винятками під ваші модулі оплати й доставки.
  • TLS з автоматичним оновленням сертифікатів.
  • Щоденні бекапи бази й медіа на окреме сховище і перевірене відновлення.
  • Staging, де можна безпечно пробувати оновлення.
  • Дашборди Grafana й алерти про проблеми.
  • Документацію: що де стоїть, як оновлювати, як відновитися з бекапу.

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