
RoutersUA — український інтернет-магазин, що спеціалізується на роутерах GL.iNet. Дизайн і розробку сайту виконав Олег (Telegram: @lexterr2), і саме його робота визначає вигляд і зручність магазину.
У цій статті розповідаємо, як у жовтні 2026 року ми перенесли магазин на новий сервер і оновили його програмну платформу, зберігши створений Олегом дизайн.
З чого ми починали (15 жовтня 2026 року)
Магазин працює на ocStore — локалізованій версії OpenCart — із комерційною темою upStore. Коли ми взялися за роботу, хостинг і застаріле програмне середовище мали серйозні технічні та експлуатаційні проблеми:
- Застаріле програмне забезпечення і ненадійний хостинг. Магазин працював на ocStore 3.0.3.7 на віртуальному хостингу TheHost під PHP 7.3, оновлення безпеки для якого припинилися ще у 2021 році. Сайт обслуговувала зв’язка nginx + Apache, а доступу root до сервера ми не мали.
- Збої під час оформлення замовлення. Покупці скаржилися на проблеми з оформленням замовлення та вибором доставки Новою поштою. Ми відтворили проблему: одне з трьох тестових замовлень не оформилося, причому без жодного повідомлення — кнопка оформлення просто зникла. Причиною був стан гонитви (race condition) в обробці сесій: номер замовлення міг зникнути із сесії між двома запитами. Журнал помилок показав, що такий збій траплявся ще з травня.
- Помилки на очах у відвідувачів. Повідомлення про помилки PHP, зокрема з внутрішніми шляхами до файлів на сервері, з’являлися на загальнодоступних сторінках.
- Перевантажений хостинг. За 30 годин Cloudflare зафіксував близько 400 тайм-аутів і понад 300 відповідей 429 Too Many Requests (забагато запитів) від TheHost. Під удар потрапляли сторінки товарів, оформлення замовлення і навіть власні JavaScript-файли сайту.
- Повільне завантаження. У мобільному тесті Google Lighthouse головна сторінка отримала 60 балів за ефективністю. Основний вміст з’являвся лише через 4,2 секунди.
- Слабкий захист на рівні Cloudflare. Cloudflare підключався до сервера без перевірки його сертифіката, досі дозволяв TLS 1.0, і жодних правил брандмауера не було розгорнуто.
Як ми працювали
Раніше проєкт обслуговувався через панель керування хостингом, FTP і SSH із дуже обмеженими можливостями. Ми перенесли проєкт у репозиторій на GitHub і фіксували там кожне спостереження, рішення, зміну та наші скрипти — в одній історії з контролем версій.
Ми дотримувалися двох правил:
- Спершу підтвердити проблему фактами і лише потім її виправляти, зазначаючи джерело.
- Перевіряти кожну зміну на окремому сервері, перш ніж розгортати її в робочому магазині.
За п’ять днів роботи в репозиторії з’явилося понад 200 комітів.
1. Новий сервер (15 жовтня)
Ми розгорнули новий сервер у Hetzner: 4 віртуальні процесори, 8 ГБ оперативної пам’яті, Debian 13, nginx, PHP, MariaDB і Redis. Разом з оплатою IPv4-адреси це коштує близько 10,60 доларів на місяць.
Сервер повністю налаштовується скриптом з одного конфігураційного файлу, тож його розгортання відтворюване й не залежить від ручних дій.
2. Оновлення й виправлення (15–16 жовтня)
Оновлення з ocStore 3.0.3.7 до 3.0.4.1 ми перетворили на послідовність скриптів і неодноразово відпрацювали її на копії робочих даних.
Нова версія спричинила проблеми сумісності з частиною теми та її доповнень, а в самому ocStore і доповненнях сторонніх розробників були давні помилки. Усі виправлення ми зібрали в один патч сумісності, який наразі містить 57 задокументованих виправлень.
Серед них:
- стан гонитви під час оформлення замовлення, який був і в старій версії: виправлено блокуванням на рівні сесії;
- некоректне збереження номерів телефону, якщо покупець вводив їх із кодом країни;
- кнопка купівлі, яка спрацьовувала із затримкою;
- численні дефекти теми upStore, які проявилися на новій версії ocStore.
3. Перемикання (16 жовтня, 13:44 за київським часом)
Перехід відбувався за чітко визначеною послідовністю:
- Перевели старий магазин у режим обслуговування і зробили останню резервну копію.
- Скрипт імпорту переніс замовлення й дані покупців за 118 секунд.
- Змінили DNS-записи, щоб трафік ішов на новий сервер.
- Протягом хвилини оформили тестове замовлення.
Перша спроба безпечно зупинилася: не пройшла перевірка сертифіката. Ми знайшли й усунули причину і лише тоді продовжили.
4. Швидкість
Після перенесення ми зосередилися на тому, щоб сторінки швидше завантажувалися, швидше реагували на дії відвідувачів, а навігація відчувалася жвавішою.
- Прибрали зайве навантаження. Одна з функцій Cloudflare додавала на кожну сторінку ще один тег Google. Ми її вимкнули.
- Сторінки віддаються з мережі Cloudflare. Сторінки магазину тепер кешуються й надходять до відвідувачів із серверів Cloudflare зі стисненням Brotli.
- Пришвидшили перше відображення. CSS, потрібний для першого відображення сторінки, ми вбудовуємо безпосередньо в неї. Скрипти завантажуються, не блокуючи відображення, а аналітика запускається після першої взаємодії відвідувача зі сторінкою.
- Зменшили зміщення макета. Виправили слайдер, який затримував перше відображення сторінки, і прибрали зміщення макета на мобільних пристроях.
- Миттєве повернення назад. Коли відвідувач повертається назад, більшість сторінок тепер відновлюється безпосередньо зі зворотного кешу браузера, а не завантажується повторно.
Результати
- Мобільна оцінка Lighthouse за ефективністю для головної сторінки зросла з 69 балів одразу після перенесення до 92–93 після прогрівання кешу. Сторінки товарів отримують до 100 балів, сторінки категорій — до 99.
- Дані реальних користувачів за перші три дні, 75-й процентиль (три з чотирьох відвідувань не гірші за ці значення):
- основний вміст з’являється за 0,5–0,9 секунди;
- сторінка реагує на дотик за 32–72 мілісекунди;
- зміщення макета мінімальні.
- Усі ці показники впевнено вкладаються в пороги, які Google вважає добрими.
5. Доступність і якість
Ми також зробили магазин доступнішим, зокрема для відвідувачів, які користуються допоміжними технологіями.
- Виправили недостатній колірний контраст, вміст, що виходив за межі блоків, і елементи керування без доступних назв. Підписи для програм зчитування з екрана тепер українською.
- Провели автоматичний аудит доступності інструментом axe для всіх типів сторінок, зокрема для сторінки помилки 404.
- Отримали 100 балів Lighthouse у категоріях Доступність, Оптимальні методи та SEO.
6. Безпека (аудит 18 жовтня)
Ми посилили захист на рівні мережі, сервера та застосунку.
З’єднання
- Cloudflare тепер перевіряє TLS-сертифікат сервера.
- З’єднання можливі лише через TLS 1.2 або новіший.
- HSTS (HTTP Strict Transport Security) вказує браузерам відкривати сайт лише через HTTPS.
Мережевий периметр
- Розгорнуто керовані правила брандмауера Cloudflare, зокрема набір правил OWASP, а також обмеження частоти запитів.
- Майже одразу наші налаштовані правила заблокували сканер, що шукав відкритий конфігураційний файл.
- Сервер приймає вебтрафік лише через Cloudflare.
Адмінпанель і API
- Адмінпанель захищена Cloudflare Access: для входу потрібен одноразовий код, який надходить електронною поштою.
- Доступ до API магазину дозволено лише з відомих адрес.
Застосунок магазину
- Під час входу сесія користувача оновлюється.
- Паролі зберігаються у вигляді хешів Argon2id.
- Файли cookie налаштовано з урахуванням вимог безпеки.
- Відповіді сервера містять заголовки безпеки.
- Налаштовано політику безпеки вмісту (Content Security Policy, CSP).
- jQuery оновлено до версії 3.7.1.
Сервер
- SSH-доступ дозволено лише з IP-адрес нашого офісу.
- Файли магазину щодня перевіряються на несанкціоновані зміни.
- На сервері працює лише PHP 8.5, старіші версії видалено.
- Оновлення безпеки встановлюються автоматично. Якщо нове ядро потребує перезавантаження, сервер перезавантажується рано вранці.
7. Надійність і обслуговування
Безпека й швидкість — лише частина картини. Магазин має ще й надійно відновлюватися після збоїв і залишатися простим в обслуговуванні.
Резервне копіювання та відновлення
- Зашифровані резервні копії зберігаються поза сервером. База даних копіюється щогодини, змінені файли — щодня, повна копія створюється щотижня.
- Ми перевірили відновлення на практиці: скрипт відновлення розгорнув повну робочу копію магазину на новому сервері за 4 хвилини 17 секунд.
- Ця копія тепер слугує тестовим середовищем для routersua.com. Кожну зміну спершу перевіряємо там, а вже потім переносимо в робочий магазин.
Автоматичне відновлення
- Сервер перевіряє власний стан кожні 15 хвилин.
- Служби, що дали збій, перезапускаються автоматично, а ліміт спроб не дає їм зациклитися на перезапусках.
- Кожен збій записується в журнал.
- Сервер має фіксовану мережеву адресу, а захисний механізм під час завантаження повертає попередні мережеві налаштування, якщо нові не працюють.
Інтеграція з Новою поштою
- Довідники міст і відділень — близько 11 000 міст і 55 000 відділень — тепер надійно оновлюються нашим власним завантажувачем.
- Окремий запобіжник не дає випадково змінити дані відправника в Новій пошті.
- Виправлено помилку збереження форми на сторінці експрес-накладної, а сам процес налагоджено.
Пошта й товарні фіди
- Уся пошта, і вхідна, і вихідна, проходить через Cloudflare, а поштовий домен додатково захищено.
- Ми залишили лише ті товарні фіди, які справді використовуються: для Google, Meta і нашої внутрішньої системи управління товарною інформацією (PIM).
Що маємо зараз
RoutersUA сьогодні швидший, безпечніший, стійкіший до збоїв і простіший в обслуговуванні, ніж будь-коли раніше.
Ідеться не лише про бали в тестах. Оформлення замовлення знову працює коректно, інфраструктуру можна відтворити, резервні копії перевірено на практиці, а захист налаштовано на рівні мережі, сервера й застосунку.
Не менш важливо, що кожну зміну можна простежити до її причини й доказів, на яких вона ґрунтується. У результаті маємо не просто швидшу роботу магазину, а надійнішу систему, яку легше підтримувати, — із задокументованою історією та відтворюваним процесом для подальших покращень.
Роутери GL.iNet, які ми продаємо, зібрані в каталозі: Wi-Fi роутери і портативні стільникові маршрутизатори.