Площадка под Drupal: где он не заведётся и какой VPS мы берём
Меня зовут Евгений Семёнов, я технический директор ITfresh — мы пятнадцать с лишним лет обслуживаем московские компании до 50 рабочих мест и держим сайты клиентов на собственных серверах в дата-центре МТС. В обзорной статье серии я объяснял, кому Drupal подходит, а кому нет. Здесь — чистая практика: как мы разворачиваем Drupal 11 и дистрибутив Drupal CMS так, чтобы сайт потом год не требовал внимания.
Первое, с чем сталкивается заказчик: у него уже есть «хостинг за двести рублей», и он хочет поставить Drupal туда. Отвечаю сразу — не получится, и дело не в снобизме. Drupal 11 требует PHP 8.3 и выше с набором расширений (PDO, mbstring, GD или ImageMagick, xml, json, curl, openssl), Composer 2 для сборки проекта и доступ по SSH, потому что без консоли вы не выполните ни одну операцию обслуживания. Базу данных берём MariaDB 10.6+ или MySQL 8.0+; PostgreSQL 16+ тоже поддерживается, но мы ставим его только там, где он уже есть у клиента. На дешёвом shared-тарифе обычно нет либо SSH, либо нужной версии PHP, либо возможности поднять лимит памяти выше 128 МБ, либо всего сразу.
Почему мы почти всегда селим такие сайты у себя в ЦОД, а не на сервере в офисе клиента? Три причины. Офисный канал — это один провайдер без резерва и публичный IP, который провайдер может поменять. Офисный сервер — это ещё и файловая помойка, 1С и терминал в одном корпусе, и любая их проблема тянет за собой сайт. И наконец, обновления безопасности Drupal выходят по средам, и накатывать их надо в течение дня-двух — это удобно делать централизованно, со своей площадки, где у нас уже настроены мониторинг и бэкапы.
Типовой профиль виртуальной машины, который мы выделяем под корпоративный сайт:
| Профиль | vCPU | RAM | Диск | Для чего |
|---|---|---|---|---|
| Стартовый | 2 | 4 ГБ | 40 ГБ SSD | Визитка или корпсайт до 10 разделов, редактируют 1–2 человека |
| Типовой | 4 | 8 ГБ | 80 ГБ SSD | Корпсайт компании до 50 РМ: новости, каталог услуг, формы, Redis |
| Усиленный | 4–6 | 16 ГБ | 160 ГБ SSD | Несколько сайтов в одной установке, поисковый индекс, интеграции с 1С и CRM |
Операционная система — актуальный LTS-релиз Ubuntu или Debian, nginx, PHP-FPM 8.3 с opcache и apcu, MariaDB, Redis. Всё это ставится из штатных репозиториев, ничего экзотического. В «стартовом» профиле память нужна не Drupal как таковому, а пиковым операциям: сборке composer, обновлению базы, генерации стилей изображений. На 2 ГБ всё это работает, но обновление ядра начинает упираться в swap, и мы предпочитаем закладывать запас.
Установка через Composer: ядро или дистрибутив Drupal CMS
Drupal давно не распаковывают из архива. Проект собирается Composer'ом, и у вас два стартовых шаблона. Первый — drupal/recommended-project: чистое ядро, пустая конфигурация, никаких contrib-модулей. Это выбор для проектов, где есть разработчик и собственная сборка. Второй — drupal/cms, дистрибутив Drupal CMS (актуальная версия 2.1.3), в котором сразу лежит набор рецептов, редактор Drupal Canvas с живым превью, библиотека компонентов и готовые шаблоны сайта. Для типового корпоративного сайта «о компании, услуги, новости, контакты» мы в восьми случаях из десяти берём именно дистрибутив: это экономит неделю ручной сборки типов контента и ролей.
# Вариант 1: чистое ядро
composer create-project drupal/recommended-project /var/www/example
cd /var/www/example
composer require drush/drush
# Вариант 2: дистрибутив Drupal CMS
composer create-project drupal/cms /var/www/example
cd /var/www/example
В обоих случаях вы получите одинаковую структуру: каталог web/ — это и есть docroot, куда смотрит веб-сервер; vendor/ — библиотеки PHP; config/sync/ — выгрузка конфигурации в YAML (о ней отдельная глава); composer.json и composer.lock — опись того, что стоит. Принципиальный момент, который не понимают те, кто пришёл из WordPress: веб-сервер должен видеть только web/. Каталог vendor, composer.lock, файлы с паролями от базы, приватные файлы и резервные копии лежат уровнем выше и снаружи недостижимы. Если разместить проект так, что docroot совпадает с корнем, вы публикуете в интернет половину своих внутренностей.

Права на файлы выставляем один раз и больше не трогаем: владелец кода — deploy-пользователь, группа — www-data, веб-серверу доступен на запись только web/sites/default/files и приватный каталог вне docroot. Сам settings.php после установки делаем доступным только для чтения. Это защищает от самой частой ошибки после взлома одного contrib-модуля: злоумышленник не может дописать что-то в код сайта, потому что PHP-процесс не имеет права туда писать.
Установщик в браузере или drush site:install
Мастер установки в браузере работает, и для первого знакомства он удобен: выбираете язык, профиль, вводите реквизиты базы. Но на продакшене мы его не используем: он зависит от лимитов PHP-FPM и таймаутов, а на русском языке ещё и тянет пакет переводов, что иногда упирается в лимит времени запроса. Консольная установка воспроизводима, её можно положить в скрипт и повторить на stage-сервере один в один:
vendor/bin/drush site:install standard \
--locale=ru \
--db-url=mysql://example:пароль@localhost/example \
--site-name="ООО Пример" \
--account-name=admin \
--account-pass='сложный-пароль' -y
vendor/bin/drush status
Для Drupal CMS вместо профиля standard используется собственный профиль дистрибутива, а набор стартовых рецептов выбирается в его мастере либо применяется после установки — о чём следующая глава. После site:install сразу же правим web/sites/default/settings.php: переносим реквизиты базы и хеш-соль в settings.local.php, который не попадает в git, задаём путь приватных файлов и каталог синхронизации конфигурации $settings['config_sync_directory'] = '../config/sync';.
drush status в тикет проекта. Через полгода, когда понадобится понять, какой PHP и какая версия ядра стояли на момент сдачи, это сэкономит час разбирательств.Рецепты Drupal CMS: сборка разделов за минуты
Слово «рецепт» сбивает с толку — звучит как демо-контент. На деле recipe в Drupal — это декларативный пакет: перечень модулей, которые нужно включить, набор конфигурации (типы контента, поля, представления Views, роли и права, формы), плюс опциональные действия вроде «добавить пункт меню». Рецепт применяется поверх живого сайта одной командой, не переустанавливает его и не трогает уже существующий контент. Сам Drupal CMS построен из таких рецептов, и в его поставке уже лежат готовые: новости, события, блог, карточки сотрудников, кейсы, SEO-инструменты, формы обратной связи, защита от спама.
# Посмотреть, что есть в дистрибутиве
ls recipes/
# Применить рецепт (из корня проекта)
php web/core/scripts/drupal recipe recipes/drupal_cms_news
php web/core/scripts/drupal recipe recipes/drupal_cms_events
# Сбросить кеш и проверить, что появились новые типы контента
vendor/bin/drush cr
vendor/bin/drush pm:list --status=enabled --type=module | grep -i cms
Реальный пример: клиенту — инжиниринговой компании на 40 сотрудников — нужен был блок «Новости + мероприятия + команда» с архивами по годам, лентой на главной и анонсами в сайдбаре. На чистом ядре это два-три дня работы: создать типы контента, поля даты и изображения, настроить стили картинок, собрать четыре представления Views, раздать права редактору. С рецептами дистрибутива у нас ушёл час, включая проверку. Рецепт ставит не только структуру, но и согласованные между собой настройки: у новостей сразу есть красивые URL через pathauto, метатеги, карта сайта. Дальше мы только переименовали поля под заказчика и переделали шаблон вывода.
Теперь честная часть. Кнопки «откатить рецепт» нет. Рецепт — это набор изменений конфигурации, и после применения они становятся частью сайта наравне с тем, что вы настроили руками. Если рецепт включил пять модулей и создал тип контента, выключать и удалять всё это придётся вручную или через откат конфигурации из git (об этом ниже). Поэтому наш порядок такой:
- Рецепты применяются только на dev-копии, никогда сразу на проде.
- Перед применением —
drush cexи коммит, чтобы было к чему вернуться. - После — просмотр diff конфигурации: что именно добавилось, какие права появились у каких ролей.
- Только потом — перенос на stage и прод через штатный импорт конфигурации.
Отдельно про AI-функции Drupal CMS 2.x: генерация лендинга из текстового описания, чат-бот в админке, автоматические alt-тексты для картинок. Они опциональны, требуют внешнего API-ключа OpenAI или Anthropic и на большинстве наших проектов выключены — клиентам в России проще и безопаснее без внешних AI-сервисов. Но alt-тексты, если ключ всё-таки есть, реально экономят редакторам время.
Веб-сервер: эталонный конфиг nginx и PHP-FPM
Drupal из коробки заточен под Apache: в docroot лежит .htaccess, который закрывает служебные файлы и делает чистые URL. Если у вас Apache с mod_php или php-fpm — сайт заработает почти без усилий, и для старта это честно проще. Мы же на всех площадках используем nginx: он заметно экономнее по памяти при десятках одновременных запросов, и под него у нас единая схема для всех CMS клиентов. Плата за это — nginx не читает .htaccess, и все правила безопасности надо воспроизвести в server-блоке самостоятельно. Вот наш выверенный минимум:
server {
listen 443 ssl http2;
server_name example.ru www.example.ru;
root /var/www/example/web;
index index.php;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
client_max_body_size 64m;
# Скрытые файлы и служебные каталоги
location ~ /\.(?!well-known) { deny all; }
location ~ ^/sites/.*/private/ { return 403; }
location ~ (^|/)\.(git|svn)|composer\.(json|lock)$|\.(yml|yaml|twig|engine|inc|install|module|profile|po|sh|sql|theme|log|bak)$ {
return 404;
}
# Никакого PHP внутри файлов, загруженных пользователями
location ~ ^/sites/[^/]+/files/.*\.php$ { deny all; }
# Стили изображений генерируются по первому запросу
location ~* ^/sites/.*/files/styles/ { try_files $uri @rewrite; }
# Чистые URL
location / { try_files $uri /index.php?$query_string; }
location @rewrite { rewrite ^ /index.php; }
# Статика
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|woff2?)$ {
try_files $uri @rewrite;
expires 30d;
log_not_found off;
}
# PHP: только index.php и update.php
location ~ '^/(index|update)\.php(/|$)' {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS on;
fastcgi_intercept_errors on;
fastcgi_read_timeout 300;
fastcgi_pass unix:/run/php/php8.3-fpm-example.sock;
}
location ~ \.php$ { return 404; }
}
Три блока здесь важнее остальных. Запрет исполнения PHP в sites/*/files — это защита от классической атаки «загрузить картинку с расширением .php через форму». Правило try_files $uri /index.php?$query_string отдаёт существующие файлы напрямую, а всё остальное — фронт-контроллеру Drupal, так работают чистые URL. И финальный location ~ \.php$ { return 404; }: мы принципиально разрешаем запускать только index.php и update.php, всё прочее в docroot — не точка входа.
На стороне PHP-FPM у каждого сайта свой пул с собственным сокетом и пользователем — так один взломанный сайт не видит файлы соседнего. Ключевые параметры из php.ini пула:
memory_limit = 256M
max_execution_time = 120
upload_max_filesize = 64M
post_max_size = 64M
opcache.enable = 1
opcache.memory_consumption = 192
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
apc.enabled = 1
apc.shm_size = 64M
Минимум, который проверяет сам Drupal, — 64 МБ, но с таким лимитом админка с Views и редактором Canvas начнёт падать при сохранении сложных страниц. 256 МБ — наш стандарт; мы видели проекты, где нужно было 512 для генерации больших PDF. opcache.validate_timestamps = 0 даёт заметную экономию процессора, потому что PHP перестаёт проверять дату каждого файла при каждом запросе; цена — после выкладки кода обязательно перезапускать пул PHP-FPM, иначе сайт будет крутить старые файлы. Мы зашили перезапуск в скрипт деплоя и забыли об этом.
HTTPS и грабля с trusted_host_patterns
Сертификат — через certbot с плагином для nginx, продление по системному таймеру, сайт на 80-м порту только редиректит на 443. В settings.php сообщаем Drupal, что он за HTTPS, и — самое важное — объявляем, на какие доменные имена он вообще имеет право отвечать:
$settings['trusted_host_patterns'] = [
'^example\.ru$',
'^www\.example\.ru$',
];
$settings['reverse_proxy'] = FALSE;
$settings['file_private_path'] = '../private';
Грабля следующая: без trusted_host_patterns статус-отчёт горит красным, а с ними новички получают «The provided host name is not valid for this server» при первом же обращении по IP или по техническому домену вида stage.example.ru. Это не ошибка, это защита от подмены заголовка Host — Drupal просто отказывается генерировать ссылки на чужое имя. Правильное решение — добавить все легитимные имена в список, в том числе для stage-окружения в его собственном settings.local.php, а не отключать проверку.
Кеширование: три слоя против мифа о «медленном Drupal»
Каждый раз, когда мне показывают «тормозящий Drupal», я первым делом открываю /admin/config/development/performance — и в большинстве случаев кеш страниц там выключен, потому что кто-то отключил его «на время разработки» и забыл. Без кеша Drupal на каждый запрос собирает страницу из сотен сущностей, и это действительно медленно. С кешем — это одна из самых быстрых CMS из коробки, потому что архитектура кеша продумана глубже, чем у конкурентов.

Слой первый — Internal Page Cache. Готовая HTML-страница для анонимного посетителя целиком хранится в кеше и отдаётся без участия ни одного плагина. Работает только для анонимов и только для страниц без персонализации — то есть ровно для 95% трафика корпоративного сайта. Слой второй — Dynamic Page Cache: страница кешируется кусками, и те блоки, что зависят от пользователя (имя в шапке, персональное меню), дорисовываются отдельно. Он работает и для авторизованных редакторов. Третий — render cache отдельных сущностей и блоков: если новость уже один раз отрисована, её HTML переиспользуется на всех страницах, где она встречается. Все три слоя в ядре, все три включены по умолчанию, и ломать их не надо.
Главное, что делает этот механизм умным, — теги инвалидации. Когда редактор правит новость, сбрасываются только те кешированные страницы, на которых эта новость участвует, а не весь кеш сайта. Поэтому «обновили текст, а на сайте старый» — в Drupal почти никогда не проблема; если это случилось, значит, кто-то собрал кастомный блок без тегов.
Где живёт кеш по умолчанию? В базе данных. Для «стартового» профиля этого достаточно. На «типовом» и выше мы переносим кеш в Redis: ставим php-redis, сервер Redis на том же хосте и contrib-модуль redis:
apt install redis-server php8.3-redis
composer require drupal/redis
vendor/bin/drush pm:install redis -y
// settings.php
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['cache']['default'] = 'cache.backend.redis';
$settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml';
Эффект — разгрузка базы: десятки запросов к таблицам cache_* на каждую страницу превращаются в обращения к памяти, и редакторам, которые видят сайт без Page Cache, становится ощутимо быстрее работать. По нашим замерам порядок такой: холодная страница с выключенными кешами — сотни миллисекунд, иногда за секунду на тяжёлых Views; та же страница из Internal Page Cache — единицы миллисекунд на стороне приложения. Разница на порядок и больше, и именно она определяет, сколько одновременных посетителей выдержит «типовой» VPS.
Varnish и CDN: когда оправдано, а когда лишнее
Varnish перед nginx и CDN перед Varnish — стандартная архитектура для медийных порталов с сотнями тысяч просмотров в день. У корпоративного сайта компании на 50 сотрудников посещаемость измеряется сотнями, редко тысячами в день, и Internal Page Cache в Redis закрывает эту нагрузку с запасом. Varnish добавляет ещё один слой, который надо инвалидировать, настраивать и мониторить, а значит, ещё одну точку отказа. Мы ставим его, только когда есть конкретная причина: реальные пики трафика от рекламы, публичный каталог с тысячами карточек или требование отдавать сайт при временной недоступности бэкенда. CDN оправдан, если у вас аудитория из разных регионов и много тяжёлых медиафайлов; для московской компании с московскими клиентами это чаще всего деньги без эффекта.
Локализация: русский интерфейс без боли
Когда вы указываете --locale=ru при установке (или выбираете русский в мастере), Drupal сам скачивает актуальный пакет переводов с localize.drupal.org и импортирует его. Переводы ядра на русский полные и качественные — в админке не будет англо-русской каши. Включаются модули Language, Interface Translation (locale) и, если нужен многоязычный контент, Content Translation и Configuration Translation. Для сайта только на русском последние два не нужны: один язык по умолчанию, и всё.
Проблемы начинаются с contrib-модулями. Переводы для них тоже живут на localize.drupal.org, но покрытие разное: у популярных модулей вроде pathauto, metatag или webform русский есть почти полностью, у нишевых — наполовину или вовсе нет. После установки каждого нового модуля Drupal пытается подтянуть его перевод автоматически (это делает cron), а недостающие строки остаются на английском. Добить их руками можно на странице /admin/config/regional/translate: вводите английскую фразу, находите её, вписываете русский вариант. Это работает для любых строк, проходящих через механизм перевода, и изменения сохраняются в базе.
# Обновить переводы для всех модулей после установки новых
vendor/bin/drush locale:check
vendor/bin/drush locale:update
# Экспортировать свои правки переводов в файл (для переноса на прод)
vendor/bin/drush locale:export ru --types=customized > translations/ru.custom.po
Три практических совета, к которым мы пришли. Первый: не переводите насильно служебные термины — «нода», «таксономия», «представление» в русском переводе ядра уже есть, и менеджеры привыкают к ним за неделю; попытка переименовать их в «статья» и «раздел» ломает соответствие с документацией, по которой они же будут гуглить. Второй: свои переводы помечаются как «customized» и не перезаписываются при следующем обновлении пакета — но только если вы правили их через интерфейс или импортировали с нужным флагом; правка напрямую в .po-файле модуля слетит при следующем composer update. Третий: обновление переводов зависит от cron, и если cron не настроен (см. чек-лист), новые модули так и останутся на английском, а вы будете думать, что перевода нет.
С языком контента всё проще: поля, типы контента и меню вы создаёте сразу на русском, и переводить тут нечего. Если сайт двуязычный, включайте Content Translation с самого начала — добавить второй язык на живой сайт через полгода возможно, но URL-структура и уже сделанные Views потребуют ревизии.
Конфигурация как код: drush cex и drush cim
Если бы меня попросили назвать одну причину, по которой мы выбираем Drupal для проектов с несколькими окружениями, — это система управления конфигурацией. Каждый тип контента, каждое поле, каждое представление, роль, настройка модуля и даже включённый список модулей — это объект конфигурации, который экспортируется в YAML-файл. Команда drush cex выгружает всю конфигурацию сайта в config/sync/, drush cim накатывает её обратно. Папка лежит в git вместе с кодом, и любое изменение видно как diff.
# На dev-сервере после настройки через админку
vendor/bin/drush cex -y
git add config/ composer.json composer.lock
git commit -m "Тип контента «Вакансии» + представление списка"
git push
# На проде — скрипт деплоя
git pull
composer install --no-dev --optimize-autoloader
vendor/bin/drush state:set system.maintenance_mode 1 -y
vendor/bin/drush updb -y
vendor/bin/drush cim -y
vendor/bin/drush cr
vendor/bin/drush state:set system.maintenance_mode 0 -y
systemctl reload php8.3-fpm
Что это меняет в работе? На проде никто не кликает в админке. Вообще. Все структурные изменения делаются на dev, экспортируются, проходят через stage, где их смотрит заказчик, и только потом попадают на прод ровно в том виде, в каком были проверены. Когда что-то сломалось — git log по папке config показывает, кто, когда и что именно поменял, и откат — это git revert плюс drush cim. В WordPress такой дисциплины в принципе нет: настройки плагинов живут в базе, и перенос между окружениями превращается в экспорт-импорт дампов с заменой URL.
Порядок команд в деплое не случаен. Сначала updb — обновления базы от новых версий модулей, потом cim — импорт конфигурации, потом сброс кеша. Перепутать местами — получить ошибку импорта, потому что конфигурация ссылается на схему, которой в базе ещё нет. Перед cim полезно глянуть drush config:status: он покажет, какие объекты отличаются между файлами и базой, и если там неожиданно много «только в базе», значит, кто-то всё-таки кликал на проде.
Для разных окружений мы используем модуль config_split: на dev включены devel и отключён кеш, на проде наоборот — и эти различия лежат в отдельных наборах конфигурации, которые активируются в зависимости от окружения. Так одна и та же выгрузка честно работает везде.
Чего в конфигурации нет и как с этим жить
В YAML не попадает контент: ноды, пользователи, термины таксономии, медиафайлы, комментарии, отправки веб-форм. Не попадают загруженные файлы из sites/default/files. Не попадает состояние (state) — временные значения вроде времени последнего запуска cron. И не попадают значения из settings.php, которые переопределяют конфигурацию — например, ключи API, которые мы намеренно держим вне git.
- Контент течёт в одну сторону: с прода на dev, через
drush sql:dumpиrsyncфайлов. Никогда наоборот — иначе затрёте то, что редакторы написали за неделю. - Стартовый контент при запуске (страницы «О компании», «Контакты») мы создаём на stage или заливаем миграцией с помощью модулей migrate_plus и migrate_tools — об этом подробнее в статье про миграцию.
- Секреты живут в
settings.local.phpи переопределяют конфигурацию через$config[], так что в YAML лежат пустые значения. - UUID сайта должен совпадать между окружениями, иначе
cimоткажется работать. Мы ставим его принудительно при создании каждого окружения из одной и той же выгрузки.
Чек-лист передачи сайта клиенту: 12 пунктов
Сайт «работает» и сайт «готов к передаче» — разные состояния. За годы мы собрали список, который инженер проходит перед тем, как отдать доступы контент-менеджерам заказчика. Каждый пункт родился из реального инцидента, поэтому пропускать их мы не разрешаем даже на «простых» проектах.
- Cron запускается из системного crontab, а не «ленивым» cron'ом по заходам посетителей. Строка вида
*/15 * * * * deploy cd /var/www/example && vendor/bin/drush core:cron, а автоматический запуск в/admin/config/system/cronвыключен. Иначе на сайте с низкой посещаемостью переводы, индексы и очистка временных файлов не работают неделями. - Статус-отчёт без красного и жёлтого.
/admin/reports/statusчист: права на файлы, trusted hosts, версия PHP, доступность приватного каталога, актуальность ядра. Жёлтое предупреждение сегодня — это красная ошибка через месяц. - Ядро на последнем патч-релизе (сейчас 11.4.5), все contrib-модули обновлены,
composer outdated "drupal/*"не показывает известных security-релизов. - Роль контент-менеджера без лишних прав. Создание и правка своего контента — да; администрирование модулей, пользователей, Views, темы — нет. Учётка admin с UID 1 передаётся клиенту в запечатанном виде и хранится у нас в сейфе паролей.
- Бэкап настроен и проверен восстановлением. Ежедневный дамп базы через
drush sql:dumpплюс копияsites/default/filesи приватного каталога — на отдельное хранилище, с ротацией. «Проверен» — значит, мы развернули копию на тестовой машине и открыли главную. - Обновления безопасности в расписании. Для Drupal CMS включены автообновления дистрибутива там, где это применимо; для классического проекта — в нашем календаре стоит проверка каждую среду, потому что именно в этот день команда безопасности Drupal публикует advisories.
- HTTPS и редиректы. Сертификат продлевается автоматически, http → https, www ↔ без www в одну сторону, HSTS включён.
- Кеш и агрегация включены. Internal Page Cache, Dynamic Page Cache, агрегация CSS/JS — всё в положении «вкл», время жизни кеша для анонимов задано. Devel и прочие отладочные модули на проде отсутствуют.
- Защита форм. На каждой публичной форме — honeypot или antibot, для webform дополнительно лимит отправок. Без этого спам в «обратную связь» начинается на вторую неделю.
- SEO-минимум. pathauto с понятными шаблонами адресов, metatag с дефолтами для каждого типа контента, simple_sitemap генерирует карту сайта, модуль redirect ловит переименованные URL.
- Конфигурация выгружена и совпадает с git.
drush config:statusпуст, последний коммит в config/ соответствует тому, что на проде, stage синхронизирован. - Мониторинг и документация. Хост в нашем Zabbix: доступность, место на диске, сертификат, ошибки в логах PHP-FPM. В тикете проекта — вывод
drush status, схема окружений, кто за что отвечает, и короткая инструкция для редакторов с картинками.
На полный проход по списку у инженера уходит около двух часов, если сайт собран по описанной выше схеме, и полдня, если сайт достался от предыдущего подрядчика. Второй случай чаще — и именно поэтому список начинается с cron и статус-отчёта: они мгновенно показывают, насколько аккуратно работали до вас.
Если вам нужно развернуть Drupal 11 или Drupal CMS под корпоративный сайт, перенести существующий сайт на нормальную площадку или просто провести аудит того, что уже есть, — напишите нам. ITfresh, Telegram @ITfresh_Boss, телефон +7 903 729-62-41. Разворачиваем на собственных серверах в дата-центре МТС, сопровождаем по абонентке, первая консультация — бесплатно.
Оставить комментарий