Короткий ответ
Стейджинг закрывают паролем в конфиге веб-сервера (basic-auth в nginx или Apache), а не строкой Disallow: / в robots.txt. Пароль живёт на тестовом сервере и в репозиторий не попадает, поэтому деплой не может перенести его на рабочий сайт. robots.txt и мета-тег noindex лежат в коде проекта и уезжают в прод вместе со всем остальным.
После каждого релиза нужны три проверки на рабочем домене: содержимое файла robots.txt, поиск noindex в коде главной страницы и заголовки ответа сервера через curl. На всё уходит 5 минут.
Почему Disallow: / не защищает тестовый сайт
У Disallow: / на стейджинге два дефекта. Первый: он не закрывает от индексации. Google Search Central прямо пишет, что robots.txt управляет сканированием, а заблокированный URL может попасть в индекс, если на него есть ссылки. Тестовый поддомен находят по ссылке в письме, в таск-трекере с публичной доской, в скриншоте, в Referer. Потом в выдаче появляется dev.сайт.ee с пометкой, что описание недоступно.
Второй дефект дороже. Файл лежит в репозитории, и при релизе его копируют на прод. Сайт при этом работает, открывается, форма отправляется, в браузере никто ничего не заметит. Узнают через одну-две недели по графику показов в Search Console. В статье про миграцию сайта без потери трафика я называл это самой частой причиной провала переезда, и за годы аудитов это не изменилось.
| Способ закрыть стейджинг | Защищает от индексации | Может уехать в прод при деплое | Как проверить |
|---|---|---|---|
Disallow: / в robots.txt | Нет, закрывает только сканирование | Да, файл в репозитории | Открыть /robots.txt |
Мета-тег noindex в шаблоне | Да | Да, если не завязан на переменную окружения | Поиск noindex в исходном коде |
Заголовок X-Robots-Tag: noindex | Да | Да, если конфиг сервера копируют целиком | curl -I https://сайт.ee/ |
| Basic-auth на веб-сервере | Да, робот получает 401 | Нет, конфиг тестового сервера отдельный | Открыть сайт в режиме инкогнито |
| Доступ по списку IP | Да, робот получает 403 | Нет | Открыть сайт с мобильного интернета |
Как закрыть стейджинг, чтобы запрет не переехал
Рабочая схема у меня одна: basic-auth на уровне nginx только в конфиге тестового окружения. В проекте на Next.js или WordPress при этом нет ни одной строки про индексацию, которая отличалась бы между стейджингом и продом.
server {
server_name dev.example.ee;
auth_basic "Staging";
auth_basic_user_file /etc/nginx/.htpasswd-staging;
# ...
}
Если сайт живёт на Cloudflare, ту же задачу решает Cloudflare Access на поддомен стейджинга: доступ по почте или по одноразовому коду, и снова вне репозитория. На Vercel превью-сборки по умолчанию отдают X-Robots-Tag: noindex, но на свой домен продакшена этот заголовок не ставится, так что там риск другого рода: закрытым оказывается превью, которое вы отправили клиенту как «почти готовый сайт».
Когда без мета-тега в коде не обойтись (например, один шаблон Next.js собирается на все окружения), noindex включается только при явной переменной вроде SITE_ENV=staging. Отсутствие переменной должно означать «индексировать», а не наоборот. Если логика обратная, первый же сервер, где переменную забыли задать, окажется закрытым.
Где запрет прячется при релизе
Когда трафик просел после релиза, я проверяю 5 мест в таком порядке: от самого частого к самому незаметному, от robots.txt до правил Cloudflare.
- Файл
robots.txt. Открываюhttps://сайт.ee/robots.txtв браузере. ИщуDisallow: /без пути после слеша. Если файл генерируется (в Next.js этоapp/robots.ts), смотрю ещё и код генератора: там бывает условие по окружению с перепутанной веткой. - Мета-тег robots. Поиск
noindexв исходном коде главной и одной внутренней страницы, не в DevTools, а через «Просмотр кода страницы». Разные шаблоны могут вести себя по-разному. - Заголовок
X-Robots-Tag. Командаcurl -I https://сайт.ee/показывает заголовки ответа. Этот запрет не виден ни в коде страницы, ни в браузере, и поэтому его ищут последним, хотя проверяется он за секунду. - Настройка WordPress. Галочка «Попросить поисковые системы не индексировать сайт» хранится в базе данных в опции
blog_public. При переносе базы со стейджинга на прод она переезжает, даже если файлы проекта заливали чистыми. С версии 5.7 WordPress выводит в этом случае мета-тегnoindex, так что проверка из пункта 2 её тоже поймает. - Правила CDN и хостинга. Transform Rules в Cloudflare, заголовки в панели хостинга, плагины безопасности. Если
curl -IпоказываетX-Robots-Tag, а в конфиге nginx его нет, искать нужно здесь.
Отдельный случай, про который забывают: robots.txt открыт, но в нём закрыт путь к CSS и JS. Сайт в индексе, но Google рендерит его без стилей. Правила того, что закрывать в этом файле, а что нет, я разбирал в статье про sitemap.xml и robots.txt.
Проверка после релиза: пять минут
Эти 5 пунктов я прогоняю руками после любого релиза, который трогал шаблоны, конфиг nginx или базу данных.
https://сайт.ee/robots.txtв браузере: нетDisallow: /, есть строкаSitemap:с рабочим адресом.- Исходный код главной и одной карточки или статьи: нет
noindex,canonicalуказывает на рабочий домен, а не наdev.. curl -I https://сайт.ee/: статус 200, нетX-Robots-Tag: noindex.- «Проверка URL» в Search Console для главной с кнопкой «Проверить страницу на сайте»: статус «URL можно проиндексировать».
- Через два-три дня отчёт «Индексирование страниц»: не растёт категория «Заблокировано в файле robots.txt» или «Исключено тегом noindex».
Пункт про canonical появился в списке не для полноты. Шаблон Next.js или WordPress, собранный на стейджинге, иногда берёт домен из переменной окружения, и прод получает canonical на тестовый адрес. Google тогда видит две версии одного текста и выбирает каноническую сам; как это выглядит в отчётах, описано в разборе про дубли страниц.
Если запрет уже уехал в прод
Порядок действий зависит от того, какой запрет сработал: robots.txt или noindex. Поэтому сначала диагностика по 5 пунктам выше, потом правка в Search Console.
- Уехал
Disallow: /. Исправьте файл, затем в Search Console откройте отчёт о файле robots.txt и запросите повторное сканирование. Google кэшируетrobots.txtдо 24 часов, без запроса робот может ещё сутки работать по старой версии. - Уехал
noindex. Уберите его и отправьте на проверку URL главную и основные разделы. Остальное подтянется при обычном обходе. - В обоих случаях переотправьте
sitemap.xml: это даёт роботу список адресов, которые нужно обойти заново.
Срок возврата предсказать нельзя, он зависит от частоты обхода конкретного сайта. На сайте, который Googlebot посещает ежедневно, первые страницы возвращаются быстрее, чем на сайте на 30 страниц, куда робот заходит раз в неделю. Если через две-три недели страницы по-прежнему висят в статусе «Просканирована, но пока не проиндексирована», причина уже не в запрете, и дальше помогает разбор из статьи о том, почему страницы не индексируются в Google.
Кому basic-auth не подходит
Пароль на стейджинге неудобен в 3 ситуациях, и в них я выбираю Cloudflare Access, список IP или отдельный тестовый URL.
- Клиент или контент-менеджер смотрит тестовый сайт с телефона и путается в окне авторизации. Здесь лучше Cloudflare Access с входом по почте.
- Внешний сервис должен ходить на стейджинг без пароля: платёжный шлюз шлёт вебхуки, мониторинг проверяет доступность. Тогда доступ по списку IP с исключением для адресов сервиса, а не снятие защиты.
- Нужно проверить, как Google рендерит страницу до релиза. Инструмент «Проверка URL» на закрытый паролем сайт не зайдёт. Такую проверку делают на отдельном открытом URL с
noindex, который удаляют сразу после теста, и это единственное место, где мета-тег на тестовом окружении оправдан.
