Зазвичай до нас приходять у двох випадках. Перший — у вас один-два важливі сайти на shared-хостингу, і їм там тісно: сайт гальмує в години пік, ліміти невідомо які, а коли щось ламається, підтримка відповідає шаблоном. Другий — ви веб-студія, у вас десятки клієнтських сайтів, розкиданих по різних хостингах і VPS, і ніхто вже точно не скаже, де яка версія PHP і коли востаннє робили бекап.
Болить в обох випадках однаково. Один заражений сайт тягне за собою сусідів. Оновлення плагіна кладе головну сторінку в п’ятницю ввечері. Листи з контактної форми падають у спам. А бекап, як з’ясовується, є, але відновити з нього ніхто не пробував.
Що ми робимо
Ставимо платформу на виділеному сервері (OVH або Hetzner) або на віртуальній машині у вашому Proxmox і доводимо її до стану, коли сайти просто працюють.
- Nginx + PHP-FPM. Кожен сайт має окремого системного користувача і свій пул PHP-FPM. Сайт не бачить файлів сусіда, а «важкий» сайт не забирає всі воркери. Кілька версій PHP живуть поруч: старий сайт на 7.4 не заважає новим на 8.3.
- Кеш. OPcache для PHP, FastCGI-кеш у Nginx для анонімних відвідувачів, Redis для об’єктного кешу там, де плагіни його підтримують.
- Бази даних. MariaDB з окремим користувачем на кожен сайт і без доступу ззовні.
- TLS. Сертифікати Let’s Encrypt випускаються й поновлюються самі, з моніторингом терміну дії.
- Захист. Обмеження частоти запитів на
wp-login.phpіxmlrpc.php(або повна заборона xmlrpc, якщо він не потрібен), CrowdSec або fail2ban на логах Nginx і SSH, за потреби — WAF перед сайтами. - Пошта. Сайти шлють листи через нормальний SMTP з SPF, DKIM і DMARC, а не через голий
mail()з адресою, яку ніхто не підписав. - Бекапи й моніторинг. Щоденні копії файлів і баз на окреме сховище, перевірка доступності кожного сайту і термінів сертифікатів, сповіщення в Telegram або на пошту.
Панель чи чиста конфігурація
Тут два шляхи, і жоден не кращий у всьому.
Панель типу HestiaCP зручна студії. Менеджер сам створить сайт, поштову скриньку чи базу для нового клієнта, і йому не треба для цього писати адміну. Ми самі тримаємо частину своїх сайтів на HestiaCP. Але панель — це ще одна річ, яку треба оновлювати і стежити за її вразливостями. До того ж вона має власні уявлення про те, де лежать конфіги, і ручні правки поверх неї можуть зникнути після оновлення.
Чиста конфігурація через Ansible підходить, коли сайтів небагато або вони важливі й рідко змінюються. Усе описано в репозиторії: віртуальні хости, пули PHP, користувачі, cron. Сервер можна відтворити з нуля, а будь-яку зміну видно в історії Git. Зате новий сайт додає той, хто вміє запустити плейбук.
Часто робимо гібрид: панель для щоденної роботи студії, а базову систему, захист, моніторинг і бекапи — через Ansible поза панеллю.
Окремо про репозиторії. Свіжі версії PHP на Debian зазвичай беруть зі стороннього репозиторію, і в нього часом спливає ключ підпису. Тоді apt update тихо перестає приносити оновлення безпеки. Такі речі ми ловимо моніторингом, а не випадково через пів року.
Оновлення: ламає не сервер, а плагіни
Із досвіду: сервер падає рідко. Сайти ламаються після оновлення плагіна, теми чи ядра CMS. Тому автоматичні оновлення без перевірки — погана ідея, а ручні щоразу відкладають.
Схема така: сайт копіюється на staging, там проходять оновлення, далі автоматична перевірка — головна сторінка, кілька ключових URL, кошик чи форма, пошук PHP-помилок у лозі. Якщо все гаразд, ті самі оновлення йдуть на продакшн. Якщо ні — продакшн не чіпаємо, а ви отримуєте звіт, що саме зламалось.
wp core update --minor
wp plugin update --all --exclude=woocommerce
wp core verify-checksums
curl -fsS -o /dev/null -w '%{http_code}\n' https://staging.example/
Великі релізи, WooCommerce, платні плагіни з ліцензією — оновлюємо вручну і з попередженням. Для Joomla принцип той самий, тільки інструменти інші.
Коли це не підходить: якщо сайт сильно переписаний «по живому» і жодна копія не поводиться як оригінал, спершу доведеться навести лад у самому коді. Це окрема робота.
Бекапи й міграція
Бекап, з якого ніхто не відновлювався, — це надія, а не бекап. Тому ми регулярно й автоматично розгортаємо копію сайту з бекапу в ізольованому середовищі й перевіряємо, що вона відкривається і база ціла.
Міграцію з shared-хостингу робимо без простою: переносимо файли й базу, перевіряємо сайт на новому сервері через підміну в hosts, заздалегідь знижуємо TTL у DNS, наостанок синхронізуємо зміни і перемикаємо записи. Пошту переносимо окремо, разом зі старими листами, якщо вона жила на тому ж хостингу.
Що ви отримуєте
- Сервер, повністю оформлений на вас: root-доступ, доступ до панелі, якщо вона є.
- Ізольовані сайти з власними користувачами, пулами PHP і базами.
- Оновлення через staging і звіт після кожного циклу.
- Захист логіну, xmlrpc і SSH, сертифікати, що поновлюються самі.
- Налаштовані SPF, DKIM і DMARC — листи з сайтів доходять до адресатів.
- Бекапи на окреме сховище з регулярною перевіркою відновлення.
- Моніторинг доступності й сповіщення, які отримуєте і ви.
- Документацію: що де стоїть, як додати сайт, як відновитися з бекапу.
Якщо у вас один сайт, якому тісно на shared-хостингу, або студія з десятками клієнтів і зоопарком серверів — напишіть, скільки сайтів і де вони зараз живуть. Подивимось і запропонуємо, як це звести в одне місце.