Разделение общего сервера на клиентские: план работ
Студия или фрилансер почти всегда начинают одинаково: один VPS, на нём три-пять клиентских сайтов, общий nginx, общий MySQL, общий набор cron-задач. Это нормально, пока проектов немного и деньги считанные. Но в какой-то момент один клиент требует изоляцию для аудита безопасности, другой хочет забрать свой проект себе, а третий подкладывает такую нагрузку, что падают все соседи разом — и общий сервер из экономии превращается в риск. Разнести всё по отдельным серверам несложно технически, но легко наделать ошибок в координации: ниже — план, который учитывает именно эту часть, а не только команды rsync и mysqldump.
Содержание
Когда общий сервер становится проблемой
Разделение обычно назревает по одной из трёх причин, и от причины зависит, насколько срочно и как аккуратно надо действовать.
Требование клиента к изоляции. Клиент из финансового сектора, медицины или госсектора на аудите узнаёт, что его база данных крутится на одной машине с чужими проектами, и требует separate hosting как условие продолжения контракта. Здесь обычно есть жёсткий дедлайн и явно сформулированное требование — это самый простой случай, потому что переговоры уже состоялись.
Продажа отдельного проекта. Один из клиентских сайтов продаётся вместе с бизнесом, и новый владелец хочет получить инфраструктуру отдельно, со своим биллингом и доступом, без общих корней со студией. Здесь важно не только перенести сервисы, но и полностью вычистить общие учётные записи, ключи и cron-задачи, которые могли быть привязаны к инфраструктуре студии.
Рост нагрузки и рисков. Явного триггера нет, просто один проект начинает есть 80% CPU общего сервера, и остальные клиенты страдают без причины, о которой они даже не знают. Это самый коварный случай: дедлайна нет, поэтому разделение откладывается до первого серьёзного инцидента — падения при пиковой нагрузке одного из соседей.
Во всех трёх случаях итоговый план одинаков: инвентаризация, подготовка новых серверов, перенос по одному, координация по датам, переключение DNS, безопасное отключение старого сервера. Разница только в сроках и в том, кто торопит.
Инвентаризация: находим настоящие границы между проектами
Это самый недооценённый этап. Когда проекты жили на одном сервере месяцами или годами, границы между ними размываются — и именно здесь чаще всего случаются сюрпризы уже после того, как «всё вроде перенесли».
Пройдитесь по каждому клиенту и honestно зафиксируйте:
- Файлы приложения. Не только
/var/www/client-a/, но и то, что лежит вне очевидной директории — загруженные пользователями файлы в/mnt/uploads/, кэш в/var/cache/nginx/, симлинки на общие ресурсы. - База(ы) данных. Проверьте не только явные базы вида
client_a_prod, но и таблицы с префиксами внутри общей базы — такое бывает, если исторически экономили на количестве баз MySQL. - Cron-задачи.
crontab -l -u www-dataи содержимое/etc/cron.d/— здесь часто прячутся задачи бэкапа, рассылок или синхронизации, которые никто не документировал. - Системные конфиги, специфичные для проекта. Отдельный виртуальный хост nginx — это очевидно, а вот кастомные PHP-настройки в
/etc/php/8.3/fpm/pool.d/client-a.conf, отдельный systemd-сервис для очереди задач, специфичныйufw-правило под IP клиента — уже не всегда. - Внешние интеграции. Вебхуки платёжных систем, API-ключи, DNS-записи для верификации почты (SPF/DKIM), у которых значение привязано к IP именно этого сервера.
Отдельно проверьте общие ресурсы, на которые незаметно стали полагаться несколько проектов: одна установленная версия ImageMagick или LibreOffice, которую использует конвертер документов сразу двух клиентов; общий Redis на порту 6379 без паролей, где базы 0 и 1 разделены «по договорённости»; общий SMTP-relay через Postfix, настроенный один раз для всех. При переезде первого же клиента вы либо тащите этот общий кусок с собой (и он должен быть учтён как отдельная зависимость), либо ставите его копию на новый сервер — но тогда нужно понять, что случится с оставшимися клиентами на старом сервере, если вы что-то в общей конфигурации измените.
Практический инструмент инвентаризации — таблица на каждого клиента:
| Клиент | Домен(ы) | Директория | БД | Cron | Системные зависимости | Внешние интеграции |
|---|---|---|---|---|---|---|
| client-a | client-a.ru | /var/www/client-a | client_a_prod | 2 задачи (бэкап, рассылка) | php-fpm pool, ImageMagick | Stripe webhook, SPF |
| client-b | client-b.com, shop.client-b.com | /var/www/client-b | shared_db (префикс cb_) | 1 задача | Redis db1, общий Postfix | YooKassa webhook |
Пока эта таблица не заполнена по всем клиентам, план дальнейших действий строить рано — именно на этом этапе всплывают самые дорогие сюрпризы.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSГотовим отдельный сервер под каждого клиента
Когда границы понятны, для каждого клиента поднимаете отдельный сервер под его стек — не копию общего сервера «на всякий случай», а осознанно подобранную конфигурацию.
Порядок действий на новом сервере, до переноса данных:
- Базовая настройка ОС и безопасность — SSH-ключи вместо пароля, fail2ban, файрвол с закрытыми портами кроме нужных.
- Установка именно того стека, который использует конкретный проект (не всё подряд «на будущее» — лишние сервисы это лишняя поверхность атаки и лишние апдейты).
- Создание пользователя и структуры директорий, максимально похожей на старую — это упростит перенос конфигов и уменьшит число мест, где придётся что-то менять руками.
- Настройка резервного копирования сразу, до переноса продакшн-данных — чтобы первый же бэкап нового сервера был не «после инцидента», а рутинный.
Для веб-студий и агентств, где такие серверы приходится поднимать регулярно под нового клиента или под очередной вынос из общего пула, разумно сразу закладывать шаблон — конфиг nginx, systemd-юниты, скрипт бэкапа — который переиспользуете от клиента к клиенту, а не пишете заново. Подробный разбор, какой стек и конфигурацию обычно берут под такие задачи, разобран в статье про подбор и настройку VPS под веб-студию и агентство — пригодится как чек-лист именно для этого шага.
Sizing нового сервера — отдельный вопрос. Если на общем сервере вы никогда не измеряли, сколько именно ресурсов реально ест конкретный проект (а не сколько ему было выделено «на бумаге»), самое время это сделать: htop под нагрузкой, размер базы через du -sh /var/lib/mysql/client_a_prod, средний RPS по логам nginx за неделю. Ориентируйтесь не на пиковые цифры общего сервера (они смазаны соседями), а на реальное потребление именно этого клиента плюс запас 30-50% на рост.
Перенос: серия миграций, а не одно событие
Важно сразу принять честную рамку: это не «миграция сервера» в единственном числе, а N независимых миграций — по одной на каждого клиента, каждая со своим окном простоя, своим списком проверок и своим риском. Смешивать их в одном плане — источник ошибок: то, что удобно для клиента A, может быть неприемлемо для клиента B.
Для одного клиента типовая последовательность:
# 1. Синхронизация файлов заранее, без простоя (можно за дни до переноса)
rsync -avz --progress /var/www/client-a/ user@new-server:/var/www/client-a/
# 2. В момент окна простоя — снимок базы
mysqldump -u root -p --single-transaction client_a_prod > client_a_prod.sql
# 3. Финальная синхронизация файлов (дельта, которая накопилась)
rsync -avz --delete /var/www/client-a/ user@new-server:/var/www/client-a/
# 4. Перенос дампа и восстановление на новом сервере
scp client_a_prod.sql user@new-server:/tmp/
mysql -u root -p client_a_prod < /tmp/client_a_prod.sql
# 5. Перенос cron-задач
crontab -l -u www-data > client_a_crontab.txt
scp client_a_crontab.txt user@new-server:/tmp/
# на новом сервере: crontab -u www-data /tmp/client_a_crontab.txt
Дальше — smoke-test: открыть сайт по IP нового сервера (через /etc/hosts на своей машине или заголовок Host в curl), проверить логин, оформление тестового заказа, отправку письма, работу вебхуков в тестовом режиме. Только после этого — переключение DNS (следующий раздел).
Порядок переноса клиентов имеет значение. Начните с наименее критичного проекта — не с самого крупного и не с того, где самый строгий SLA. Первая миграция почти всегда вскрывает нюансы (забытая cron-задача, не тот часовой пояс на новом сервере, отсутствующее системное расширение PHP), и лучше набить эти шишки на менее рискованном клиенте. Про технику самого переноса конкретного сайта — включая нюансы с TTL и минимизацией простоя — подробно в статье про перенос сайта на новый VPS без простоя, а если у клиента большая база и даунтайм должен быть минимальным — в статье про перенос большой базы данных с минимальным простоем.
Координация с клиентом и переключение DNS
Здесь — основная разница между разделением общего сервера и обычной миграцией «сервер А → сервер Б». У вас не один клиент, а несколько, и у каждого:
- своё допустимое окно простоя (интернет-магазин не может лечь в рабочий день, у корпоративного сайта окно шире);
- своё удобное время (часовой пояс клиента, его собственные пиковые часы, дни, когда у него запущена рекламная кампания и трогать ничего нельзя);
- своя степень вовлечённости — кто-то просит просто уведомить, кто-то хочет присутствовать на созвоне во время переноса и лично протестировать результат.
Практика, которая экономит нервы: заранее, до начала переноса всех проектов, отправить каждому клиенту короткое письмо с двумя вопросами — «есть ли у вас период, когда сайт точно нельзя трогать» и «предпочитаете уведомление постфактум или присутствие во время переноса». Ответы фиксируются в той же таблице, что и инвентаризация, отдельной колонкой.
Переключение DNS делается индивидуально по каждому домену, по готовности именно его нового сервера — не одним махом для всех клиентов сразу:
- За 24-48 часов до переноса снизьте TTL A-записи домена клиента до 300 секунд (если он был выше) — это позволит переключению распространиться быстро.
- После успешного smoke-теста на новом сервере (см. предыдущий раздел) — меняете A-запись на IP нового сервера.
- Держите старый сервер работающим (тот же виртуальный хост, та же база) минимум сутки-двое после переключения — резолверы с устаревшим TTL могут ещё стучаться на старый IP.
- Через несколько дней после переключения верните TTL к обычному значению (3600 и выше) на новом сервере.
Если у клиента несколько поддоменов (API, админка, статика на CDN) — DNS-записи для каждого поддомена нужно свести в тот же реестр на этапе инвентаризации, иначе легко забыть переключить api.client-a.ru, пока основной домен уже переехал.
Трекинг статуса и безопасное отключение старого сервера
При одном клиенте держать статус переноса в голове несложно. При пяти-десяти независимых клиентских миграциях, растянутых на недели, память подводит почти гарантированно — кто-то один «висит» в состоянии «данные перенесены, DNS ещё нет» неделями, потому что на него банально забыли вернуться.
Ведите явную таблицу статусов — отдельным листом рядом с таблицей инвентаризации, обновляемую по факту, а не «в уме»:
| Клиент | Инвентаризация | Новый сервер готов | Данные перенесены | Согласовано окно с клиентом | DNS переключён | Старый сервер можно чистить |
|---|---|---|---|---|---|---|
| client-a | done | done | done | done | done | нет — ждём 48ч после DNS |
| client-b | done | done | в процессе | согласовано на сб 22:00 | нет | нет |
| client-c | done | нет | нет | нет | нет | нет |
Такая таблица решает две задачи: вы в любой момент точно знаете, кто на какой стадии, и что клиент не забыт; а перед отключением старого сервера у вас есть чёткий критерий — «все строки в последней колонке = да» — вместо расплывчатого «вроде все переехали».
Отключение старого общего сервера — необратимый шаг, и торопиться с ним не стоит, даже когда кажется, что все клиенты давно на новых серверах. Перед тем, как гасить старый сервер:
- Проверьте логи доступа nginx/apache за последние 2-4 недели на предмет реальных запросов, а не только конфигурацию виртуальных хостов:
awk '{print $1, $7}' /var/log/nginx/access.log* | sort | uniq -c | sort -rn | head -50
grep -h "Host:" /var/log/nginx/access.log* 2>/dev/null | sort | uniq -c
- Отдельно посмотрите на запросы, которые НЕ попадают ни в один известный виртуальный хост (
default_serverв nginx, который логирует «промахи») — это частый способ обнаружить забытый поддомен или интеграцию, всё ещё смотрящую на старый IP. - Проверьте почтовые очереди (
mailqилиpostqueue -p) — если через старый сервер до сих пор идёт исходящая почта одного из клиентов (забытый SMTP-relay в конфиге стороннего сервиса), отключение сломает уведомления, о которых никто не вспомнит до жалобы пользователя. - Сверьтесь с таблицей внешних интеграций из этапа инвентаризации — платёжные вебхуки, API сторонних сервисов, куда был прописан старый IP или домен, указывающий на старый сервер.
- Только после этого — снимите финальный полный бэкап старого сервера целиком (диск целиком или архив всех директорий и дампов баз) и держите его отдельно минимум 30 дней, прежде чем реально освобождать сервер.
Если для кого-то из клиентов доступ к продакшену на новом сервере получают несколько человек команды — стоит сразу настроить это правильно, без раздачи root всем подряд; порядок разобран в статье про то, как раздать доступ команде без выдачи root.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать VPSНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько времени закладывать на разделение общего сервера с 5-6 клиентами?
Ориентировочно — от 3 до 6 недель, если делать аккуратно: инвентаризация одна на всех (несколько дней), затем перенос клиентов по одному с окнами по договорённости, плюс минимум неделя-две наблюдения после каждого переключения DNS перед тем, как браться за следующего клиента. Цифра ориентировочная и сильно зависит от отзывчивости клиентов в согласовании окон.
Можно ли перенести всех клиентов в одно окно простоя, чтобы не растягивать процесс?
Технически можно, но это резко повышает риск: если что-то пойдёт не так у одного клиента, вы одновременно разбираетесь с несколькими живыми инцидентами, и откат для всех сразу физически сложнее, чем для одного. Поочерёдный перенос даёт возможность учиться на первых миграциях и держать риск локализованным.
Что делать, если два клиента используют одну и ту же лицензию стороннего ПО (например, платный плагин CMS), купленную на старом сервере?
Это ровно тот случай размытых границ из этапа инвентаризации — нужно заранее выяснить условия лицензии (привязка к домену или к серверу) и либо купить вторую лицензию, либо перенести привязку на новый домен/сервер до отключения старого.
Нужно ли уведомлять клиента, если перенос прошёл гладко и простоя фактически не было?
Да, короткое уведомление постфактум — хорошая практика даже при нулевом простое: клиент видит, что изменение произошло контролируемо, и знает, к кому обращаться, если в ближайшие дни всплывёт что-то нетипичное на новом сервере.
Как быть с общим SSL-сертификатом (wildcard) на несколько клиентских поддоменов старого сервера?
На новых отдельных серверах разумнее выпустить отдельные сертификаты Let's Encrypt на домен каждого клиента — это устраняет зависимость от общего wildcard-сертификата и упрощает будущую ротацию, если один из клиентов снова сменит инфраструктуру.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →