Поддержка и абонентское обслуживание

Тестовая копия сайта: как обновлять без риска положить продакшн

Как поднять staging на поддомене за час, чем он отличается от локалки, как переносить изменения обратно и не забыть про robots.

обновлено 8 минут чтения 6 Дмитрий Акиндинов
Содержание
  1. Зачем копия, если обновления обычно проходят нормально
  2. Поддомен на том же хостинге за час
  3. Обязательное: закрыть от индексации, отключить почту и платежи
  4. Что проверять на копии перед обновлением боевого сайта
  5. Обратный перенос: почему копировать базу обратно опасно
  6. Когда копия не нужна и хватает бэкапа
  7. Частые вопросы

Тестовая копия на поддомене того же хостинга поднимается за час-полтора. Обязательных условий три: закрыть от индексации, отключить отправку почты и выключить приём платежей. Без этого копия начнёт слать письма клиентам и попадёт в поиск как дубль.

«У меня 90 обновлений накопилось, и я боюсь их ставить, потому что в прошлый раз всё легло на два часа в рабочий день». Слышу такое от владельцев сайтов чаще, чем хотелось бы. Обычно решение простое: не бояться, а сначала проверить обновление на копии сайта, которая живёт отдельно от боевой версии. В этой статье покажу, как поднять такую копию на обычном shared-хостинге за час без покупки отдельного сервера, что на ней обязательно закрыть от посторонних глаз и как правильно переносить проверенные изменения обратно.

Два одинаковых окна браузера рядом, одно помечено гаечным ключом

Зачем копия, если обновления обычно проходят нормально

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

Магазин на WooCommerce, обновление плагина оплаты. Новая версия поменяла формат хука обработки платежа, интеграция с эквайрингом перестала передавать статус заказа. Заметили через четыре часа, когда клиент пожаловался, что оплатил, а заказ висит в статусе «ожидание оплаты». Если бы обновление сначала прогнали на копии и сделали тестовый платёж, поймали бы за пять минут.

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

Визитка на WordPress, крупное обновление темы. Автор темы переписал систему хуков между мажорными версиями. После автообновления часть кастомных стилей, которые правил я сам поверх темы, перестала подключаться, сайт выглядел так, будто из него вынули половину CSS. На копии это увидели бы сразу на главной странице.

Общий знаменатель всех трёх историй: проблема не в том, что обновления плохие, а в том, что взаимодействие конкретной версии плагина, конкретной темы и конкретного кастомного кода непредсказуемо без проверки. Копия сайта превращает «мы узнаем, сломалось или нет, когда клиент напишет» в «мы узнаем за десять минут до того, как это увидит хоть один посетитель».

Поддомен на том же хостинге за час

Самый практичный вариант для сайта на shared-хостинге, отдельный поддомен вроде test.ваш-сайт.ru или staging.ваш-сайт.ru, который физически живёт в отдельной папке того же хостинг-аккаунта. Не нужен отдельный сервер, не нужна отдельная оплата, только немного места на диске.

Порядок действий для WordPress (для Битрикса и других CMS логика та же, отличаются только пути и таблицы):

  1. Создать поддомен в панели хостинга, направить его на папку, например /staging/.
  2. Скопировать файлы сайта в эту папку.
cp -r public_html/* public_html/staging/
  1. Создать отдельную базу данных и импортировать в неё дамп боевой базы.
mysqldump -u user -p production_db > dump.sql
mysql -u user -p staging_db < dump.sql
  1. Прописать в конфиге копии новые данные подключения к базе (для WordPress это wp-config.php, для Битрикса bitrix/php_interface/dbconn.php).
  2. Заменить в базе все упоминания основного домена на адрес поддомена. Прямой SQL-запрос для WordPress:
UPDATE wp_options SET option_value = replace(option_value, 'https://ваш-сайт.ru', 'https://staging.ваш-сайт.ru') WHERE option_name = 'siteurl' OR option_name = 'home';

Для полной замены по всем таблицам, включая сериализованные данные в постах и настройках плагинов, руками SQL уже опасен: обычный REPLACE ломает длину строки внутри сериализованного массива, и WordPress перестаёт читать эти данные. Здесь нужен инструмент, который умеет пересчитывать длины при замене, например WP-CLI:

wp search-replace 'https://ваш-сайт.ru' 'https://staging.ваш-сайт.ru' --all-tables

На типовом сайте визитки или сайта услуг весь процесс занимает от 40 минут до полутора часов в зависимости от размера базы и опыта. Для крупного магазина с большой базой заказов время увеличивается пропорционально размеру дампа.

Обязательное: закрыть от индексации, отключить почту и платежи

Копия, которая видна поисковику и принимает настоящие платежи, это не тестовый стенд, а дублирующий источник проблем. Три вещи, которые нужно сделать сразу после создания копии, ещё до первого теста.

Закрыть от индексации. В файл robots.txt поддомена (не основного сайта, важно не перепутать) добавить полный запрет:

User-agent: *
Disallow: /

Дополнительно поставить noindex, nofollow в HTTP-заголовке или в мета-теге, потому что часть роботов игнорирует robots.txt для уже проиндексированных URL. Заодно закрыть поддомен базовой HTTP-авторизацией через .htaccess, чтобы случайный переход по ссылке не показал посторонним незаконченную версию сайта.

Отключить реальную отправку почты. Иначе тестовый заказ на копии магазина отправит настоящее письмо «ваш заказ принят» реальному клиенту из скопированной базы, а форма обратной связи продублирует тестовую заявку в CRM или Telegram-бота владельца. Для WordPress проще всего поставить плагин-заглушку вроде Disable Emails на время тестов, либо прописать фиктивный SMTP, который никуда не доставляет письма.

Перевести платежи в тестовый режим. Если на сайте есть эквайринг или ЮKassa, на копии должны стоять тестовые ключи API, а не боевые. Иначе тестовая оплата на копии спишет реальные деньги с реальной карты того, кто её проводит.

Обезличить или удалить чувствительные данные из скопированной базы. Копия базы заказов и заявок содержит настоящие телефоны, имена и адреса клиентов. Если доступ к копии не ограничен строго тем же кругом людей, что и к боевому сайту, это уже вопрос 152-ФЗ, а не только технического удобства.

Что проверять на копии перед обновлением боевого сайта

Чек-лист, который использую сам перед тем, как переносить обновление с копии на продакшн:

  • сайт открывается на всех типах страниц: главная, карточка товара или услуги, форма, корзина или заявка,
  • визуально ничего не съехало на десктопе и на мобильном экране,
  • тестовая заявка или заказ проходит от начала до конца, включая уведомление (в тестовом режиме),
  • админка открывается, ключевые разделы редактирования работают без ошибок,
  • в консоли браузера нет новых ошибок JavaScript, которых не было до обновления,
  • в error_log сервера нет новых PHP Warning или Fatal Error после обновления,
  • скорость загрузки не просела заметно относительно версии до обновления.

Отдельно стоит сверить это с формальной проверкой после любых правок на сайте, не только после обновлений. Общий подход к тому, как проверять сайт перед тем, как считать задачу закрытой, разобран в статье про приёмочное тестирование после правок. А что конкретно может сломаться при обновлении ядра, плагинов и тем WordPress и как снизить этот риск ещё на этапе планирования, смотрите в статье обновление WordPress без поломок.

Обратный перенос: почему копировать базу обратно опасно

Логичное на первый взгляд действие: проверили обновление на копии, всё работает, теперь просто скопировать копию поверх боевого сайта целиком. Это плохая идея по одной причине: пока шла проверка, на боевом сайте продолжали появляться реальные заказы, заявки, комментарии и правки контента. Если залить копию базы поверх продакшна, все эти данные потеряются.

Правильный порядок обратный: изменения переносятся с копии на продакшн, а не наоборот.

  • Файлы (обновлённое ядро, темы, плагины) копируются с копии на боевой сайт напрямую, файлы не содержат пользовательских данных, конфликта нет.
  • Изменения в базе, если они были (новая структура таблиц, новые опции плагина), переносятся вручную или через миграционный SQL-скрипт, который применяет только структурные изменения, а не подменяет данные целиком.
  • Перед переносом файлов обязательно снимается свежий бэкап боевого сайта. Про то, где и как хранить такие бэкапы правильно, есть отдельная статья про резервные копии WordPress без платных плагинов.
  • После переноса файлов боевой сайт проверяется по тому же чек-листу, что и копия.

Таблица, что переносится в каком направлении, чтобы не запутаться:

ЧтоС копии на продакшнС продакшна на копию
Обновлённые файлы CMS, тем, плагиновда, переносимнет
Структурные изменения в базе (новые таблицы, опции)да, через миграциюнет
Пользовательские данные (заказы, заявки, комментарии)никогдада, регулярно при пересоздании копии
Настройки, специфичные для тестового окруженияникогданет, настраиваются заново

Если обновление меняет структуру данных существенно, например мажорное обновление магазинного плагина, ручной перенос слишком рискован, и в этом случае честнее пересоздать копию заново со свежим дампом продакшна, применить обновление снова, а на боевой сайт накатить то же самое обновление напрямую, уже без переноса из копии.

Когда копия не нужна и хватает бэкапа

Полноценная тестовая копия оправдана не всегда. Для простой визитки без форм, платежей и сложной кастомизации, где обновления сводятся к смене минорных версий пары плагинов, создание отдельного стенда каждый раз избыточно. Разумная альтернатива:

  • снять свежий бэкап файлов и базы непосредственно перед обновлением,
  • обновлять по одному компоненту, а не всё пачкой одним кликом,
  • сразу после каждого шага открывать сайт и проверять главные страницы,
  • если что-то сломалось, откатить именно этот компонент из бэкапа, а не искать проблему вслепую.

Это занимает 10-15 минут внимания вместо часа на разворачивание копии, и для сайта с низким риском (нет платежей, нет сложной интеграции, трафик небольшой) вполне достаточно. Постоянная копия имеет смысл заводить, когда: на сайте есть платежи или сложные интеграции, обновления происходят часто (раз в неделю и чаще), или сайт уже один раз падал после обновления и вы не хотите повторения.

Если хочется настроить процесс обновлений один раз и не думать об этом каждый месяц, я включаю тестовую копию и регламент проверки перед обновлением в абонентское обслуживание, подробности в тарифах. А если сайт уже переезжал или переезжает на новый хостинг и заодно нужно поднять постоянный staging-контур, у меня есть отдельный разбор процесса переноса в статье перенос сайта на новый хостинг. Если ситуация срочная и обновление уже сломало боевой сайт прямо сейчас, пишите через форму на сайте, разбираю такие случаи в приоритете.

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

Зачем нужна тестовая копия сайта

Чтобы проверять обновления и правки до того, как они попадут к посетителям. Проверка на копии занимает 10-15 минут внимания вместо часа паники на боевом сайте.

Как сделать копию

Поднять её на поддомене того же хостинга: скопировать файлы, развернуть базу, поменять адрес сайта. На визитке или сайте услуг это 40-90 минут.

Что обязательно отключить на копии

Индексацию, отправку писем и приём платежей. Забытая почта на копии рассылает клиентам дубли уведомлений, а открытая для роботов копия попадает в поиск и конкурирует с оригиналом.

Можно ли копировать базу обратно

Опасно. За время проверки на боевом сайте появились новые заявки и заказы, и обратный перенос базы их сотрёт. Обратно переносят только файлы и настройки.

Передайте техническую часть в надёжные руки.

Слежу за хостингом, бэкапами и обновлениями. Когда что-то пойдёт не так – звоните мне, не своему программисту, не в спортзал и не маме.

Короткие вопросы по теме

Все вопросы по теме "Поддержка и абонентское обслуживание"

Заявка

Обсудим задачу

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

Куда удобнее ответить?