Как настроить редирект в Nginx без rewrite: готовые конфигурации return | AdminWiki

Как настроить редирект в Nginx без rewrite: готовые конфигурации return

05 сентября 2026 14 мин. чтения
Содержание статьи

Как настроить редирект в Nginx без rewrite: короткий ответ

Для простого редиректа в Nginx используйте директиву return. Она сразу возвращает клиенту HTTP-код и заголовок Location, после чего обработка запроса завершается. Для переноса всего сайта подойдет запись return 301 https://new.example.com$request_uri;.

server {
    listen 80;
    listen [::]:80;
    server_name old.example.com;

    return 301 https://new.example.com$request_uri;
}

Для одной страницы правило размещают в точном location: location = /old-page. Для каталога используют отдельное правило для самого каталога и regex location для вложенных адресов. При переходе на другой домен указывайте абсолютный URL с протоколом, например https://external.example.com$request_uri.

После изменения конфигурации выполните sudo nginx -t, примените настройки командой sudo systemctl reload nginx и проверьте ответ через curl -I или curl -IL. При проблемах изучите активный server_name, порядок location и access log. Для SEO-переноса обновите внутренние ссылки, canonical и sitemap, а старые и новые адреса проверьте в Google Search Console и Яндекс Вебмастере.

Минимальный редирект через return

Фиксированный URL можно перенаправить коротким правилом:

location = /old-page {
    return 301 /new-page$is_args$args;
}

Запись location = /old-page означает точное совпадение пути. Запрос /old-page?ref=mail перейдет на /new-page?ref=mail. Переменная $is_args добавляет знак вопроса только при наличии параметров, а $args передает саму query string.

Когда исходный путь нужно сохранить полностью, используйте $request_uri:

return 301 https://new.example.com$request_uri;

Запрос /docs/install?version=2 в таком случае превратится в https://new.example.com/docs/install?version=2. Для нового домена в return указывайте полную схему и hostname.

Почему для простого редиректа не нужен rewrite

return отвечает на запрос готовым кодом и заранее известным адресом. Это удобный вариант для переноса домена, каталога, отдельной страницы или всей HTTP-версии сайта на HTTPS.

rewrite преобразует URI по шаблону и может работать с регулярными выражениями и условиями. Он нужен, когда адрес строится по сложному правилу. Для фиксированного перенаправления такая логика увеличивает объем конфигурации и усложняет аудит.

Правило через return проще сопоставить с задачей: виден код ответа, целевой URL и область действия. Для команды поддержки это сокращает время проверки и снижает риск случайно затронуть соседние адреса.

Nginx 301 redirect и временный 302: какой код выбрать

HTTP-код выбирают по смыслу операции. 301 сообщает о постоянном переносе, 302 обозначает временное переключение, а 307 и 308 сохраняют HTTP-метод и тело запроса.

КодСценарийПоведение метода
301Постоянный перенос страницы, каталога или доменаКлиент может заменить POST на GET
302Временный тест, обслуживание или короткое переключениеКлиент может заменить POST на GET
307Временный перенос с сохранением способа запросаМетод и тело сохраняются
308Постоянный перенос с сохранением способа запросаМетод и тело сохраняются

Когда использовать постоянный 301

Код 301 подходит для окончательной смены URL. Типичные случаи:

  • переезд с old.example.com на new.example.com;
  • замена /old-section/article на /new-section/article;
  • удаление старой страницы с переносом на релевантный материал;
  • переход с HTTP на HTTPS при выборе защищенной схемы как канонической.

Целевой адрес должен быть конечным. Если старый URL сначала ведет на промежуточный адрес, а тот отправляет клиента дальше, формируется цепочка. Для большого количества запросов это добавляет задержку и усложняет обработку поисковыми роботами.

301 может кэшироваться браузерами, прокси и поисковыми системами. Перед постоянным переносом проверьте hostname, путь и схему через curl. Ошибка в таком правиле сохраняется в клиентском кэше дольше, чем временный ответ.

Когда выбрать 302, 307 или 308

302 используйте для временного сценария: тестирования новой страницы, краткого обслуживания или переключения трафика на резервный адрес. Такой код не должен заменять 301 при окончательной миграции сайта.

307 нужен, когда временный переход должен сохранить метод запроса и тело. Это актуально для POST, PUT и других запросов, где повторная отправка как GET меняет смысл операции.

308 решает ту же задачу для постоянного переноса. Например, API может окончательно переехать на другой путь, сохранив POST или PUT. Для обычных страниц с GET чаще применяют 301, для API с обязательным сохранением метода подходят 307 или 308.

Проверьте поддержку 307 и 308 в старых версиях Nginx и промежуточных прокси, если сервер входит в устаревшую инфраструктуру. Код должен одинаково обрабатываться Nginx, балансировщиком и клиентом.

Где размещать return: server-блок или location

Контекст определяет область действия правила. Редирект всего виртуального хоста размещают в server, а точечный переход страницы или каталога ограничивают подходящим location.

Редирект всего хоста на уровне server

В server-блоке Nginx сопоставляет запрос по listen и server_name. Директива return на этом уровне срабатывает для всех URI выбранного hostname.

server {
    listen 80;
    listen [::]:80;
    server_name old.example.com www.old.example.com;

    return 301 https://new.example.com$request_uri;
}

Такой вариант подходит для полного переноса домена. Отдельные location для /, /docs и /api не нужны, потому что правило уже охватывает весь хост.

Перед правкой найдите активный виртуальный хост и подключаемые файлы командой sudo nginx -T. Она выводит объединенную конфигурацию Nginx и помогает увидеть конфликтующие server_name. Структура основных контекстов и готовые примеры собраны в разборе nginx.conf.

При переходе с Apache проверьте, что старые правила не остались в другом прокси или в конфигурации приложения. Сопоставить директивы и порядок миграции поможет руководство по миграции с Apache на Nginx.

Точный location для одной страницы

Точное совпадение ограничивает редирект одним путем:

server {
    listen 80;
    server_name example.com;

    location = /old-page {
        return 301 /new-page$is_args$args;
    }
}

К запросу /old-page-extra это правило не относится. Query string не участвует в выборе location, поэтому /old-page?utm_source=ad все равно попадет в точный блок.

Слеш в конце считается частью пути. Если оба варианта доступны, задайте поведение явно:

location = /old-page {
    return 301 /new-page$is_args$args;
}

location = /old-page/ {
    return 301 /new-page/$is_args$args;
}

Сопоставьте конечные слеши с принятой структурой URL. Иначе один вариант может отдавать 301, а второй останется доступным с кодом 200 или получит отдельный редирект от приложения.

Готовые конфигурации: редирект всего сайта, каталога и страницы в Nginx

Ниже приведены независимые фрагменты. Замените нейтральные значения old.example.com, new.example.com и пути на свои данные, затем проверьте итоговую конфигурацию.

Редирект всего сайта на новый домен

Для HTTP-версии старого домена используйте отдельный server-блок:

server {
    listen 80;
    listen [::]:80;
    server_name old.example.com www.old.example.com;

    return 301 https://new.example.com$request_uri;
}

Запрос http://old.example.com/docs/install?edition=pro получит адрес https://new.example.com/docs/install?edition=pro. Переменная $request_uri переносит путь и query string без отдельного перечисления параметров.

Для обращений по HTTPS старый домен тоже должен иметь рабочий TLS-блок:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name old.example.com www.old.example.com;

    ssl_certificate /etc/nginx/ssl/old.example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/old.example.com/privkey.pem;

    return 301 https://new.example.com$request_uri;
}

TLS-соединение устанавливается до HTTP-редиректа. Поэтому для HTTPS-старого домена нужен действующий сертификат старого hostname. Без него браузер может показать ошибку сертификата и не получить ответ 301.

Редирект HTTP на HTTPS

Если домен сохраняется, но весь трафик должен работать через HTTPS, используйте порт 80 только для перенаправления:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    return 301 https://example.com$request_uri;
}

Hostname example.com указан явно, поэтому запрос с www.example.com одновременно переходит на HTTPS и на выбранный канонический домен. Если каноническим должен быть вариант с www, замените целевой hostname во всех правилах.

HTTPS-блок должен обслуживать содержимое сайта или передавать запрос приложению. Если он безусловно отправляет запрос обратно на HTTP, возникает цикл. При наличии балансировщика проверьте, какой протокол он передает Nginx в X-Forwarded-Proto.

Редирект каталога с сохранением вложенного пути

Пусть раздел /old-section переезжает в /new-section, а вложенные страницы должны сохранить остаток пути:

server {
    listen 80;
    server_name example.com;

    location = /old-section {
        return 301 /new-section$is_args$args;
    }

    location ~ ^/old-section/(.*)$ {
        return 301 /new-section/$1$is_args$args;
    }
}

Здесь $1 содержит захваченную часть после /old-section/. Запрос /old-section/article?lang=ru перейдет на /new-section/article?lang=ru. Запрос без завершающего слеша, /old-section, обработает точный location =.

Regex location в примере чувствителен к регистру. Для путей с разным регистром можно применить location ~*, но сначала проверьте, допускает ли сайт такие дубликаты. Автоматическое смешивание вариантов регистра часто создает дополнительные URL.

Редирект одной страницы

Для точечной замены URL используйте фиксированный путь и сохраните параметры запроса:

server {
    listen 80;
    server_name example.com;

    location = /old-page {
        return 301 /new-page$is_args$args;
    }
}

Запрос /old-page?utm_source=newsletter&page=2 получит /new-page?utm_source=newsletter&page=2. Без параметров результатом будет /new-page, без лишнего знака вопроса.

Точное совпадение снижает риск затронуть адреса вроде /old-page/archive или /old-page-2. Если такие пути тоже нужно переносить, опишите их отдельными правилами и проверьте каждое сопоставление.

Редирект на другой домен в Nginx

Для перехода отдельного URL на внешний проект укажите абсолютный адрес:

server {
    listen 80;
    server_name example.com;

    location = /old-manual {
        return 301 https://external.example.com$request_uri;
    }
}

Запрос /old-manual?source=help перейдет на https://external.example.com/old-manual?source=help. Такой шаблон сохраняет исходный путь.

Если на новом домене используется другой путь, задайте его явно:

location = /old-manual {
    return 301 https://external.example.com/docs/manual$is_args$args;
}

Проверьте три значения: схему http или https, точное имя домена и целевой путь. Целевой сервер должен отвечать без обратного перехода на старый hostname.

Путь, query-параметры и защита от redirect loop

Корректный редирект должен сохранить нужные части запроса и завершиться за один переход. Ошибки обычно связаны с потерей query string, неверным выбором server или тем, что новый адрес снова попадает под старое правило.

Как сохранить query-параметры

$request_uri содержит исходный URI вместе с параметрами запроса. Используйте его, когда путь не меняется:

location / {
    return 301 https://new.example.com$request_uri;
}

При замене части пути применяйте $is_args$args:

location ~ ^/old-section/(.*)$ {
    return 301 /new-section/$1$is_args$args;
}

$args содержит query string без начального знака вопроса. $is_args возвращает ?, если параметры существуют, и пустую строку, если их нет. Поэтому конфигурация корректно обрабатывает оба варианта:

  • /old-section/article превращается в /new-section/article;
  • /old-section/article?tag=nginx&page=2 превращается в /new-section/article?tag=nginx&page=2.

Не добавляйте знак вопроса без проверки наличия параметров. Запись вроде /new-page?$args может формировать лишний разделитель в URL.

Как не создать бесконечный цикл

Цикл появляется, когда запрос после перехода снова соответствует тому же правилу или соседнему правилу, которое отправляет его назад. Диагностируйте его по шагам:

  1. Проверьте каждый заголовок Location командой curl -IL.
  2. Убедитесь, что новый hostname не перечислен в старом redirect server-блоке.
  3. Сравните схему запроса и схему целевого адреса. Правило HTTP на HTTPS должно срабатывать только на порту 80.
  4. Проверьте балансировщик, CDN и reverse proxy перед Nginx. Они могут передавать протокол клиента через X-Forwarded-Proto.
  5. Сверьте DNS старого и нового домена, чтобы запрос действительно попадал на ожидающий его сервер.

HTTP и HTTPS тестируйте отдельно. Если перед Nginx стоит прокси, зафиксируйте, где происходит TLS termination и какой компонент принимает решение о переходе между схемами.

Порядок выбора location

Nginx проверяет location в определенном порядке:

  • location = /old-page имеет точное совпадение и обрабатывается первым;
  • обычный префиксный блок вроде location /old-section/ выбирается по наиболее длинному совпавшему префиксу;
  • regex location вроде location ~ ^/old-section/(.*)$ проверяются после поиска префикса, в порядке появления в конфигурации;
  • префикс с модификатором ^~ не передает запрос регулярным правилам.

location = /old-section не совпадает с /old-section/. Для каталога без слеша нужен отдельный точный блок, а вложенные адреса может обработать regex location. При конфликте правил проверьте полную конфигурацию через nginx -T и фактический ответ через curl.

Подробная диагностика приоритетов location, логов и маршрутизации описана в руководстве по отладке маршрутизации Nginx.

Когда return достаточно, а когда нужен другой механизм

return закрывает предсказуемые сценарии. Его удобно применять там, где целевой адрес можно записать в конфигурации одной строкой или небольшим набором независимых правил.

Признаки простой задачи для return

  • Код ответа заранее известен, например 301 или 302.
  • Целевой URL фиксирован или строится из понятного пути и переменных.
  • Правило относится к одному hostname или нескольким явно заданным location.
  • Условий по заголовкам, cookie, методу и значению параметров нет.
  • Нужно сохранить исходный URI через $request_uri или query string через $is_args$args.

Для пяти или десяти независимых страниц несколько точных location часто читаются лучше, чем универсальное регулярное выражение:

location = /old-a {
    return 301 /new-a$is_args$args;
}

location = /old-b {
    return 301 /new-b$is_args$args;
}

Признаки сложной карты перенаправлений

Отдельный механизм потребуется, если конфигурация должна обслуживать сотни независимых соответствий, разные правила для нескольких параметров или переходы по заголовкам и значениям cookie. Большой набор regex location трудно проверять вручную: одно широкое выражение может перехватить URL, предназначенный для другого правила.

Сначала составьте таблицу старый URL - новый URL. Для каждого адреса зафиксируйте код, hostname, путь, параметры и ожидаемый конечный ответ. Простую таблицу можно хранить через map в контексте http, а сложные преобразования передать серверной логике или приложению.

rewrite оправдан, когда путь нужно преобразовать по регулярному шаблону с условиями. map удобен для выбора результата по hostname, URI или заголовку. В обоих случаях добавьте автоматические проверки для старых адресов, чтобы отслеживать цепочки и циклы.

Для API Gateway и сложной маршрутизации полезен отдельный материал о Nginx как L7-маршрутизаторе. Он помогает определить границу между простым редиректом и полноценной логикой маршрутизации.

Проверка конфигурации и диагностика редиректа

Редактирование файла не меняет поведение Nginx до успешной проверки и reload. Проверяйте результат на уровне HTTP-ответа, а не только в браузере, где могут действовать кэш и сохраненные перенаправления.

Проверка синтаксиса и reload

Выполните проверку синтаксиса:

sudo nginx -t

При успешной проверке примените новую конфигурацию:

sudo systemctl reload nginx

reload перечитывает конфигурацию и позволяет активным соединениям завершить работу без остановки сервиса. Если nginx -t сообщает об ошибке, исправьте указанный файл и повторите проверку. Не переходите к reload с конфигурацией, которую Nginx не принял.

Для отдельного тестового стенда удобно использовать VDS с независимым hostname. Облачные серверы, базы данных и Kubernetes для таких задач предоставляет Timeweb Cloud. Тестовый домен должен иметь DNS-запись и сертификат, если проверяется HTTPS.

Проверка ответа через curl

Проверьте первый ответ без перехода по заголовку:

curl -I 'https://old.example.com/old-page?utm_source=test'

Ожидайте код 301, 302, 307 или 308 и корректный заголовок Location. Для просмотра всей цепочки используйте:

curl -IL 'https://old.example.com/old-page?utm_source=test'

Пример ожидаемого первого ответа:

HTTP/2 301
location: https://new.example.com/old-page?utm_source=test

Проверьте четыре свойства: статус каждого перехода, точный hostname, сохранение пути и query string, количество промежуточных ответов. Один прямой 301 предпочтительнее цепочки 301 - 302 - 200.

Ключ -I запрашивает только заголовки, а -L разрешает переходить по Location. Если приложение по-разному отвечает на HEAD и GET, дополните проверку обычным запросом без -I.

Типовые ошибки и их исправление

  • 404 вместо редиректа. Проверьте, что запрос попал в нужный server_name, путь совпадает с location =, а конфигурация после правки прошла nginx -t и получила reload.
  • 200 вместо 301. В активном блоке нет return, сработал другой location или запрос пришел на другой виртуальный хост. Сравните вывод nginx -T с DNS и заголовком Host.
  • Бесконечный цикл. Проверьте направление Location, список server_name, HTTP/HTTPS-блоки и настройки балансировщика.
  • Потеря параметров. Для сохранения полного запроса используйте $request_uri. При смене пути добавьте $is_args$args.
  • Неверный hostname. Укажите канонический домен явно и убедитесь, что сертификат соответствует старому домену при HTTPS-редиректе.
  • Лишняя цепочка 301 - 302. Направляйте старый URL сразу на конечный HTTPS-адрес и уберите промежуточное правило приложения.
  • После правки ничего не изменилось. Проверьте reload, кэш браузера, CDN и заголовки ответа через curl -I. Запись в другом include-файле может иметь более подходящий server или location.

Для расследования конкретного запроса сопоставьте время запроса с access log и error log. Если запрос не появился в ожидаемом access log, он, вероятно, ушел на другой сервер, балансировщик или виртуальный хост.

SEO-проверка после настройки редиректа домена в Nginx

301 закрывает технический переход, но миграция URL требует обновления самого сайта. Поисковый робот должен видеть согласованную цепочку: старый адрес возвращает 301, новый адрес отвечает 200, а внутренние ссылки ведут сразу на новый URL.

Проверка внутренних ссылок и canonical

После переноса обновите внутренние ссылки в меню, статьях, навигации, хлебных крошках и шаблонах. Укажите новые адреса в canonical и замените ссылки на старые страницы в sitemap.

Проверьте, что новый URL не ссылается на старый адрес, который сначала отдает 301. Такие ссылки создают дополнительные переходы при каждом обходе. Для query-параметров заранее определите, какие из них нужны сайту, а какие служат только для аналитики.

Контроль миграции в поисковых инструментах

Составьте список старых URL и их целевых страниц до изменения конфигурации. После reload проверьте выборочные адреса через curl, затем отслеживайте их в Google Search Console и Яндекс Вебмастере.

  • Проверяйте, что старые страницы отдают ожидаемый постоянный код.
  • Следите за ошибками сканирования и страницами, которые выпали из индекса.
  • Контролируйте появление цепочек и циклов.
  • Сверяйте входящий трафик на новые URL с датой переключения.
  • Обновляйте sitemap после смены домена или структуры разделов.

Зафиксируйте дату переноса, список измененных правил и результаты проверки. Это упростит поиск причины, если на отдельных разделах появятся ошибки после обновления DNS или конфигурации.

Проверка веса и релевантности перенаправлений

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

При возможности меняйте за один этап один тип адреса: домен, схему или структуру пути. Одновременная смена всех компонентов усложняет диагностику. Целевой URL должен отвечать напрямую, использовать правильный canonical и присутствовать в актуальном sitemap.

Практический порядок после настройки такой: проверить старые адреса, убрать цепочки, обновить внутренние ссылки и canonical, отправить новые URL в поисковые инструменты, затем контролировать логи и статистику переходов. При миграции Apache на Nginx сопоставьте эту проверку с картой старых правил, чтобы не потерять отдельные разделы.

Поделиться:
Сохранить гайд? В закладки браузера