# Мультисайт на движке NGCMS: плюсы и минусы
> Статья основана на практическом опыте внедрения мультисайта в NGCMS (февраль–апрель 2026 г.) и актуальной документации проекта.
---
## Что такое мультисайт в NGCMS
Мультисайт — это режим работы NGCMS, при котором **одна установка движка** обслуживает несколько доменов одновременно. Каждый дополнительный сайт хранит свою конфигурацию в `engine/conf/multi/{site_id}/`, имеет изолированную папку загрузок (`uploads/multi/{site_id}/`) и может работать в одном из двух режимов базы данных: **shared** (общая БД с отдельным префиксом таблиц) или **separate** (полностью отдельная БД на своём MySQL-сервере). Основной (master) сайт управляет всеми дочерними через единую админ-панель.
Конфигурация хранится в `engine/conf/multiconfig.php`:
```php
$multimaster = 'main';
$multiconfig = [
    'main' => ['domains' => ['example.com', 'www.example.com'], 'active' => 1],
    'blog' => ['domains' => ['blog.example.com'],               'active' => 1],
    'shop' => ['domains' => ['shop.example.com'],               'active' => 1],
];
```
---
## Плюсы
### 1. Одна кодовая база — несколько сайтов
Все дочерние сайты работают на одних и тех же файлах движка, шаблонах и плагинах. Обновление движка делается один раз и сразу применяется ко всей сети. Нет риска "забыть обновить" один из сайтов.
### 2. Два режима работы с базой данных
При добавлении дочернего сайта выбирается один из режимов:
- **Shared (общая БД)** — сайт получает собственный префикс таблиц (например `blog_`, `shop_`), таблицы автоматически копируются с данными мастер-сайта. Не нужен отдельный MySQL-пользователь — всё в одной базе.
- **Separate (внешняя БД)** — сайт подключается к совершенно другой MySQL-базе (отдельный host, dbname, user, password). Полная изоляция данных, подходит для случаев когда дочерний сайт должен физически находиться в другой базе.
  В обоих случаях настройки хранятся в `engine/conf/multi/{site_id}/config.php`, переключение происходит прозрачно для движка.
### 3. Полное управление из одной админ-панели
Из интерфейса мастер-сайта можно:
- добавить/удалить/включить/выключить дочерний сайт;
- переключиться в конфиг нужного сайта прямо из страницы «Конфигурация» (GET-параметр `site_id`);
- видеть список всех мультисайтов и их статусы в одной таблице.
### 4. Изолированные загрузки
Каждый сайт хранит медиафайлы в `uploads/multi/{site_id}/`: аватары, изображения, файлы, вложения. Папки создаются автоматически при добавлении сайта. Пути прописываются в конфиге автоматически, URL-адреса включают домен дочернего сайта.
### 5. Динамический robots.txt
Файл `robots.php` в корне сайта определяет домен по `$_SERVER['HTTP_HOST']` и отдаёт нужный `robots.txt` из `engine/conf/multi/{site_id}/robots.txt`. Поддерживаются плейсхолдеры `{SITE_URL}` и `{DOMAIN}`, которые заменяются налету. Каждому дочернему сайту можно задать свои правила для поисковых роботов — вплоть до полного закрытия тестового окружения (`Disallow: /`).
### 6. Встроенная мультиязычность
Поверх мультисайта реализована система переводов статей (`multilang_enabled`). Сайты с флагом `multilang_enabled = 1` связывают новости через `translation_group_id`. Автоопределение языка по домену (ru.web.ua → `ru`, en.web.ua → `en`), блок управления переводами прямо в редакторе новости. Можно отключить для конкретного сайта, не затрагивая остальные.
Для включения мультиязычности требуется **одноразовая SQL-миграция**: добавить колонки `translation_group_id` и `lang_code` в таблицу `ng_news`. Готовый скрипт находится в `engine/trash/upgrade_multilang.sql`. Язык каждого сайта задаётся параметром `lang` прямо в `multiconfig.php`:
```php
$multiconfig = [
    'main'    => ['domains' => ['ru.example.com'], 'active' => 1, 'lang' => 'ru', 'multilang_enabled' => 1],
    'en_site' => ['domains' => ['en.example.com'], 'active' => 1, 'lang' => 'en', 'multilang_enabled' => 1],
    'uk_site' => ['domains' => ['uk.example.com'], 'active' => 1, 'lang' => 'uk', 'multilang_enabled' => 0],
];
```
### 7. Автоматизация на Windows (OSPanel)
При добавлении нового сайта движок автоматически создаёт **junction link** в папке OSPanel (`mklink /J`), `.osp/project.ini` с нужной версией PHP. Никаких ручных шагов в панели управления локального сервера не требуется.
### 8. Гибкость размещения на хостинге
Поддерживаются три схемы деплоя: парковка доменов в cPanel/ISPmanager/Plesk (рекомендуется), символические ссылки через SSH, а также `.htaccess`-редиректы как запасной вариант. Протестировано на Beget, TimeWeb, Majordomo, RU-CENTER.
### 9. Инструменты миграции
Утилита `fix_multisite_urls.php` позволяет массово заменить старые абсолютные URL загрузок (`https://old.ru/uploads/files/`) на новые относительные пути мультисайта (`/uploads/multi/{site_id}/files/`) во всех контентных таблицах БД. Запуск через браузер с секретным ключом, поддержка dry-run режима.
### 10. Раздельный SEO-контроль
Каждый дочерний сайт имеет собственные: `robots.txt`, sitemap-URL в `home_url`, настройки ЧПУ (`rewrite.php`, `urlconf.php`), права доступа (`perm.rules.php`). Это позволяет продвигать сайты независимо.
### 11. Изоляция конфигурации плагинов (extras/)
Каждый дочерний сайт хранит настройки плагинов в `engine/conf/multi/{site_id}/extras/` — это полная копия папки `engine/conf/extras/` мастер-сайта. Настройки плагина (например, SEO-мета, заголовки, параметры форм) можно менять независимо для каждого сайта, не затрагивая остальных. При создании нового мультисайта `extras/` копируется автоматически.
### 12. Независимый планировщик задач
Каждый сайт имеет собственный `engine/conf/multi/{site_id}/cron.php` с индивидуальными настройками расписания. Автобэкап, очистка кеша, генерация sitemap — всё можно настроить раздельно. При добавлении сайта `cron.php` копируется с мастер-сайта и редактируется независимо.
### 13. Переменная `isMainSite` в шаблонах
Во всех Twig-шаблонах доступна переменная `isMainSite` — булево значение, которое равно `true` только на мастер-сайте. Позволяет скрывать или показывать блоки в зависимости от того, на каком сайте находится пользователь, без дублирования шаблонов:
```twig
{% if isMainSite %}
    <a href="/engine/?action=configuration&do=multisiteManage">Управление мультисайтами</a>
{% endif %}
```
Применяется в шаблонах конфигурации, меню, админ-панели — кнопки управления сетью видны только администратору мастер-сайта.
## Минусы
### 1. Повышенный порог входа
Мультисайт — не «из коробки» функция стандартной установки NGCMS. Требуется ручная правка `multiconfig.php`, понимание структуры конфигов `engine/conf/multi/`, настройка DNS/виртуальных хостов. Для начинающего администратора это нетривиально.
### 2. Риски общей базы данных (режим shared)
В режиме **shared** все сайты работают в одной MySQL-базе. Ошибочный запрос или `DROP TABLE` без учёта префикса может задеть чужие таблицы. Режим **separate** этот риск снимает, но добавляет накладные расходы: нужно управлять несколькими MySQL-пользователями, вести отдельные бэкапы, следить за доступностью каждого хоста БД.
**Автобэкап изолирован по prefix** (исправлено): функция `AutoBackup()` в `engine/includes/inc/functions.inc.php` использует отдельные файлы-флаги (`cache/last_backup_ng_.tmp`, `cache/last_backup_blog_.tmp`) и создаёт бэкапы с именем по prefix (`backups/backup_ng__2026_04_28.gz`). Каждый сайт делает бэкап своих таблиц независимо по своему расписанию `auto_backup_time`. Бэкап содержит только таблицы с префиксом текущего сайта (`show tables like 'prefix_%'`).
### 3. Жёсткая зависимость от файловой системы (Windows)
На Windows используются junction links вместо symlinks. Junction — это NTFS-специфичный механизм, который не поддерживается в Git, не копируется стандартными архиваторами и может запутать инструменты деплоя. При переносе на Linux потребуется пересоздавать ссылки командой `ln -s`.
### 4. Нет изоляции кода плагинов
Плагины (`engine/plugins/`) — общие для всех сайтов. Конфигурация плагинов (`plugins.php`, `plugdata.php`, `extras/`) копируется и изолируется на уровне файлов настроек, но **код плагинов один**. Обновление или конфликт плагина влияет на всю сеть. Нельзя поставить плагин «только для одного сайта» — любой активированный плагин работает везде.
### 5. Сложность отладки
При проблемах на конкретном домене нужно понимать: ядро загружает `multimaster.php` дважды (до и после config.php), переменная `$multiDomainName` устанавливается глобально, путь `confroot` зависит от HTTP_HOST. Ошибки в `multiconfig.php` приводят к тому, что все сайты «падают» одновременно.
### 6. Общие шаблоны
Папка `templates/` — единая. Если два сайта используют один шаблон, изменение внешнего вида одного сайта может сломать другой. Для полной визуальной независимости нужно создавать копии шаблонов и прописывать их в конфигах отдельных сайтов.
### 7. Ограниченное разграничение прав администраторов
Доступ к управлению мультисайтами возможен **только с мастер-сайта** (проверка `$multiDomainName`). Нет системы ролей типа «администратор только своего сайта» — любой админ мастера видит и управляет всей сетью.
### 8. Масштабирование нагрузки
Один PHP-процесс, один MySQL-сервер на все сайты. Горизонтальное масштабирование (разные серверы для разных сайтов) нативно не поддерживается. При высоком трафике придётся выносить сайты на отдельные установки движка вручную.
### 9. Миграция существующего сайта в мультисайт
При переносе уже работающего сайта в мультисайт нужно заменить все абсолютные URL в контенте (для этого создана утилита `fix_multisite_urls.php`). Без этого шага изображения и ссылки в статьях будут вести на неверные адреса. Это разовая но обязательная операция, требующая тщательной проверки.
### 10. Зависимость robots.txt от PHP
Стандартный `robots.txt` заменён PHP-скриптом (`robots.php`) через `.htaccess`. Если PHP недоступен, кеш сбит или `.htaccess`-модуль отключён — поисковики получат 500/404 вместо корректного `robots.txt`. Нужно держать резервную копию (`robots.txt.static`) и следить за работоспособностью редиректа.
### 11. Общий кэш для всей сети
Папка `engine/cache/` единая для всех сайтов мультисайта. Сброс кэша через админ-панель одного сайта очищает кэш **всей сети** — это может привести к кратковременной повышенной нагрузке на БД и PHP сразу по всем сайтам. Нет возможности сбросить кэш только одного конкретного сайта без затрагивания остальных.
## Когда мультисайт оправдан
| Сценарий                                            | Подходит?                   |
| --------------------------------------------------- | --------------------------- |
| Сеть тематических блогов с общим движком            | ✅ Да                       |
| Языковые версии одного сайта (ru/en/uk)             | ✅ Да, особенно с multilang |
| Несколько витрин на одном аккаунте хостинга         | ✅ Да                       |
| Тестовое окружение (dev/stage/prod)                 | ✅ Да                       |
| Разные сайты с разной нагрузкой и разными командами | ⚠️ Осторожно                |
| Высоконагруженный проект (>50k RPS)                 | ❌ Нет                      |
| Сайты с разными версиями движка                     | ❌ Нет                      |
---
## Итог
Мультисайт NGCMS — это **мощный инструмент для малых и средних сетей сайтов** при условии, что все они работают на одном сервере, в руках одной команды и на одной версии движка. Он значительно снижает накладные расходы на обслуживание: одно обновление, одна кодовая база, единая точка управления. Расплатой за это является общая точка отказа, сложность изоляции и более высокий порог настройки по сравнению с «просто поставить ещё один сайт».
_Документация: [hosting-multisite.md](hosting-multisite.md), [multisite-changelog.md](multisite-changelog.md), [multisite-robots.md](multisite-robots.md), [MULTILANG-README.md](MULTILANG-README.md)_
