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

Поэтому выбирать способ размещения «по удобству» — значит начинать с середины. Сначала нужно понять, где проходят границы, а потом уже решать, чем их обеспечить: Linux-пользователями, контейнерами или отдельными серверами. Разберём это по порядку.

Что на самом деле принадлежит клиенту

Слово «сайт» обманчиво. Когда студия говорит «у нас три сайта на одном VPS», в реальности на сервере лежат совсем разные вещи, и у каждой свой владелец и своя цена утечки. Полезно один раз выписать для каждого заказчика всё, что относится к нему:

  • Файлы проекта: код, темы, плагины, загруженные пользователями файлы. Загрузки часто ценнее кода — в них могут лежать сканы, счета, переписка.
  • Базы данных: отдельная база и отдельный пользователь БД или одна общая СУБД с общей учётной записью. Вторая схема встречается чаще, чем хотелось бы, и ломает любое разделение выше по стеку.
  • Секреты: файлы конфигурации с паролями БД, ключи платёжных систем, токены почтовых сервисов, соли и ключи приложения. Они лежат рядом с кодом, а значит, доступны всем, кто читает код.
  • Резервные копии: куда они пишутся, кто их читает и лежат ли копии нескольких клиентов в одном каталоге под одним ключом. Копия клиента А, доступная из-под учётной записи клиента Б, — это та же утечка, только отложенная.
  • Доступы: SFTP, SSH, панель администрирования приложения, доступ к репозиторию, учётные записи подрядчиков клиента.
  • Логи: в них встречаются адреса, идентификаторы, иногда токены в параметрах запросов.

Теперь для каждой строки задайте два вопроса. Первый: кто сегодня может это прочитать? Второй: кто может это изменить? Ответ «веб-сервер и всё, что запускается от его имени» — типичная находка. Если PHP-процессы всех сайтов работают под одним системным пользователем, то компрометация любого из них даёт чтение каталогов остальных: для системы это один и тот же субъект. Именно с этой точки стоит начинать сравнение вариантов, потому что каждый из них по-разному смещает границу.

Три границы и одна и та же ошибка

Возьмём конкретное происшествие и прогоним его через три схемы. Условие: в плагине магазина (сайт Б) нашлась уязвимость, и злоумышленник получил возможность выполнять код с правами процесса, обслуживающего этот сайт. Это не экзотика, а самый обычный сценарий для CMS с набором сторонних расширений.

Отдельные пользователи на общем сервере

Каждый сайт получает своего системного пользователя, свой пул процессов приложения, свой каталог с правами, закрытыми для других, и свою учётную запись в базе данных. Ядро, файловая система, сетевой стек и набор системных пакетов общие. Граница здесь — права доступа Linux.

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

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

Контейнеры на общем сервере

Контейнер добавляет слой: у каждого сайта своё окружение, своя файловая система образа, свой набор зависимостей, ограничения по ресурсам. По документации Docker, в изоляции контейнеров участвуют пространства имён (namespaces) и контрольные группы (cgroups) — Docker Engine security. Пространства имён ограничивают то, что процесс «видит», cgroups — сколько ресурсов он может потребить.

Но ядро по-прежнему одно на всех. Контейнер — это не маленький сервер, а процессы обычной хостовой системы, обёрнутые в ограничения. Из этого следует важная вещь: надёжность границы зависит от конфигурации. Та же документация указывает, что настройки контейнера и дополнительные возможности процесса влияют на степень изоляции. Контейнер, запущенный с расширенными привилегиями или с примонтированными каталогами хоста, изолирован заметно слабее, чем контейнер с настройками по умолчанию. А значит, фраза «у нас всё в Docker» сама по себе ничего не говорит о защите клиентов.

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

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

Отдельные VPS для каждого клиента

Здесь у каждого заказчика свой виртуальный сервер со своим ядром, своими пользователями, своей файловой системой и своими сетевыми настройками. Взлом сайта Б означает, что злоумышленник внутри VPS магазина. Чтобы добраться до А и В, ему нужно уже не повышать права, а преодолевать границу между серверами: найти сетевой путь, украденные ключи или общий управляющий доступ. По умолчанию такого пути нет.

Важная оговорка: граница между виртуальными машинами — это другая граница, чем граница между контейнерами, и эквивалентной изоляцией их называть нельзя. Контейнеры делят одно ядро, виртуальные серверы — нет. Но и «разные VPS» не означают «разное оборудование». Размещение экземпляров на разных физических узлах — отдельное свойство инфраструктуры, а не побочный эффект того, что серверов несколько. Для сравнения: в Amazon EC2 для этого существует отдельная необязательная настройка — группы размещения, где режим spread располагает небольшой набор экземпляров на разном оборудовании, а partition разделяет группы на непересекающееся оборудование (Amazon EC2: Placement groups). Мысль отсюда простая: независимость от общего оборудования — это то, о чём нужно договариваться и что нужно уточнять, а не предполагать. Если вам важна независимость по физическому узлу, спросите об этом у провайдера отдельно и не закладывайте в договор с клиентом обещание, которого вы не проверяли.

И ещё одно прямое следствие: отдельный VPS не является резервной копией. Если сайт клиента удалён, повреждён вирусом-шифровальщиком или испорчен неудачным обновлением, то отдельный сервер вам не поможет — он просто так же пострадает целиком. Копии, хранящиеся вне этого сервера, — отдельная задача.

Сводка по сценарию взлома одного сайта

Что доступно после компрометации одного сайта (при корректной настройке)
СхемаЧто останавливает движение к соседямЧто остаётся общимТипичная слабость
Пользователи LinuxПрава на каталоги, отдельные учётные записи БДЯдро, ФС, системные пакеты, сетьОдна ошибка в правах или уязвимость ядра
КонтейнерыПространства имён, ограничения ресурсов, отдельная ФС образаЯдро и хост, демон контейнеровЛишние привилегии, примонтированные каталоги хоста, доступ к демону
Отдельные VPSОтдельное ядро и отдельная системаТолько то, что вы связали сами: ключи, сеть, панелиОбщие управляющие доступы студии

Заметьте, что в последней колонке во всех трёх строках есть то, что вы можете сделать неправильно сами. Это подводит к самому неприятному месту всей темы.

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

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

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

Ключ от всех дверей лежит у студии

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

Возьмём наш сценарий: сайт Б взломан. Если на его сервере лежит ключ развёртывания, который подходит и к серверам А и В, злоумышленник получает не уязвимость, а готовый пропуск. Внешняя изоляция сохранилась, но внутри неё лежит универсальный ключ. То же верно и для контейнеров: Docker-документация называет доступ к демону Docker с правами root существенной границей доверия, потому что управление демоном может позволить смонтировать файловую систему хоста (Docker Engine security). Практический вывод: если в контейнер сайта проброшен сокет демона (так делают для удобства автоматизации) или если пользователь, управляющий контейнерами, фактически равен администратору хоста, то контейнерная изоляция между клиентами не работает как граница.

Что с этим делать, не превращая дело в бюрократию:

  • Разные ключи на разные серверы. Ключ, по которому можно зайти на сервер клиента Б, не должен открывать сервер клиента А. Это неудобно ровно настолько, насколько полезно.
  • Не оставлять управляющие ключи на клиентских серверах. Развёртывание «снаружи внутрь»: система, расположенная отдельно, заходит на сервер, а не сервер хранит доступ к соседям.
  • Минимальные права для автоматизации. Учётная запись развёртывания должна уметь обновить код одного сайта, а не быть администратором хоста.
  • Не пробрасывать управление контейнерами внутрь контейнеров приложений. Если какой-то служебный контейнер действительно нужен с таким доступом, считайте его частью доверенной зоны и не размещайте рядом с клиентскими приложениями.
  • Раздельные секреты и копии. Резервные копии разных клиентов шифруются разными ключами или пишутся в разные хранилища с разными учётными данными.
  • Отдельные доступы подрядчиков. Фрилансер, который правит вёрстку для клиента А, должен видеть только клиента А.

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

Шумный сосед и независимый график обновлений

Безопасность — не единственная причина проводить границы. Есть две будничные причины, которые студия почувствует раньше, чем настоящий инцидент.

Когда один сайт мешает остальным

Магазин запустил рассылку и акцию: нагрузка выросла, процессы приложения заняли процессор, база данных забирает память. Остальные сайты на том же сервере замедляются или начинают отвечать ошибками, хотя их никто не трогал. При схеме с пользователями на общем сервере ограничить такого соседа сложнее: ресурсы делятся по умолчанию «как получится». Контейнеры дают инструменты: по документации Docker, контрольные группы участвуют в изоляции и позволяют ограничивать потребление, так что можно задать потолок памяти и процессорного времени для каждого сайта. Это не отменяет общего физического предела сервера, но превращает неконтролируемую «борьбу за ресурсы» в заданный заранее лимит.

Отдельные VPS решают вопрос радикальнее: у каждого клиента свой набор vCPU, памяти и диска. Всплеск нагрузки магазина съедает его собственный ресурс, а не чужой. Но тут надо быть честным по отношению к цифрам. В тарифной линейке MAATRIX есть, например, 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 ГБ). Эти параметры описывают конфигурацию, а не обещание ёмкости: сколько посетителей выдержит конкретный магазин на конкретном тарифе, покажет только замер на его реальной нагрузке. Поэтому подбирайте размер отдельно для каждого клиента, а не по принципу «все на самый маленький».

Независимость обновлений

Здесь изоляция работает как организационный инструмент. Сайт-визитка клиники стоит на старой версии PHP, потому что устаревшая тема сломается на новой. Магазин, наоборот, должен обновляться регулярно, иначе скоро появятся уязвимости в плагинах. Если они на одном сервере с общим набором системных пакетов, студия начинает торговаться сама с собой: обновить версию языка ради магазина или оставить старую ради визитки. Контейнеры решают эту проблему очень хорошо: у каждого сайта своя версия среды выполнения, а обновление одного не затрагивает остальных. Отдельные VPS дают то же самое на уровне всей системы, плюс возможность перезагрузить сервер ядра для одного клиента, не предупреждая остальных.

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

Как связать выбор с ценностью данных и условиями клиента

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

  1. Что случится при утечке данных клиента? Для визитки с публичным текстом — почти ничего. Для личного кабинета с договорами, персональными данными и платёжными событиями — юридические и репутационные последствия.
  2. Как часто на сайте меняется код? Статичный сайт с обновлением раз в год и магазин с еженедельными плагинами — разный риск ошибки.
  3. Есть ли у клиента собственные требования? Некоторые заказчики в договоре или внутренних правилах прямо требуют отдельную инфраструктуру. Тогда выбор уже сделан за вас.
  4. Какова нагрузка и насколько она скачкообразна? Акции, рассылки и сезонность делают соседство рискованным.
  5. Кто имеет доступ к сайту со стороны клиента? Чем больше внешних людей с правами, тем выше вероятность ошибки, и тем важнее жёсткая граница.
  6. Какое время простоя клиент готов терпеть и кто за него платит? Это определяет, насколько нужны независимые обновления и раздельное обслуживание.

По ответам складывается примерно такая картина. Это авторский ориентир, а не стандарт отрасли, и пороги каждая студия выставит сама:

Ориентир для распределения клиентов по границам
Профиль клиентаРазумная границаПочему
Сайт-визитка, редкие правки, публичные данныеОтдельный пользователь и отдельная база на общем сервереЦена ошибки низкая, а обслуживание одного сервера проще
Магазин или сервис с активной разработкой, заметной нагрузкойКонтейнеры с лимитами ресурсов без лишних привилегий или отдельный VPSНужны свои версии окружения и контроль потребления
Кабинет с чувствительными данными, особые требования договораОтдельный VPS с отдельными ключами и копиями вне сервераНужна граница на уровне ядра и отдельный регламент доступа

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

Порядок перехода, если сайты уже живут вместе

Чаще всего задача возникает не на чистом месте, а когда три-десять сайтов давно работают на одном сервере. Переносить всё разом не стоит. Рабочий порядок такой:

  1. Составьте опись по каждому сайту: файлы, база, секреты, копии, доступы, версии окружения. Зафиксируйте, под каким пользователем работает каждый процесс.
  2. Закройте самое дешёвое и самое опасное: разведите системных пользователей, пулы процессов и учётные записи БД, проверьте права на каталоги и файлы конфигурации.
  3. Разделите ключи и копии. Это не требует нового оборудования и убирает самый частый обходной путь.
  4. Выберите одного самого рискованного клиента — с наибольшей ценностью данных или самым нестабильным кодом — и вынесите его первым в контейнер или на отдельный VPS. Проверьте, что в новом месте нет общих секретов со старым.
  5. Только после этого решайте, нужно ли переносить остальных, опираясь на таблицу профилей выше.

Для переноса отдельного клиента на собственный сервер удобно, что VPS MAATRIX оформляется быстро: в публичном предложении указано автоматическое создание сервера через пару минут после оплаты, есть root-доступ, NVMe-диски и процессоры AMD EPYC, а среди локаций перечислены UK, US, RU и FR. Оплата возможна картой РФ и через СБП. Точные образы и их наличие в каждой локации проверяйте в форме заказа — это зависит от выбранной конфигурации. Размер конфигурации выбирайте под реальную нагрузку конкретного сайта, а не под красивую строку тарифа, а копии храните отдельно от сервера: сам по себе отдельный VPS их не заменяет.

Граница, которая выдержит разговор с заказчиком

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

И последний вопрос, который стоит задать себе по каждому клиенту: если на его сайте случится ошибка, чью работу она затронет — только его или ещё чью-то? Ответ — не техническая деталь, а основание для цены услуги. Клиент, чья ошибка не должна задеть никого, получает отдельную границу и платит за собственный сервер и отдельное обслуживание. Клиент, который согласен жить по соседству, получает более скромную границу и меньший счёт. А студия получает возможность объяснять цену не размером тарифа, а размером ответственности, которую она на себя берёт.