Мобильный трафик в Nginx: сравниваем варианты настройки
Nginx может отправлять мобильных пользователей на отдельный origin, добавлять заголовки для кеша или вообще не различать устройства. Сравниваем четыре подхода и показываем, где ломаются редиректы, кеширование и определение по User-Agent.

Мобильный трафик в Nginx можно обслуживать четырьмя разными способами: оставить один адаптивный сайт, определять устройство по User-Agent, вынести мобильную версию на отдельный адрес или разделить только тяжёлые ресурсы. Очевидное решение — редиректить всех с маленьким экраном на m.example.com — часто создаёт петли, дубли страниц и неправильные ответы из кеша. Ниже — сравнение для Nginx Open Source 1.25.x и критерии, по которым выбирают подход.
Сначала определите, что именно нужно мобильному трафику
Nginx не превращает десктопный HTML в мобильный интерфейс. Он может выбрать upstream, отдать редирект, добавить заголовки и кешировать ответ. Разметку, изображения и поведение интерфейса обычно меняют приложение, CSS и браузер.
Перед настройкой ответьте на три вопроса:
- Нужен тот же контент в другом расположении или отдельная мобильная версия страниц.
- Можно ли менять приложение и шаблоны, или доступен только reverse proxy.
- Что должно измениться: HTML, изображения, API-ответы, кеш или только маршрут до backend.
Если отличается только ширина экрана, обычно достаточно адаптивной вёрстки и отзывчивых изображений. Если мобильному клиенту нужен другой HTML или отдельный backend, тогда появляется смысл в маршрутизации на уровне Nginx.
Разделять трафик по устройствам стоит не потому, что запрос пришёл со смартфона, а потому, что сервер действительно должен ответить ему иначе.
Четыре подхода и их цена
| Подход | Что меняется | Плюсы | Цена и риск |
|---|---|---|---|
| Адаптивный сайт | Один HTML, CSS и набор ресурсов | Нет дублей URL и логики определения устройства | Нужно переделать шаблоны и проверить изображения |
| Разделение по User-Agent | Upstream, редирект или заголовок запроса | Можно внедрить без полного переписывания приложения | Неполное определение устройств, ошибки кеша и ботов |
| Отдельный мобильный адрес | Например, m.example.com | Полностью другой HTML и backend | Дублирование страниц, ссылки, SEO и синхронизация релизов |
| Облегчение ресурсов | Изображения, кеш, сжатие и API | Меньше байт без двух версий сайта | Нужны контроль размеров, метрики и корректный cache key |
Вариант 1. Один адаптивный сайт
Это базовый вариант: Nginx не различает телефоны и компьютеры, а приложение отдаёт один канонический URL. В HTML используются CSS media queries, элементы picture или адаптивные размеры изображений. Такой подход не требует map, отдельных upstream и особых правил для кеша.
Он подходит, если бизнес-логика и содержание страниц одинаковы, а различается только представление. Не пытайтесь компенсировать слишком тяжёлую страницу редиректом: сначала проверьте размер изображений, количество запросов и время ответа backend.
Вариант 2. Определение устройства через User-Agent
В Nginx для этого используется директива map. Она вычисляет переменную до обработки запроса. Ниже пример для Nginx 1.25.x: мобильному User-Agent выбирается отдельный upstream, но URL остаётся тем же.
http {
map $http_user_agent $mobile_upstream {
default http://web_backend;
~*"Android|iPhone|iPad|Mobile" http://mobile_backend;
}
upstream web_backend {
server 127.0.0.1:8080;
}
upstream mobile_backend {
server 127.0.0.1:8081;
}
server {
listen 80;
server_name example.com;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Device-Class mobile-or-desktop;
proxy_pass $mobile_upstream;
}
}
}
Плюс схемы — простая маршрутизация без изменения адресов. Минус — строка User-Agent не является надёжным описанием возможностей устройства. Планшет, встроенный браузер, поисковый робот или новый формат строки могут попасть не в ту группу.
В рабочей конфигурации не используйте слишком короткое правило вроде ~*mobile без проверки реального трафика. Сначала соберите примеры User-Agent из access log, затем протестируйте спорные варианты через staging.
Вариант 3. Отдельный мобильный домен
Редирект на m.example.com оправдан, когда мобильная версия действительно отдельный продукт: другой шаблонизатор, другой набор данных или отдельный backend. Само определение устройства можно оставить на основном домене.
http {
map $http_user_agent $redirect_to_mobile {
default 0;
~*"Android|iPhone|iPad|Mobile" 1;
}
server {
listen 80;
server_name example.com;
location / {
if ($redirect_to_mobile = 1) {
return 302 https://m.example.com$request_uri;
}
proxy_set_header Host $host;
proxy_pass http://web_backend;
}
}
server {
listen 80;
server_name m.example.com;
location / {
proxy_set_header Host $host;
proxy_pass http://mobile_backend;
}
}
}
Здесь применён временный ответ 302. Постоянный 301 не ставьте на первом этапе: после кеширования браузером откатить ошибочное правило сложнее. Проверьте, что мобильный домен не редиректит обратно на основной по той же логике. Для страниц, доступных по двум адресам, приложение должно определить канонический URL и правила связи версий.
Вариант 4. Разделять только тяжёлые ресурсы
Часто полный мобильный backend не нужен. Можно оставить общий HTML, а размер изображений, формат и кеширование настроить на уровне приложения или CDN. Nginx при этом отвечает за проксирование и заголовки, но не должен угадывать, какой размер картинки нужен экрану.
Если один URL может вернуть разные ответы в зависимости от User-Agent, кеш обязан учитывать этот фактор. Иначе первый сохранённый ответ уйдёт следующему клиенту, даже если ему нужна другая версия.
http {
map $http_user_agent $device_cache_suffix {
default desktop;
~*"Android|iPhone|iPad|Mobile" mobile;
}
proxy_cache_path /var/cache/nginx/mobile
keys_zone=device_cache:10m
inactive=10m;
server {
listen 80;
server_name example.com;
location / {
proxy_cache device_cache;
proxy_cache_key "$scheme$request_method$host$request_uri:$device_cache_suffix";
proxy_set_header Host $host;
proxy_pass http://web_backend;
}
}
}
Такой ключ кеша разделяет варианты, но удваивает количество объектов и может снизить эффективность кеша. Если приложение само отдаёт одинаковый HTML, не добавляйте разделение только ради метки устройства.
Когда какой вариант выбирать
- Выбирайте адаптивный сайт, если мобильным пользователям нужен тот же контент, а различается только layout и размер ресурсов.
- Выбирайте User-Agent без редиректа, если нужно временно направить запросы на отдельный backend, но вы готовы тестировать список устройств и кеш.
- Выбирайте отдельный домен, только если мобильный интерфейс имеет собственную архитектуру и команду сопровождения.
- Выбирайте разделение ресурсов, если основной расход — изображения, шрифты или ответы API, а HTML можно оставить единым.
Практический критерий простой: если для мобильного и десктопного клиента нужно поддерживать разные бизнес-сценарии, разделяйте backend. Если меняется только способ отображения, переносите различия в HTML, CSS и ресурсы.
Что ломается чаще всего
Кеш возвращает десктопную страницу телефону
Проблема появляется, когда ответы отличаются по User-Agent, а proxy_cache_key остаётся одинаковым. Исправление — не просто добавить заголовок Vary, а проверить, учитывает ли конкретный слой кеширования этот заголовок. Для Nginx безопаснее явно разделить ключ, как в примере выше, либо не варьировать HTML на этом уровне.
Редирект зацикливается
Обычно основной домен отправляет мобильный User-Agent на m.example.com, а сервер мобильного домена применяет то же правило и отправляет запрос назад. Для каждого домена задайте собственную логику и протестируйте цепочку командой curl с несколькими User-Agent.
Боты получают мобильную версию
Поисковые роботы и социальные превью могут использовать нестандартные User-Agent. Нельзя считать, что отсутствие слова Mobile означает десктопный браузер. Логируйте результат классификации, а критичные страницы проверяйте отдельными запросами от имени робота и обычного браузера.
Новый браузер не попал в правило
Список регулярных выражений устаревает. Не добавляйте бесконечный перечень моделей телефонов: группируйте по устойчивым признакам, проверяйте реальные строки и держите правило коротким. При неизвестном значении безопаснее отправить общий адаптивный ответ, если он у вас есть.
Изменение конфигурации не применилось
Перед перезагрузкой проверьте синтаксис командой nginx -t. Затем используйте мягкую перезагрузку, принятую в вашей системе, и убедитесь по access log, что новый процесс обслуживает запросы. Команда и путь к бинарному файлу могут отличаться в пакетах Debian, Ubuntu, RHEL и контейнерных образах.
Как проверить решение до продакшена
- Составьте таблицу сценариев: обычный браузер, iPhone, Android, планшет, бот, встроенный браузер приложения и неизвестный User-Agent.
- Для каждого сценария проверьте статус, конечный URL, заголовки кеша, размер ответа и выбранный upstream.
- Повторите запрос дважды. Второй ответ не должен содержать чужую версию страницы или неожиданный статус
HIT. - Проверьте редиректы с query string и путями вроде
/cart,/loginи/checkout. В этих местах ошибка классификации дороже, чем на обычной статье. - После запуска смотрите долю ответов 3xx, 4xx и 5xx отдельно по классу устройства, а также промахи кеша и размер HTML.
Классификация устройства — это правило, по которому запрос относят к группе вроде mobile или desktop. В Nginx она обычно строится на заголовке User-Agent, но этот заголовок сообщает о клиенте со слов самого клиента и не гарантирует фактический размер экрана.
Что настроить следующим шагом
Начните с базовой версии без разделения HTML: включите адаптивные изображения, измерьте размер ответа и зафиксируйте долю мобильного трафика. Если после этого остаётся конкретная проблема — например, мобильному приложению нужен другой API или backend — добавьте маршрутизацию через map на staging. Перед переносом в продакшен проверьте cache key, цепочки редиректов и неизвестные User-Agent, а затем сравните показатели по устройствам на одинаковом окне времени.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: Официальная документация Nginx: модуль map, Официальная документация Nginx: проксирование HTTP
Частые вопросы
Нужно ли вообще определять мобильные устройства в Nginx?
Можно ли считать User-Agent надёжным способом узнать размер экрана?
Почему после настройки телефон иногда получает десктопную страницу?
Что делать, если редирект на мобильный домен зациклился?
Что произойдёт, если новый браузер не попадёт в регулярное выражение?
Будет ли эта конфигурация работать в другой версии Nginx?
Есть ли подводные камни в продакшене?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.