Оптимизация OpenCart: сервер душит магазин — 2 кейса с цифрами | Мастерская — статьи по WordPress, OpenCart и серверам | de-bor.ru

Частный web-мастер Денис Борисов
WordPress-сайтов

Оптимизация OpenCart: сервер душит магазин — 2 кейса с цифрами

Скорость и оптимизация · 2026-09-26 · обновлено 2026-09-26 · 14 мин чтения
Два магазина на OpenCart тормозили по-разному: один отдавал главную за 12 секунд холодным хитом, второй в пик сыпал 500-ми в 46% запросов. В обоих случаях проблема была не только в коде магазина, но и в серверной части: конфигурации, запросах, логировании и нагрузке. Ниже — цифры, команды и проверки из двух живых ремонтов.

Короткий вывод: что чинить первым

Дешевое и безопасное всегда идет первым. Включить gzip — сервер начинает отдавать около 50 КБ вместо 728 КБ, что особенно заметно на медленном мобильном соединении. Параллельно — вынести сканеров в deny и прикрыть тяжелый поиск лимитом: эти два шага снимают фоновую нагрузку с базы, пока вы разбираетесь с запросами.

Дальше — видимость. В этом кейсе первый фулскан нашелся в день включения slow log, а точечный индекс превращает выборку по заказам из 3.65 секунды в 0.001. Порядок диагностики: сначала замеры и дешевые шаги (gzip, лимиты, slow log), настройки FPM/fcgid — после, с замером до/после каждого шага. Логи ротировать обязательно: один раздутый error.log объемом около 330 МБ добавляет запись на каждый хит.

Отдельная ветка — жалобы с iPhone на частичную загрузку. Там свой нюанс с TLS 1.3, о нем ниже своим разделом. Не смешивать с общей оптимизацией.

Почему OpenCart упирается в сервер

Первая причина — несжатый HTML. OpenCart с темой Revolution собирает главную на 700+ КБ: сотни картинок в кеше, длинные списки товаров, прелоадер. Без gzip все это летит как есть, и на медленном мобильном интернете первая загрузка тянется секундами. Проверка занимает десять секунд: запросить страницу с заголовком Accept-Encoding и без, сравнить вес.

Вторая — ответы через диск и холодный пул PHP. В этом кейсе при дефолтных fastcgi_buffers большие ответы nginx складывал во временные файлы — это прямо видно по buffered to a temporary file в error.log. А пул PHP-FPM в режиме ondemand с idle timeout 10 секунд завершает простаивающие воркеры — после паузы следующий запрос может получить холодный старт.

Третья — слепые тяжелые запросы. База всего 340 МБ, а MySQL ест больше ядра CPU сутками. Значит, дело не в размере, а в кривых выборках: поиск с LIKE, глубокий OFFSET на page=54, фильтры без индексов. Без slow log вы этого не увидите — будете гадать.

Четвертая — боты и мусор. Сканep, перебирающий 1145 служебных URL с одного IP. Скраперы, листающие поиск до 19-й страницы. Раздутые журналы systemd, старые разборы логов в /tmp на 8 ГБ, storage/logs с позапрошлогодними файлами. Каждый пункт по отдельности мелочь, вместе — проценты CPU и гигабайты диска.

Кейс 1: магазин А — холодный TTFB, gzip и MySQL

Магазин на OpenCart 2.3.0.2 с темой Revolution 5.2.1 и каталогом около 34 тысяч товаров (33,9 тысячи позиций в базе на момент диагностики; в мае было 26,9 тысячи — каталог растет). Сервер: 4 ядра, 7.8 ГБ памяти, диск 78 ГБ, панель ISPmanager, связка nginx → PHP-FPM 7.4. Жалоба клиента звучала знакомо: первый заход грузится долго, потом нормально.

Замеры с ноутбука показали: TTFB главной 2.13 секунды холодным хитом и 1.63 теплым. Только TLS-рукопожатие занимало около 0.36 секунды, остальное — бэкенд. Категория /furnitura холодным хитом отвечала 12.66 секунды. HTML главной весил 728 837 байт, и gzip-тест подтвердил худшее: с заголовком сжатия и без вес одинаковый. Сжатие было выключено полностью, весь блок gzip в nginx.conf стоял закомментированным.

Диск был забит на 88%: 68 из 78 ГБ. Разбор показал 8.2 ГБ наших же старых разборов логов в /tmp, 3.9 ГБ журнала systemd, 145 МБ кеша пакетов и около 134 МБ протухших логов OpenCart за прошлый год. База при этом весила всего 339.5 МБ — не она съедала диск. Драйвером роста оказались картинки: кеш и каталог прибавили 5 ГБ за четыре месяца. Чистка безопасного мусора дала 68 → 56 ГБ, свободно стало 23 ГБ вместо 10.

Волна 1 заняла около трех часов и три reload nginx (R1, R2 плюс внеплановый R3 — сужение маски поиска). Gzip включили вместе с deny сканера одним reload: главная стала отдавать 49 964 байта вместо 728 837, минус 93%. Прогноз был скромнее, факт вышел лучше. Сканep 203.0.113.36, до этого получавший 404 и 301, в ту же минуту начал получать 403. Поиск прикрыли лимитом 10 запросов в минуту с burst 5 — но с первой попытки маска задушила живой ajax-подсказчик, который шлет 8 запросов за три секунды набора. Пришлось сузить маску до точного product/search и выставить статус 429 вместо дефолтного 503. Проверка: восемь подсказок — все 200, флуд из 12 поисков — 11 раз 200 и один 429.

Диагностика дала первый улов в тот же день: фулскан таблицы oc_order_product на 869 тысяч строк за 3.8 секунды. Таблица росла быстро — 97 МБ и 285 тысяч строк в мае, 125 МБ и 868 тысяч в сентябре. Точечный индекс по order_id создался за 11.8 секунд в тихом окне и превратил типовую выборку из 3.65 секунды в 0.001. Фикс в одну строку убрал notice темы Revolution, сыпавший сотнями записей в день. Отдельно закрыли netdata, торчавшую наружу без пароля, — теперь только через SSH-туннель. Похожий разбор несжатых страниц описан в статье как ускорить сайт без плагинов — механика gzip и буферов там та же.

Итог волны 1 TTFB главной около 2 секунд (замеры 1.8–3.4 с учетом шума), категория около 2 секунд (2.14 после волны 1, 1.9 после волны 2-мини). Критерий «без деградации вдвое» выполнен; пять минут наблюдений — 1929 ответов 200 и ни одного 500/502/503. MySQL при этом остался около 97%: дальше жгли глубокая пагинация и фильтры, это уже следующий заход.

Кейс 2: магазин Б — лавина 500-х, fcgid и сканер

Магазин ноутбуков на OpenCart 3.0.3.9. Каталог небольшой — 424 товара, то есть душила не витрина, а сервер. Сервер: Beget Cloud, Ubuntu 24.04, FASTPANEL2, nginx 1.28 + Apache 2.4.58 через mod_fcgid, PHP 7.4.33 на сайте, MySQL 8.0.44. Жалоба владельца: сайт не открывается на iPhone, в Москве и Петербурге.

Проверка на трех живых iPhone сайт открыла. Дальше смотрели логи за четыре дня: всего 2840 пятисотых, из них с iPhone — 54. Остальные 2786 — десктоп и боты. Вывод прямой: проблема не iOS-специфична, iPhone просто оказался тем экраном, на котором ее заметили. Пик пятисотых совпал по времени с активностью сканера 203.0.113.6 — 1200+ запросов в час с перебором /.git/objects. Вклады не изолировались, корректно говорить о совпадении и комплексе причин, а не о доказанной причине: в 15:00 — 10 пятисотых на 1466 запросов, в 16:00 — 1217 на 2620, это 46%, в 17:00 — 552 на 3970, в 18:00 — 6 на 1498. В тот же час один IP перебирал /.git/objects тысячами запросов — классический скан.

Механизм такой: PHP-воркер не успевал или рвалась связка Apache mod_fcgid на дефолтных таймаутах без recycle — в backend-логе в секунды пятисотых лежал ap_pass_brigade failed, Broken pipe с тем же IP. Усилители: флуд ботов, error.log объемом около 330 МБ с записью на каждый хит, полтора миллиона Notice и 400 тысяч Warning от OCMOD-модификаций, плюс .git на 2.3 ГБ прямо в webroot. Тела 500-х — около 14 КБ (замерено). Похоже на полный шаблон через бутстрап: если так, каждая ошибка стоит полного PHP-прохода. Это интерпретация, не замер.

Лечение шло комплексом из шести блоков: бан сканера и deny dotfiles на двух слоях, вынос .git за пределы webroot, fcgid с IOTimeout 90, BusyTimeout 300, MaxRequestsPerProcess 500 и MaxProcesses 150, выключение Notice и Deprecated в обход захардкоженного E_ALL в index.php и startup.php, ротация error.log с исходных около 330 МБ до 2.5 МБ в архиве, slow log с порогом 2 секунды и healthcheck трех страниц с iPhone user-agent каждые пять минут. Проверка тем же калибром, что ночью давал 10 из 10 пятисотых: после фикса 10 из 10 ответов 200 за 0.5–1.9 секунды, 39 запросов в минуту — ноль пятисотых. Разбор кодов ответа сервера подробнее есть в материале про ошибку 500 — логика чтения access и error логов переносится один в один.

Честные цифры Худший час: 46% пятисотых → 1.2%. Среднее за сутки: около 710 в день → 37 в день, финальный срез 37 на 23102 (0.16%). Сравнение «в 290 раз» по пиковому часу против суток некорректно и в статью не пошло. Slow log пуст 48 часов, страницы около секунды при низкой нагрузке.

Здесь нужна оговорка, которую подтвердил независимый аудит 26 сентября: менялись бан, fcgid, error_reporting, логирование и .git одновременно, поэтому вклады по отдельности не изолированы. Корректная формулировка — комплекс устранил массовый сценарий. Один бот с 6 запросов в секунду за 3 секунды все еще кладет /search — порог отказа единичных rps смягчен, но не закрыт.

Нюанс TLS 1.3 и iPhone: что сработало, чего не знаем

Отдельная история магазина Б, и ее просили рассказать обязательно. Жалоба: iPhone на iOS 26.6.1, любая страница грузится частично — видны куски, пустые блоки, дальше не идет. Во всех браузерах сразу, потому что на iOS один WebKit. Во всех сетях: два проводных провайдера и два мобильных. С VPN и без. Время фиксации — 16:07.

Логи за 16:00–16:25 не показали серверной причины: ноль 500/502/503, healthcheck зеленый весь день. Массовый 5xx-сценарий исключен, но это не доказывает отсутствие любой другой серверной или сетевой проблемы. С 16:00 до 16:25 — ноль 500/502/503, только 200/206/304 и бот-404. Healthcheck весь день зеленый: 200 за 0.3–0.7 секунды. Нагрузка 0.2, свободно 5.5 ГБ памяти, диск наполовину пуст, MySQL slow — ноль. HTML для iPhone и десктопа байт в байт одинаковый.

Помог совет поддержки Beget: отключить TLS 1.3, оставить 1.2. Владелец подтвердил — частичная загрузка ушла. Тот же прием помог второму проекту. Но механизм спорный, и молчать об этом нельзя: симптом сохранялся с VPN, так что сводить все к провайдерскому пути нельзя. Аудит прямо запретил называть HTTP/2 причиной частичного рендера — доказано только то, что 242 запроса по HTTP/1.1 замедляют загрузку. Честная позиция: фикс сработал дважды, причина на уровне сети и стека не установлена.

Грабли nginx при этом вполне конкретные и их стоит знать. Директива ssl_protocols в server-блоке сайта не работает — версию диктует default_server. Рабочая точка оказалась в conf.d/parking.conf с server_name _. В http-контекст директиву ставить нельзя: там висит listen 443 quic, которому нужен 1.3. Проверка простая: openssl с флагом tls1_3 должен получить alert protocol version, с tls1_2 — успешное соединение.

openssl s_client -connect example.ru:443 -tls1_3
openssl s_client -connect example.ru:443 -tls1_2

Для TLS 1.3 ожидаем отказ с alert protocol version, для TLS 1.2 — успешное соединение. HTTP 200 дополнительно проверяется обычным HTTPS-запросом. И помнить: FASTPANEL перезаписывает конфиг сайта при работах в панели, строки проверять после. У магазина А, кстати, тоже давно стоит только TLSv1.2 — решение еще с июля.

Не делать всем подряд Отключение TLS 1.3 — точечный фикс под конкретный симптом, а не базовая оптимизация. Без жалоб на частичный рендер с iPhone трогать протоколы не нужно. Сначала логи, healthcheck и замеры, потом протоколы.

Чеклист ремонта: 7 шагов с командами

Шаг 1. Снять эталоны до любых правок. Два замера curl главной и категории, df, хвост error.log как образец нормы. Без эталонов потом не доказать, что стало лучше.

curl -o /dev/null -s -w "ttfb %{time_starttransfer} total %{time_total} code %{http_code} size %{size_download}\n" https://example.ru/
curl -o /dev/null -s -H "Accept-Encoding: gzip" -w "gzip-size %{size_download} code %{http_code}\n" https://example.ru/
df -h /
nginx -t

Шаг 2. Включить gzip в http-контексте nginx.conf и проверить вес. Картинки и архивы не трогать, добавить в типы image/svg+xml.

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

Шаг 3. Задать fastcgi_buffers, чтобы большие ответы перестали складываться на диск. Ориентир из живых конфигов:

fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;

Шаг 4. Включить MySQL slow log без рестарта и закрепить drop-in навсегда. Порог — 2 секунды. На Beget Cloud и Timeweb путь к конфигам подскажет панель, сам прием одинаковый.

SET GLOBAL slow_query_log = 1, slow_query_log_file = '/var/log/mysql/mysql-slow.log', long_query_time = 2;
-- навсегда: /etc/mysql/mariadb.conf.d/99-shop-slow.cnf
-- ротация уже покрывается /etc/logrotate.d/mysql-server (проверить, что маска включает slow-лог)

Нужны права SUPER/root: в кейсе у site-юзера их не было, включали через root-socket. SET действует до рестарта MySQL, навсегда — только drop-in.

На Reg.ru с VPS и ISPmanager прием тот же, но после любых операций панели сверяйте конфиг: ISPmanager умеет молча вернуть дефолты, как это было с gzip-блоком и путями логов в первом кейсе.

Шаг 5. Найти главного пожирателя в slow log и дать точечный индекс в тихом окне. Пример из кейса: создание заняло 11.8 секунды, типовая выборка стала отвечать за миллисекунды.

EXPLAIN SELECT * FROM oc_order_product WHERE order_id = 12345;
ALTER TABLE oc_order_product ADD INDEX idx_order_id (order_id);

Шаг 6. Вынести сканеров в deny и прикрыть тяжелый поиск. Отдельный файл в vhosts-resources, один reload. Маску лимита — только на точный product/search, иначе задушите живой ajax-подсказчик.

deny 203.0.113.36;
# http-контекст, один раз (в кейсе — отдельный search-limit.conf):
limit_req_zone $binary_remote_addr zone=search:10m rate=10r/m;
# server/location, только на точный поиск:
limit_req zone=search burst=5 nodelay;
limit_req_status 429;

Шаг 7. Почистить безопасный мусор и закрыть торчащие сервисы. Наши старые разборы в /tmp, журнал старше недели, протухшие логи storage — в архив локально, потом удаление. Netdata — только на localhost, смотреть через SSH-туннель. После каждой правки в панели ISPmanager или FASTPANEL проверять конфиг: панели перезаписывают index, rewrite SEO-URL и пути логов.

journalctl --vacuum-time=7d
ls -la /tmp/all_logs*.txt   # файлы конкретного кейса (магазин А) — сверить перед удалением
rm /tmp/all_logs.txt /tmp/all_logs2.txt
ssh -L 19999:localhost:19999 root@203.0.113.10

Проверка результата

После каждого шага — свой замер, не в конце все разом. TTFB главной и категории до и после, вес страницы с gzip и без, diff slow log, df, хвост access по кодам, две минуты error.log без emerg и crit. Критерии отката простые: 500 или 502 на эталонах, TTFB вдвое дольше пяти минут, новые emerg/crit, не открывается корзина даже на чтение. Любой пункт — откатить вызвавший шаг сразу.

Сводно, ДО → ПОСЛЕ. Магазин А (каталог около 34 тысяч товаров): главная 728 837 байт → 49 964; TTFB главной 2.13/1.63 с → около 2 с; furnitura холодным хитом 12.66 с → около 2 с; выборка заказов 3.65 с → 0.001 с; диск 68 ГБ/88% → 56 ГБ/72%; пять минут наблюдений — 1929 ответов 200 без 500/502/503. Магазин остался работать штатно при растущем каталоге; честная оговорка — MySQL держится около 97%, глубокая пагинация и фильтры ушли в следующий заход. Магазин Б: худший час 46% пятисотых → 1.2%; фон 710 в день → 37 в день (срез 37 на 23102); нагрузочный калибр 10 из 10 пятисотых → 10 из 10 двухсотых за 0.5–1.9 с.

Когда способ не сработает

Глубокая пагинация лечится не сервером. Листалки вида page=54 с полумегабайтом HTML — это тяжелые OFFSET-запросы, их режут лимитами выдачи и robots-правилами для поиска, а не буферами. Один настойчивый бот с 6 запросов в секунду все равно положит /search — там нужен отдельный порог на уровне веба, у магазина Б он остался в бэклоге.

PHP 7.4 с истекшей поддержкой — отдельный долг, не часть ремонта. Смешивать его с ликвидацией лавины 500-х нельзя: обновление мажорной версии PHP на OpenCart с OCMOD и старой темой — свой проект со своим окном. То же с публичным файлменеджером в afm и дампами БД в webroot: это следующий слой P0 по безопасности, а не причина прошлой лавины.

Обмен с 1С живет своей жизнью: TEMP-каталог, ночные выгрузки по 10 ГБ, сотни запросов в сутки. Его не трогать без окна и без владельца — одна чистка не в том часу остановит обмен. И диск сам по себе TTFB не дает, но при 9.8 ГБ свободно одна полная выгрузка плюс пик логов упираются в 95% — чистить до пика, не после.

Частые вопросы

Gzip не поднимет нагрузку на CPU?
Нагрузка на CPU немного увеличивается, потому что сервер дополнительно сжимает текст. В данном кейсе отдельного замера прироста CPU от gzip не проводили. Сжимается только текст и только для браузеров, которые умеют сжатие, — то есть всех. Картинки и архивы идут как есть. Проверка — четыре эталонные страницы: код 200, заголовок Content-Encoding, вес в районе 50–160 КБ. Откат — одной строкой и reload за секунды.
Лимит на поиск не заденет живых покупателей?
Лимит 10 запросов в минуту с burst 5 вешается только на точный route product/search. Категории, карточки и корзина не затрагиваются. Живой человек не ищет каждые 5 секунд минуту подряд. При превышении заданного rate/burst nginx возвращает 429; состояние лимита постепенно восстанавливается по заданной скорости. Подсказчик автокомплита под лимит не подводить — маску держать узкой.
Отключать ли TLS 1.3 на своем магазине?
Только при конкретном симптоме: iPhone грузит страницы частично, а логи сервера чистые и healthcheck зеленый. Без этого симптома протоколы не трогать. Помнить про грабли: версию диктует default_server, в http-контекст при quic директиву ставить нельзя, после работ в FASTPANEL строки проверять заново.
Можно ли чистить кеш картинок image/cache?
Технически да, он перегенерируется. Практически — только с решения владельца: в кейсе клиент просил оставить, там лежал архив images.zip на 9.8 ГБ с нужными исходниками. Безопасный мусор — свои старые разборы в /tmp, журнал старше недели, протухшие логи. Кеш и каталог — после согласования.
Хватит ли включения slow log, чтобы найти все тормоза?
Для первого улова обычно достаточно: в этом кейсе фулскан на сотни тысяч строк нашелся в день включения slow log. Дальше нужны EXPLAIN конкретных запросов, request_time в access.log и разбор глубокой пагинации. Slow log показывает что тормозит, а не почему это вообще запрашивают — вторую половину дают access.log и разбор поведения ботов.

OpenCart тормозит или сыплет 500-ми? Посмотрю логи и скажу, что душит сервер

Диагностика за 1 день: эталоны, slow log, боты, конфиги. Дальше — волны фиксов с замерами.

Написать в Написать в

Техническая оптимизация

Техническая оптимизация

Скорость, кэш, Core Web Vitals.

7.200

Подробнее
Сопровождение и поддержка сайта

Сопровождение и поддержка сайта

Мониторинг скорости и оптимизация.

от 5.400 ₽/мес

Подробнее

Разрабатываю WordPress-сайты

Лендинги, многостраничные сайты, интернет-магазины на WooCommerce — всё на WordPress с удобной панелью управления.

Сайт под ключ: регистрация домена и хостинга, установка WordPress, настройка шаблона и модулей.

Поддерживаю WordPress-сайты

Обновление плагинов и тем, резервное копирование, мониторинг работоспособности — сайт работает без сбоев.

Оперативное исправление ошибок, создание новых разделов, доработка функционала и наполнение контентом.

Продвигаю WordPress-сайты

SEO-оптимизация, настройка Яндекс Метрики и Вебмастера, подключение Google Search Console.

Оптимизация позволяет «поднять» сайт в поисковых выдачах, увеличить целевой трафик и привлечь новых клиентов.

Чистка от вирусов WordPress

Если сайт взломали, появился подозрительный код или спам-рассылка — найду и удалю вредоносный код, закрою уязвимости и настрою защиту от повторного заражения.

После чистки проверю все файлы и плагины, обновлю WordPress до актуальной версии и настрою автоматическое резервное копирование.

Диагностика сайта

Проверю ваш сайт по ключевым параметрам и подготовлю отчёт с рекомендациями:

  • Скорость загрузки и производительность;
  • Безопасность и уязвимости;
  • SEO-состояние и индексация;
  • Мобильная адаптация;
  • Технические ошибки и код.
Заказать диагностику
Михайлова Анастасия

Денис МАСТЕР своего дела. Вёл целый проект, работали с ним на протяжении 4х месяцев. Отзывчивый, понимающий с полуслова специалист. Стоимость услуг радует, а качество работы приводит в восторг.

Денис спасибо Вам от лица нашей строительной компании и от всего нашего персонала.

Михайлова Анастасия

Игорь Караваев

Обратился к Денису для восстановления сайта на WordPress после сбоя. Сделал, как и обещал, за сутки — сайт снова работает без ошибок. Профессионал своего дела, доходчиво объясняет, вежлив и тактичен. Однозначно рекомендую!

Игорь Караваев

Яна Веркулич

Денис, спасибо огромное за работу)) Очень тепло вспоминаю Вас и все что Вы сделали для моей работы и моего сайта.

Денис Профессионал с большой буквы, решает любые вопросы, отличный специалист))

Рекомендую к сотрудничеству, еще раз спасибо)

Яна Веркулич

Бюро Переводов

Денис оперативно и грамотно справляется со всеми поставленными задачами. Внес правки на англоязычную и русскоязычную версии сайта, учел все пожелания. Будем обращаться еще!

Бюро Переводов

Анастасия Виричева

Денис мастер своего дела, рекомендую его как специалиста.
Понимает, что нужно сделать и справляется с поставленной задачей в короткое время.

Делал сайт для салона красоты, просто и функционально.

Анастасия Виричева

Владимир

Очень много времени мучались с сайтом на OpenCart. «Специалисты» не могли нормально разобраться в проблеме, возникавшей при выполнении элементарной задачи.

Денис сделал это в два счета, также расписал подробно, в чем была проблема и как она решена. На 200% доволен. Даже не хочется его рекомендовать, потому что будет постоянно занят))

Владимир

Ксения Петровская

Денис оперативно ответил и помог решить проблему, которую я даже описать нормально не могла)) Мы сами что-то накрутили с корпоративной почтой — письма то уходили, то нет, в общем всё сломали.

Денис всё починил, теперь у нас нормальная почта, домен работает, письма приходят и уходят. Цена как заявлена — оплатили по факту проверки. Спасибо большое!

Ксения Петровская

Александр Кривуля

Заказал у Дениса доработать сайт на WordPress. При этом трудно себе представлял, что сам хочу. Благодаря профессионализму Дениса и его умению всё грамотно и просто объяснять, предлагать разные варианты решений — цель была достигнута.

Умение общаться доходчиво и терпеливо с клиентами — огромный плюс. Я очень доволен. Однозначно рекомендую!

Александр Кривуля

Кондитер мания

Прекрасный специалист, ответил и устранил ошибку на сайте за пару часов, сохранила контакт, будем по необходимости обращаться. Рекомендую!

Кондитер мания

Бесплатная настройка хостинга и домена

Регистрация хостинга на 1 месяц и домена .ru/.рф на 1 год входит в стоимость разработки сайта.

Подробнее