Представим условный сценарий. В сети WordPress Multisite живёт два десятка сайтов, и один из них, назовём его клиентским, вырос. У него свой трафик, свои пожелания к плагинам, а главное, он хочет собственный сервер, чтобы чужие обновления и чужие всплески нагрузки его не касались. Первая мысль бодрая: найти в wp-content/uploads папку с нужным номером, забрать её, выгрузить контент и дело в шляпе.

Эта мысль живёт ровно до первого открытия перенесённого сайта. Картинки на месте, а ссылки на них ведут на старый адрес. Автор записей из админки куда-то исчез. Настройки темы вернулись к умолчаниям. Форма обратной связи молчит, потому что ключ от капчи выдан на другой домен. Сайт в сети держится не только на своей папке: он опирается на общие таблицы пользователей, на сетевые настройки и на плагины, которые включил не он. Поэтому задача формулируется иначе: что нужно отделить вместе с сайтом, чтобы он заработал самостоятельно и ничего не потерял по дороге.

Опись имущества: что принадлежит сайту, а что сети

Перед любыми командами стоит составить опись. Это занимает час-два, зато потом не придётся гадать, откуда взялась пропавшая настройка. В административной панели сети есть разделение контекстов: Network Admin управляет сайтами, пользователями, темами и плагинами всей сети, и доступ туда есть у Super Admin, а настройки отдельного сайта лежат в другом контексте. Это различие и есть основа описи: всё, что настраивалось в сетевой панели, принадлежит сети, и самостоятельный экземпляр должен получить свою копию этого решения.

Удобно разложить всё по трём корзинам.

  • Своё. Записи, страницы, комментарии, меню, виджеты, настройки темы и плагинов, загруженные файлы. Всё это переезжает вместе с сайтом.
  • Общее, но нужное сайту. Учётные записи пользователей и их роли именно на этом сайте, темы и плагины, которыми он пользуется, сетевые настройки, влияющие на поведение, например разрешённые типы файлов или лимиты загрузки.
  • Чужое. Другие сайты сети, список сайтов, регистрация новых сайтов, сетевые лицензии и всё, что относится к управлению соседями. С собой это брать не нужно, и хорошо, если этого нет в новом экземпляре.

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

Пример описи для условного клиентского сайта
ЧтоГде обычно живётЧто делать при отделении
Записи, страницы, комментарии, настройки сайтаСобственные таблицы сайта с его префиксомПеренести и переименовать под префикс нового экземпляра
Пользователи сайтаОбщая таблица пользователей сети и метаданные с ролями для этого сайтаВыбрать нужных, перенести вместе с ролями, сопоставить идентификаторы авторов
Файлы медиатекиОтдельный каталог загрузок сайта внутри общих загрузок сетиСкопировать, поправить пути и адреса в контенте
Плагины и темыОбщие каталоги, включение либо на сайте, либо на всю сетьВыяснить, как включён каждый, поставить нужные версии заново
Настройки, заданные в сетевой панелиСетевые опции, не принадлежащие сайтуПрочитать, решить, что воспроизвести вручную

Номер блога и префикс таблиц: проверять, а не вспоминать

Самая соблазнительная ловушка — считать, что вы знаете, как называются таблицы. В типичной сети у каждого сайта есть числовой идентификатор, а его таблицы получают префикс с этим числом, примерно как wp_7_posts. Но «типично» не значит «у вас так же». Префикс базового сайта задаётся в конфигурации и может быть любым. Номер нужного сайта не обязан совпадать с тем, что вы запомнили, особенно если сайты создавались и удалялись. Старые сети иногда перенесены с других схем, и в базе можно найти таблицы удалённых сайтов, которые никто не вычистил.

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

SHOW TABLES LIKE 'ВАШ_ПРЕФИКС_НОМЕР\_%';

Сравните результат с ожиданиями. Обычно в наборе будут записи, метаданные записей, комментарии, термины и связи с ними, ссылки и опции. Но плагины добавляют свои таблицы, и часть из них может быть привязана к сайту с тем же префиксом, а часть создана без номера и общая для всей сети. Универсального списка здесь не существует, каждая установка обрастает своим. Если у вас стоит магазин, система бронирования, SEO-плагин с журналом редиректов или плагин форм, ищите их таблицы отдельно: и среди пронумерованных, и среди тех, что просто начинаются с базового префикса.

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

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

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

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

Загрузки: файлы, пути и память плагинов

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

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

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

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

Пользователи: кто из сети переезжает

В сети пользователь существует один раз и может быть участником многих сайтов с разными ролями. Для самостоятельного экземпляра это означает, что учётные записи придётся вырезать из общей таблицы. Первый шаг: составить список тех, кто действительно имеет отношение к сайту. Для этого годятся метаданные пользователей: там записаны роли на каждом сайте сети. Кто не имеет роли на нашем сайте, переезжать не должен. Заодно вы не отдадите чужие адреса почты и хэши паролей другому владельцу сервера, а для клиента, который уезжает под собственную ответственность, это не мелочь.

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

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

Четвёртое: пароли. Хэши паролей лежат в таблице пользователей и переезжают вместе с записями, так что входить можно с прежними паролями. Но сессии и токены входа, соли и ключи безопасности из конфигурации у нового экземпляра свои, и это нормально: все текущие сессии завершатся, пользователи просто войдут заново. Предупредите их, чтобы вход после переключения не показался взломом.

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

Плагины и темы глазами автономного экземпляра

В сети плагин можно включить двумя способами: для всей сети или только для одного сайта. Ту же сеть можно закрыть для включения плагинов обычными администраторами, и тогда пользователь сайта видит лишь то, что разрешил Super Admin. Поэтому на вопрос «какие плагины нужны сайту» ответ состоит из двух списков: активированные на сайте и активированные сетью. Второй список легко упустить, ведь в панели сайта такие плагины выглядят как обязательные и их нельзя отключить. Вы можете годами не замечать, что функция безопасности, кэширования или форм была включена не клиентом, а сетью.

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

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

Отдельная история с лицензиями. Платные плагины и темы часто привязаны к домену или к количеству сайтов. Если лицензию оформляло агентство на сеть, у клиента её нет, и ему придётся приобрести свою или договориться о передаче. Уточните это до переключения, а не после, когда плагин потребует ключ и заблокирует обновления.

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

Темы подчиняются тому же правилу. Если клиент пользуется дочерней темой, переносите и её, и родителя. Если тема включена на уровне сети и сайт получает её обновления вместе со всеми, то на новом сервере вам придётся самому решить, какую версию ставить: ту же, что работала на сайте, или более новую. Для первой версии на новом месте разумно взять ту же, которая работала раньше, чтобы переезд не смешивался с обновлением и любую разницу можно было отнести к самому переезду.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Замена адресов и сериализованные данные

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

Для этого есть проверенный инструмент: команда search-replace из WP-CLI. По документации, она учитывает сериализованные данные PHP и не меняет первичные ключи. Это снимает главный страх: идентификаторы записей и пользователей останутся прежними, а длины внутри сериализованных значений будут пересчитаны.

Область действия тоже важна. В документации указано: в multisite по умолчанию команда работает с таблицами текущего сайта, а флаг --network расширяет область на всю сеть. На исходной сети лишний --network стал бы заменой адресов во всех соседних сайтах, чего вы не хотите ни при каких обстоятельствах. На новом самостоятельном экземпляре в нём просто нет смысла. Лучше выполнять замену там, где ей ничто не угрожает: на копии, развёрнутой на новом сервере, и не трогать оригинал.

Перед реальной заменой запустите пробный проход. В команде предусмотрен dry run, и он показывает, в каких таблицах и сколько замен произойдёт, ничего не записывая:

wp search-replace 'https://network.example/client' 'https://client.example' --dry-run

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

Обычно замен нужно несколько, и их порядок значим.

  1. Сначала полный адрес с протоколом и путём сайта.
  2. Потом вариант без протокола, если он встречается в контенте. Делайте его только после первого шага, иначе новый адрес окажется смешан с частями старого.
  3. Затем путь к загрузкам: сегмент с номером сайта в нём должен уйти, а структура остаться.

После каждого шага полезно вновь выполнить пробный проход с тем же шаблоном: он должен показать ноль замен. Если нет, что-то ещё осталось, и можно разобраться, что именно. Затем остаётся самая простая, но упрямо полезная проверка: поискать в базе остатки старого домена обычным поиском по тексту и посмотреть на результаты. Часть находок будет законной, например внешние ссылки на старый сайт в старых публикациях, и решить, что с ними делать, должен редактор, а не скрипт.

Репетиция до смены домена

Перенос лучше репетировать на временном адресе: собрать новый экземпляр на VPS, залить данные, провести замену адресов уже под рабочий домен и проверить сайт, не меняя DNS. Для проверки можно открывать сайт через локальный файл имён на своём компьютере, чтобы домен вёл на новый сервер только у вас. Обычный посетитель всё это время продолжает ходить на старое место. Именно так у вас появляется возможность ошибаться без последствий.

Критерии проверки лучше записать заранее, чтобы не решать «вроде работает» на глаз.

Что проверить на репетиции и по какому признаку считать проверку пройденной
ЗонаЧто делаемПризнак готовности
ВходВходим под ролями администратора, редактора и обычного пользователяПароли подходят, роли дают ожидаемые права, авторы записей на месте
МедиаОткрываем разные записи с картинками разных лет, смотрим миниатюры, загружаем новый файлНет битых картинок, новый файл попадает в ожидаемый каталог
ФормыОтправляем тестовые обращения через каждую формуПисьмо дошло, запись сохранена, капча принимает домен
Старые ссылкиБерём список самых посещаемых адресов и проходим по немуКаждый адрес открывается либо ведёт редиректом на нужное место
Плановые задачиПроверяем отложенные публикации и задания плагиновЗадания выполняются по расписанию
Поиск и карта сайтаИщем по сайту, открываем карту сайтаАдреса в них уже новые

Вход

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

Медиа

Выберите записи из разных периодов жизни сайта, а не только свежие. Самые старые публикации чаще всего хранят адреса в нестандартных формах. Загрузите новый файл и убедитесь, что он лёг не в старую структуру с номером сайта. Если лёг, значит, в настройках осталась привязка к прежнему каталогу.

Формы и всё, что говорит с внешним миром

Формы любят домены. Ключи капчи, подтверждённый адрес отправителя почты, адреса обратных вызовов платёжных систем, вебхуки, интеграции с рассылками и CRM: у каждого из этих элементов может быть список разрешённых адресов, и новый домен или новый IP-адрес туда не входит. Найти их проще всего пройдя по тестовым действиям: отправить форму, оформить тестовый заказ, подписаться на рассылку. Внешние сервисы нередко отвечают не сразу, поэтому оставьте на проверку достаточно времени.

Старые ссылки

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

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

У самостоятельного экземпляра тот же набор нагрузок, что и у любого одиночного WordPress: PHP-процессы, база данных, кэш и место под загрузки. Но теперь они принадлежат одному сайту, а не делятся между двадцатью. Это удобно: нагрузка видна целиком, и её проще связать с причиной. Прикиньте, сколько занимают таблицы вашего сайта и каталог его загрузок, прибавьте запас на рост и на копию во время переезда. Именно по этим цифрам, а не по общей величине сети, стоит выбирать объём диска.

На VPS MAATRIX доступны NVMe-диски, процессоры AMD EPYC и root-доступ, а в публичном предложении перечислены локации UK, US, RU и FR. Тарифная линейка начинается с Ba (1 vCPU, 2 ГБ RAM, 40 ГБ NVMe) и продолжается через Uab (2 vCPU, 4 ГБ, 80 ГБ), Heka (4 vCPU, 8 ГБ, 160 ГБ) и Maat (8 vCPU, 16 ГБ, 240 ГБ) до Djed (16 vCPU, 32 ГБ, 320 ГБ). Эти ресурсы описывают конфигурацию, а не обещают, сколько посетителей выдержит конкретный сайт: это определяется замерами на самом сайте. Root-доступ нужен для практических вещей: поставить нужную версию PHP, настроить веб-сервер и базу под сайт, задать собственное расписание заданий и держать на сервере только то, что принадлежит клиенту. Подробнее о том, как устроена сама сеть и чем она хороша, пока отдельные сайты ею довольны, рассказано в материале про WordPress Multisite на VPS. Заказать сервер можно на странице аренды VPS: оплата возможна картой РФ или через СБП, а сервер создаётся автоматически через пару минут после оплаты. Точное наличие образов и операционных систем в нужной локации уточняйте в форме заказа.

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

Исходный сайт: не торопиться с удалением

Самое опасное в такой задаче не перенос, а уборка. Пока новый экземпляр не принят и домен не переключён, исходный сайт остаётся единственным рабочим, и трогать его нельзя. Это и есть страховка: если на новом месте обнаружится проблема, возврат состоит в том, что DNS продолжает смотреть на старое место.

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

  1. Окно заморозки. Заранее согласуйте с владельцем время, когда на старом сайте не публикуют и не принимают заказы.
  2. Финальная выгрузка. В это окно заново снимите таблицы и загрузки и повторите на новом сервере всё, что отрепетировано, включая замену адресов.
  3. Короткая сверка. Пройдите по тому же списку проверок, но быстро: вход, медиа, форма, несколько старых адресов.
  4. Переключение домена. Только после согласования. Уменьшите время жизни записей DNS заранее, чтобы переключение и возможный возврат не растягивались на сутки.

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

После успешного переключения старый сайт в сети остаётся ещё на какое-то время, потому что вам может потребоваться что-то сверить, а посетители с кэшем адресов продолжат приходить к нему. Решение о его судьбе принимается в контексте сети, то есть в Network Admin, и принимает его владелец сети. Здесь есть несколько вариантов.

  • Оставить закрытым. Сайт недоступен посетителям, данные хранятся. Это самый осторожный вариант на период наблюдения.
  • Заменить заглушкой с редиректом. Если домен или адрес сайта в сети остался прежним, посетителей нужно вести на новое место, а не показывать им ошибку.
  • Удалить. Только после согласованного срока, подтверждённой копии и уверенности, что на новом месте всё работает. Вместе с сайтом исчезнут его таблицы и, возможно, файлы, поэтому перед удалением снимите полную копию и положите её туда, где она переживёт сеть.

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

Первое обновление после разъезда

Проверка самостоятельности выглядит приземлённо. Через некоторое время после переезда в перенесённом сайте выходит обновление плагина. В сети такое обновление касалось бы всех: плагин лежит в общем каталоге, и, обновив его, вы обновляете его для каждого соседа, нравится ему это или нет. Теперь у сайта свой каталог плагинов, своя база и своя версия PHP. Вы можете сначала проверить обновление на копии, затем накатить его и убедиться, что формы и вход работают. Если что-то пошло не так, откатываете только этот сайт. Соседи в сети этого не заметят, потому что в их каталогах, таблицах и настройках ничего не изменилось.

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