Представьте три сайта разных заказчиков на одном сервере. Первый — тихий сайт-визитка стоматологической клиники, который не трогали с прошлой осени. Второй — интернет-магазин, где маркетолог каждую неделю просит «поставить ещё один плагин для скидок». Третий — личный кабинет небольшой бухгалтерской фирмы с выгрузками договоров. Если плагин из второго сайта окажется дырявым, вопрос будет не в том, «упадёт ли магазин». Вопрос в том, что сможет сделать злоумышленник дальше и чьи данные окажутся у него в руках. От ответа зависит, останется ли инцидент проблемой одного заказчика или превратится в три неприятных письма и пересмотр договоров.
Поэтому выбирать способ размещения «по удобству» — значит начинать с середины. Сначала нужно понять, где проходят границы, а потом уже решать, чем их обеспечить: 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 для веб-студии и агентства: что выбрать и как настроить.
Как связать выбор с ценностью данных и условиями клиента
Теперь вернёмся к исходному вопросу. Выбор не должен быть единым для всех клиентов. Разумная студия строит не одну схему, а несколько уровней, и клиент попадает в уровень по понятным признакам. Вот набор вопросов, которые помогают разместить заказчика:
- Что случится при утечке данных клиента? Для визитки с публичным текстом — почти ничего. Для личного кабинета с договорами, персональными данными и платёжными событиями — юридические и репутационные последствия.
- Как часто на сайте меняется код? Статичный сайт с обновлением раз в год и магазин с еженедельными плагинами — разный риск ошибки.
- Есть ли у клиента собственные требования? Некоторые заказчики в договоре или внутренних правилах прямо требуют отдельную инфраструктуру. Тогда выбор уже сделан за вас.
- Какова нагрузка и насколько она скачкообразна? Акции, рассылки и сезонность делают соседство рискованным.
- Кто имеет доступ к сайту со стороны клиента? Чем больше внешних людей с правами, тем выше вероятность ошибки, и тем важнее жёсткая граница.
- Какое время простоя клиент готов терпеть и кто за него платит? Это определяет, насколько нужны независимые обновления и раздельное обслуживание.
По ответам складывается примерно такая картина. Это авторский ориентир, а не стандарт отрасли, и пороги каждая студия выставит сама:
| Профиль клиента | Разумная граница | Почему |
|---|---|---|
| Сайт-визитка, редкие правки, публичные данные | Отдельный пользователь и отдельная база на общем сервере | Цена ошибки низкая, а обслуживание одного сервера проще |
| Магазин или сервис с активной разработкой, заметной нагрузкой | Контейнеры с лимитами ресурсов без лишних привилегий или отдельный VPS | Нужны свои версии окружения и контроль потребления |
| Кабинет с чувствительными данными, особые требования договора | Отдельный VPS с отдельными ключами и копиями вне сервера | Нужна граница на уровне ядра и отдельный регламент доступа |
Обратите внимание, что студия при такой схеме не обязана переносить всех на отдельные серверы. Но она обязана уметь объяснить, почему клиент оказался там, где оказался, и что именно ему за это гарантируется. Ни одного обещания вроде «ваш сайт полностью защищён» произносить не нужно: честнее перечислить, от чего граница защищает, а от чего нет.
Порядок перехода, если сайты уже живут вместе
Чаще всего задача возникает не на чистом месте, а когда три-десять сайтов давно работают на одном сервере. Переносить всё разом не стоит. Рабочий порядок такой:
- Составьте опись по каждому сайту: файлы, база, секреты, копии, доступы, версии окружения. Зафиксируйте, под каким пользователем работает каждый процесс.
- Закройте самое дешёвое и самое опасное: разведите системных пользователей, пулы процессов и учётные записи БД, проверьте права на каталоги и файлы конфигурации.
- Разделите ключи и копии. Это не требует нового оборудования и убирает самый частый обходной путь.
- Выберите одного самого рискованного клиента — с наибольшей ценностью данных или самым нестабильным кодом — и вынесите его первым в контейнер или на отдельный VPS. Проверьте, что в новом месте нет общих секретов со старым.
- Только после этого решайте, нужно ли переносить остальных, опираясь на таблицу профилей выше.
Для переноса отдельного клиента на собственный сервер удобно, что VPS MAATRIX оформляется быстро: в публичном предложении указано автоматическое создание сервера через пару минут после оплаты, есть root-доступ, NVMe-диски и процессоры AMD EPYC, а среди локаций перечислены UK, US, RU и FR. Оплата возможна картой РФ и через СБП. Точные образы и их наличие в каждой локации проверяйте в форме заказа — это зависит от выбранной конфигурации. Размер конфигурации выбирайте под реальную нагрузку конкретного сайта, а не под красивую строку тарифа, а копии храните отдельно от сервера: сам по себе отдельный VPS их не заменяет.
Граница, которая выдержит разговор с заказчиком
Есть простой тест на зрелость выбранной схемы: сможете ли вы за минуту ответить, что произойдёт при ошибке на конкретном сайте? Не вообще, а поимённо: чьи файлы доступны, чьи базы закрыты, через какой ключ можно пойти дальше, кому придётся останавливать работу и в чьё расписание вмешается восстановление. Если на каждый вопрос есть конкретный ответ, схема выбрана осознанно, независимо от того, пользователи это, контейнеры или серверы. Если ответы расплываются, значит, размещение выбрано по удобству, а граница возникла случайно.
И последний вопрос, который стоит задать себе по каждому клиенту: если на его сайте случится ошибка, чью работу она затронет — только его или ещё чью-то? Ответ — не техническая деталь, а основание для цены услуги. Клиент, чья ошибка не должна задеть никого, получает отдельную границу и платит за собственный сервер и отдельное обслуживание. Клиент, который согласен жить по соседству, получает более скромную границу и меньший счёт. А студия получает возможность объяснять цену не размером тарифа, а размером ответственности, которую она на себя берёт.