У любой боевой конфигурации Nginx рано или поздно возникает вопрос каноничного адреса сайта: с www или без, и обязательно ли https. Если сделать редиректы неаккуратно, можно получить бесконечные циклы, дубли страниц, битые поддомены и провалы в поисковом трафике.
Ниже разберём практическую схему настройки редиректов в Nginx: с http на https и с www на домен без www (или наоборот). Я покажу несколько типовых шаблонов конфигов и поясню, как избежать ловушек.
Базовые принципы: что именно мы перенаправляем
С точки зрения Nginx, у нас есть три независимых измерения:
- протокол: http → https;
- хост: www.example.ru ↔ example.ru;
- порт: 80 и 443 (иногда кастомный).
При этом SEO и пользователи обычно ожидают, что у сайта будет один «канонический» адрес, например:
- https://example.ru — без www;
- или https://www.example.ru — с www.
Задача — сделать так, чтобы все остальные варианты (http, другой хост) делали 301-редирект на канонический.
Важно: не миксовать в одном и том же серверном блоке и обработку запросов, и перенаправления. Лучше разделить: одни server-блоки только редиректят, один — обслуживает контент.
Типовая цель: https без www
Рассмотрим самую популярную схему: весь трафик должен приходить на https://example.ru, без www. То есть:
- http://example.ru → https://example.ru;
- http://www.example.ru → https://example.ru;
- https://www.example.ru → https://example.ru;
- https://example.ru — целевой сервер, без редиректа.
Логика по шагам:
- создать server для http (порт 80), который всё редиректит на https;
- создать server для https + www, который редиректит на https без www;
- создать server для https без www, который реально обслуживает сайт.
Редирект с http на https (любой хост)
Минимальный, но аккуратный вариант для порта 80:
server {
listen 80;
listen [::]:80;
server_name example.ru www.example.ru;
return 301 https://example.ru$request_uri;
}
Такой блок:
- ловит все http-запросы на оба хоста;
- сохраняет путь и параметры запроса (через
$request_uri); - жёстко отправляет на https и сразу на домен без www.
Если вы хотите, чтобы редирект сохранял именно тот хост, на который обратились (редирект только по протоколу), можно сделать так:
server {
listen 80;
listen [::]:80;
server_name example.ru www.example.ru;
return 301 https://$host$request_uri;
}
Но в нашем сценарии цель — домен без www, поэтому точечно задаём https://example.ru.
Редирект https с www на https без www
Дальше объявляем отдельный сервер для https://www.example.ru, который вообще не обслуживает контент, а только перенаправляет:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.ru;
ssl_certificate /etc/nginx/ssl/example.ru.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.ru.key.pem;
return 301 https://example.ru$request_uri;
}
Ключевой момент — для редиректа по https тоже нужен валидный сертификат на www (или SAN/wildcard), иначе браузер покажет ошибку до того, как выполнит перенаправление. Если сертификата на www ещё нет, имеет смысл сначала выпустить его. Для продакшн-проектов удобнее сразу брать нормальные коммерческие SSL-сертификаты, чтобы не ловить неожиданные проблемы с доверием и продлением.
Боевой сервер: https без www
И, наконец, основной блок, который отвечает за сайт:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.ru;
ssl_certificate /etc/nginx/ssl/example.ru.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.ru.key.pem;
root /var/www/example.ru/current/public;
index index.php index.html;
# Дальше обычный конфиг
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
В этом сервере уже не должно быть никаких return 301 для канонического хоста — чтобы избежать лишних запросов и циклов.
Альтернативная цель: https с www
Иногда нужно наоборот — канонический домен с www: https://www.example.ru. В этом случае зеркально меняем схему.
Схема перенаправлений:
- http://example.ru → https://www.example.ru;
- http://www.example.ru → https://www.example.ru;
- https://example.ru → https://www.example.ru;
- https://www.example.ru — конечная точка.
http → https c добавлением www
server {
listen 80;
listen [::]:80;
server_name example.ru www.example.ru;
return 301 https://www.example.ru$request_uri;
}
https без www → https с www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.ru;
ssl_certificate /etc/nginx/ssl/example.ru.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.ru.key.pem;
return 301 https://www.example.ru$request_uri;
}
Боевой сервер для https с www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.ru;
ssl_certificate /etc/nginx/ssl/example.ru.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.ru.key.pem;
root /var/www/example.ru/current/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Если вы только планируете перенос сайта или смену домена, удобнее сначала развернуть тестовую конфигурацию на отдельном VDS-сервере, отладить там все редиректы, а уже потом перенести настройки в продакшн.

Типовые ошибки с редиректами в Nginx
При настройке редиректов с www и https чаще всего встречаются одни и те же проблемы.
Ошибка 1: циклический редирект
Классика — когда один серверный блок редиректит на другой, а второй редиректит обратно. Например:
server {
listen 80;
server_name example.ru;
return 301 https://example.ru$request_uri;
}
server {
listen 443 ssl;
server_name example.ru;
ssl_certificate ...;
ssl_certificate_key ...;
if ($scheme = https) {
return 301 https://example.ru$request_uri;
}
}
Во втором сервере условие по $scheme всегда истинно (мы уже на https), и браузер зацикливается: Nginx отправляет 301 на тот же самый URL.
Правильнее вообще не использовать if по схеме внутри боевого https-сервера. Перенаправление по протоколу должно происходить только в http-сервере на 80 порту.
Ошибка 2: смешивание логики в одном server
Иногда пытаются в один server запихнуть и редиректы, и отдачу статики, и работу PHP. Например:
server {
listen 443 ssl;
server_name example.ru www.example.ru;
ssl_certificate ...;
ssl_certificate_key ...;
if ($host = www.example.ru) {
return 301 https://example.ru$request_uri;
}
root /var/www/example.ru/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Формально это будет работать, но:
- при изменении логики легко запутаться и получить конфликт;
- условия
ifвserverв Nginx — часто источник сюрпризов; - конфиг хуже читается и сложнее отлаживать.
Проще сделать чистый редиректный блок на www и чистый обслуживающий блок на основной домен, как в примерах выше.
Ошибка 3: неверный порядок server_name и default_server
Когда у вас несколько сайтов на одном IP, важно правильно комбинировать server_name и флаг default_server. Распространённый баг: запросы на несуществующий поддомен попадают в «чужой» серверный блок и получают неожиданный редирект.
Простой приём:
- для нормальных сайтов указывать только нужные домены в
server_name; - создать явный «мусорный» server по умолчанию без редиректов (или с простым 444/404);
- не ставить
default_serverтам, где вы делаете сложную логику.
Если хочется глубже разобраться, как Nginx выбирает виртуальный хост и как это соотносится с Apache, посмотрите материал про сравнение веб-серверов: Nginx против Apache в 2025 году.
Сохранение пути и параметров запроса
При переходе с http на https или с www на без www крайне важно сохранять:
- путь (URI);
- строку запроса (
?param=value).
Чтобы не потерять их, в return почти всегда нужно использовать $request_uri, а не только $uri:
return 301 https://example.ru$request_uri;
$request_uri содержит и путь, и query string. Если использовать голый $uri, то фильтры каталога, параметры UTM и прочие GET-параметры пропадут, что может сильно испортить аналитику и работу части страниц.
Редиректы и SEO: как не потерять позиции
Поисковые системы в целом нормально относятся к редиректам с www и/или на https, если правильно соблюсти несколько условий.
Используем 301, а не 302
Постоянное перенаправление для смены канонического домена и протокола — это код 301:
return 301 https://example.ru$request_uri;
Временный код 302 подойдёт только для краткосрочных акций или тестов, а не для постоянной схемы http → https и www → non-www.
Каноничный домен в ссылках и sitemap
После настройки редиректов стоит проверить:
- генерирует ли ваш CMS/фреймворк ссылки сразу на каноничный домен и https;
- обновлён ли
sitemap.xmlи указаны ли там новые адреса; - правильно ли настроены
<link rel="canonical">в HTML-страницах.
Так поисковые боты быстрее переиндексируют сайт и не будут считать www- и non-www-варианты разными сайтами.
Проверка редиректов curl и браузером
После изменения конфигов Nginx обязательно проверяйте, что цепочка перенаправлений именно такая, как вы задумали.
Проверка curl
Примеры полезных команд:
# Показать только заголовки и коды ответа
curl -I http://example.ru/
# Показать цепочку редиректов до конца
curl -I -L http://example.ru/
# Проверить вариант с www
curl -I http://www.example.ru/
# Проверить https с www
curl -I https://www.example.ru/
Обратите внимание на коды:
- первый ответ должен быть 301 (или 308);
- конечная страница — 200 без дальнейших редиректов.
Проверка в браузере и DevTools
В браузере удобно открыть инструменты разработчика и вкладку Network, включить «Preserve log» и пройти по нескольким вариантам адресов:
- http://example.ru;
- http://www.example.ru;
- https://example.ru;
- https://www.example.ru.
Проследите, чтобы:
- редиректов было не более одного-двух подряд;
- не было прыжков туда-сюда между www и не-www;
- везде конечный адрес совпадает с задуманным каноническим.

Поддомены и редиректы: не ломаем admin.example.ru
Отдельный частый кейс — когда вместе с основным доменом есть поддомены: admin.example.ru, api.example.ru, static.example.ru и т.п.
Ошибка здесь — написать слишком «широкий» server на 80 порту, который захватывает и поддомены:
server {
listen 80 default_server;
server_name _;
return 301 https://example.ru$request_uri;
}
В результате любой запрос к admin.example.ru получит 301 на https://example.ru, что ломает админку или API.
Лучший подход:
- для основного домена задавать чёткий
server_name example.ru www.example.ru; - каждый важный поддомен обслуживать отдельным
server(при необходимости — со своими редиректами и/или https); - если нужен «ловец мусора» для произвольных хостов, делать его отдельным сервером, который, например, отвечает 444 или показывает простую 404 без сложной логики редиректов.
Несколько доменов на один сайт: аккуратные схемы
Бывает, что на один и тот же контент ведут несколько доменов: региональные варианты, старые имена, альтернативные зоны (.ru, .com и т.п.).
Чтобы не плодить дубли в поиске, обычно выбирают один главный домен и все остальные перенаправляют на него по схеме 301, сохраняя путь и параметры:
server {
listen 80;
server_name old-example.ru www.old-example.ru;
return 301 https://example.ru$request_uri;
}
server {
listen 443 ssl http2;
server_name old-example.ru www.old-example.ru;
ssl_certificate /etc/nginx/ssl/old-example.ru.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/old-example.ru.key.pem;
return 301 https://example.ru$request_uri;
}
Главный домен при этом настроен так же, как в базовой схеме выше.
Порядок include и структура конфигов
Чем больше сайтов и редиректов на одном Nginx, тем сильнее нужна аккуратная структура конфигов. Несколько практических советов:
- для каждого домена заведите отдельный файл в
sites-available/sites-enabled(или аналогичной структуре); - внутри файла придерживайтесь порядка: сначала http → https, потом https-редирект www/без www, потом боевой сервер;
- вынесите повторяющиеся фрагменты (например, SSL-настройки) в отдельный
include, чтобы не дублировать; - после любых правок запускайте
nginx -t, затемsystemctl reload nginx(или ваш способ перезагрузки).
Параллельно можно подумать об оптимизации обработки запросов, кешировании и HTTP/2 — у нас есть отдельный разбор приёмов работы с протоколом: HTTP/2, push, preload и приоритизация ресурсов.
Итоги
Грамотно настроенные редиректы в Nginx для www и https — это:
- один чётко определённый канонический домен (с www или без);
- обязательный переход на https с кодом 301;
- минимум дополнительных прыжков — максимум один редирект до целевого URL;
- отдельные server-блоки для редиректов и для обработки контента;
- сохранение пути и query string через
$request_uri; - корректно настроенный SSL для всех хостов, которые принимают https-запросы.
Если держать в голове эти принципы, схема www/https в Nginx будет прозрачной, предсказуемой и безопасной для SEO — без циклов, дублей и неожиданных побочных эффектов.


