По статистике, абсолютное большинство сайтов в интернете размещены на серверах под управлением Юникс-подобных систем, чаще всего - семейства Linux. Это мотивиро...
Блог компании 3v-Hosting
10 мин.
Скорость загрузки любого сайта в интернете зависит в том числе от объёма данных, которые сервер передаёт браузеру. К счастью, основные протоколы передачи данных через интернет, такие как HTML, CSS, JavaScript, JSON и другие текстовые данные хорошо сжимаются. Например файл размером 200 КБ после компрессии может занимать в несколько раз меньше. И конечно, не воспользоваться таким преимуществом было бы глупостью, поэтому все современные веб-серверы используют те или иные механизмы сжатия или компрессии трафика. Но сегодня мы поговорим о том, как этот конкретный механизм организован в одном из популярнейших веб-серверов современности, в Nginx.
В Nginx для компрессии чаще всего используют механизмы gzip и Brotli. Gzip уже встроен в Nginx и поддерживается он практически любым современным браузером. Механизм Brotli обычно сжимает текст чуть эффективнее, но для этого требуется установка отдельного модуля. Оба эти инструмента можно использовать и одновременно, например в таком случае браузер сообщает, какой алгоритм он поддерживает, а сервер выбирает подходящий и продолжает работу с выбранным механизмом.
Давайте в этой статье разберём подробнее, как настроить оба варианта компрессии, сразу проверить результат и не превратить экономию трафика в лишнюю нагрузку на CPU сервера. И начнём с самых основ.
Когда браузер запрашивает страницу, то он сообщает серверу, какие алгоритмы сжатия он сам поддерживает. Для этого существует специальный заголовок Accept-Encoding, в котором передаётся такая информация:
Accept-Encoding: gzip, deflate, br
Nginx выбирает доступный вариант и указывает его в ответе в соответствующем поле:
Content-Encoding: br
Браузер получает сжатые данные и сам их распаковывает. Для конечного приложения при таком механизме ничего не меняется и тот-же WordPress, Django, Laravel или другой backend продолжает отдавать обычный HTML или JSON.

Сжимать данные можно двумя способами, динамическим и статическим. При динамическом сжатии Nginx обрабатывает ответ перед каждой отправкой клиенту и для простого HTML и других изменяемых данных это стандартный вариант. А вот статические CSS и JavaScript файлы можно сжать заранее и хранить сжатые копии в различных форматах рядом с оригиналом, отдавая то, что поддерживает браузер:
app.js app.js.gz app.js.br
В таком случае Nginx отдаёт уже готовый сжатый файл и не тратит ресурсы CPU на повторную компрессию. Такой подход удобен для сайтов и приложений, где статические ресурсы меняются крайне редко, например только при обновлении проекта.
Gzip - это встроенный в Nginx алгоритм сжатия с широкой поддержкой браузерами и другими HTTP-клиентами. Он хорошо подходит для HTML, CSS, JavaScript, JSON, XML и других текстовых данных.
Для большинства серверов gzip можно считать базовым, стандартным вариантом, так как он не требует установки дополнительных модулей и при умеренном уровне сжатия создаёт небольшую нагрузку на процессор.
Brotli - это более новый алгоритм, который обычно сжимает текстовый контент сильнее gzip. Разница особенно заметна на крупных CSS и JavaScript-файлах.
Правда в стандартную сборку Nginx Brotli обычно не входит и для него нужен модуль ngx_brotli, поэтому сначала стоит проверить его наличие, о чем мы поговорим ниже.
Как мы уже упоминали выше, Gzip и Brotli можно включить одновременно. В этом случае, если клиент поддерживает Brotli, то сервер может использовать его, а для остальных остаётся gzip.
| gzip | Brotli | |
|---|---|---|
| Поддержка Nginx | Встроен | Нужен модуль |
| Совместимость | Очень широкая | Широкая в современных браузерах |
| Степень сжатия | Хорошая | Обычно выше |
| Динамическое сжатие | Да | Да |
| Предварительное сжатие | .gz |
.br |
Правда стоит учитывать, что для динамических ответов нет большого смысла гнаться за максимальным уровнем компрессии. У gzip и Brotli разумной отправной точкой обычно будет диапазон 4–6. Более тяжёлое сжатие интереснее для заранее подготовленной статики, где ресурс CPU тратится один раз при создании файла. Выкручивать-же ручку компрессии на максимум для всего будет нецелесообразным, так как уровень экономии трафика будет расти медленнее, чем будет расти нагрузка на CPU.
Ещё раз повторим, что сжатие имеет смысл прежде всего для текстовых форматов. HTML, CSS, JavaScript, JSON, XML, SVG и TXT обычно уменьшаются очень хорошо, в разы.
Что-же касается JPEG, PNG, WebP, AVIF, видео и архивов, то они уже используют собственную компрессию, поэтому повторное сжатие редко заметно уменьшает их размер, зато требует процессорного времени. Это же относится и к PDF, которые тоже обычно нет смысла специально пропускать через gzip или Brotli.
Отсюда следует, что добавлять в инструкции gzip_types и brotli_types все доступные MIME-типы подряд не стоит.
Как вы знаете, Gzip уже входит в Nginx, поэтому обычно достаточно добавить несколько директив в блок http файла /etc/nginx/nginx.conf для его включения. Пример конфигурации может быть таким:
gzip on; gzip_vary on; gzip_comp_level 5; gzip_min_length 1024; gzip_types text/plain text/css text/xml application/javascript application/json application/xml application/rss+xml image/svg+xml;
gzip_comp_level 5 - для production этого уровня сжатия будет вполне достаточно, как мы обсудили выше.
gzip_min_length 1024 - отсекает слишком маленькие ответы, где компрессия почти ничего не даёт.
HTML отдельно добавлять в gzip_types не нужно: Nginx сжимает text/html по умолчанию.
Если статика уже сжата заранее, можно разрешить Nginx отдавать готовые .gz архивы:
gzip_static on;
Это удобно для CSS и JavaScript, которые меняются только при обновлении проекта.
В случае с Brotli сначала нужно убедиться, что необходимый модуль доступен. Для этого выполните команду:
nginx -V 2>&1 | grep -i brotli
Если команда ничего не вернула, значит модуль нужно установить. В Ubuntu и Debian при использовании Nginx из системных репозиториев Brotli доступен отдельными пакетами. Пакет filter отвечает за динамическое сжатие, а пакет static - за выдачу заранее подготовленных .br-файлов.
Установить оба можно так:
sudo apt update sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
После установки проверьте конфигурацию и перезагрузите Nginx:
sudo nginx -t sudo systemctl reload nginx
Если Nginx установлен из стороннего репозитория или собран вручную, то системные пакеты могут оказаться несовместимы с его ABI (Application Binary Interface). В таком случае модуль Brotli придётся устанавливать способом, предусмотренным для конкретной сборки Nginx, либо собирать вместе с ней.
После подключения модуля, его конфигурация похожа на конфигурацию gzip:
brotli on; brotli_comp_level 5; brotli_min_length 1024; brotli_types text/plain text/css text/xml application/javascript application/json application/xml application/rss+xml image/svg+xml;
Для готовых .br используется:
brotli_static on;
Если проект собирается через CI/CD, то .gz и .br удобно создавать прямо на этапе сборки.
После изменения конфигурации сначала проверяем синтаксис:
nginx -t
Если ошибок нет - применим её:
systemctl reload nginx
Теперь проверяем gzip:
curl -I -H "Accept-Encoding: gzip" https://example.com/
В ответе должен появиться заголовок:
Content-Encoding: gzip
Для Brotli:
curl -I -H "Accept-Encoding: br" https://example.com/
Ожидаемый результат:
Content-Encoding: br
Лучше проверить не только HTML, но и CSS или JavaScript, так как если главная страница сжимается, а app.js остаётся без Content-Encoding, то проблема может быть в MIME-типе или списке gzip_types / brotli_types.
Всё то же самое можно проверить и в браузере: DevTools → Network → нужный запрос → Response Headers.
Сам Content-Encoding показывает только факт работы компрессии, но насколько сильно она уменьшила ответ, из него не видно.
Для этого у gzip в Nginx есть специальная переменная:
$gzip_ratio
У ngx_brotli есть её аналог:
$brotli_ratio
Эти переменные можно добавить в access log и смотреть коэффициент сжатия уже на реальном трафике. Это будет правильнее, чем ставить максимальный уровень компрессии вслепую. Лучше проверить степень сжатия при различных установках уровня сжатия и если увеличение comp_level почти не уменьшает размер ответа, то дополнительная нагрузка на CPU смысла не имеет.
Если Content-Encoding в ответе нет, то обычно причина довольно простая. Давайте перечислим основные из них.
При такой настройке:
gzip_min_length 1024; brotli_min_length 1024;
Nginx не будет сжимать ответы меньше 1 КБ. Для проверки лучше брать крупный HTML, CSS или JavaScript-файл.
Если нужного типа нет в gzip_types или brotli_types, ресурс останется несжатым.
Проверить тип ответа можно так:
curl -I https://example.com/app.js
Смотрите заголовок Content-Type и сверяйте его с конфигурацией Nginx.
Директивы brotli on; и brotli_types работают только при наличии модуля.
Проверка:
nginx -V 2>&1 | grep -i brotli
Если вывода нет, текущая сборка Nginx, скорее всего, собрана без Brotli.
После изменений нужно проверить конфиг и перечитать его:
nginx -t systemctl reload nginx
Без reload worker-процессы продолжат работать с прежними настройками.
CDN или внешний reverse proxy может сам сжимать ответы, менять Accept-Encoding или отдавать закешированную версию файла.
Тут имеет смысл проверять именно публичный ответ, который получает браузер, а при необходимости и отдельно обращаться к origin-серверу. Иначе легко искать проблему в Nginx там, где сжатие уже перехватил промежуточный слой.
Сжатие экономит трафик за счёт процессорного времени. Пока нагрузка небольшая, этого почти незаметно, но на сервере с большим количеством динамических запросов разница уже может быть ощутимой.
Особенно спорным является использование максимальных уровней компрессии. Например если Brotli level 5 уменьшает ответ до 42 КБ, а level 11 - до 39 КБ, то несколько килобайт экономии могут стоить непропорционально дорого по CPU.
На небольшом VPS это будет заметнее, ведь процессор одновременно нужен приложению, базе данных, PHP-FPM и самому Nginx. Поэтому для динамического сжатия обычно разумнее оставаться в районе 4-6 и смотреть на реальную нагрузку.
Со статикой дела обстоят гораздо проще. CSS и JavaScript можно заранее подготовить в .gz и .br, а Nginx будет только отдавать готовые файлы.
Есть ещё один редкий, но реальный нюанс. Сжатие HTTPS-ответов может участвовать в атаках класса BREACH, если в одном ответе оказываются секретные данные и содержимое, которое способен контролировать пользователь. Для обычной статики это не проблема, но страницы с токенами и другими чувствительными значениями требуют отдельной оценки.
Brotli обычно сжимает текст немного эффективнее. Но Gzip проще и уже встроен в Nginx. На практике их часто включают и используют одновременно.
Да. Браузер сообщает поддерживаемые алгоритмы через Accept-Encoding, а Nginx выбирает подходящий вариант для ответа.
gzip_comp_level ставить?Для большинства сайтов достаточно 4-6. Значение 5 можно использовать как стартовое.
brotli_comp_level выбрать?Для динамического сжатия тоже разумно начать с 4-6. Высокие уровни больше подходят для заранее подготовленной статики.
Проверьте Content-Type, список gzip_types, значение gzip_min_length и не забудьте перечитать конфигурацию Nginx после изменений.
Обычно нет. JPEG, PNG, WebP и AVIF уже используют собственное сжатие, поэтому дополнительный gzip или Brotli почти ничего не даст.
Можно. Тут важнее не объём RAM, а доступный CPU и текущая нагрузка. Максимальные уровни динамического Brotli на небольшом VPS обычно не нужны.
Настройка gzip и Brotli редко ускоряет медленный сайт сама по себе, ведь если приложение генерирует страницу три секунды, то никакой компрессор эту проблему не исправит.
Но вот на чём компрессия работает великолепно, так это практически на всём текстовом трафике сайта. В итоге HTML становится меньше, CSS становится меньше, JavaScript и JSON становятся меньше, поэтому пользователю приходится загружать меньше данных, а серверу - передавать существенно меньше трафика.
Для большинства конфигураций Nginx разумная схема довольно проста и заключается она в том, чтобы оставить gzip как совместимый базовый вариант, но добавить Brotli для клиентов, которые его поддерживают, а также не увлекаться максимальными уровнями динамического сжатия и по возможности использовать предварительно подготовленные .gz и .br для тяжёлой статики.
Что такое epoll и почему Nginx считается одним из самых быстрых веб-серверов? Разбираем работу epoll, отличия от select и poll, событийную модель и настройку Ng...
Безопасное удаление старых ядер Linux в Ubuntu, Debian, AlmaLinux, Rocky Linux и CentOS. Очистка раздела /boot, работа с APT и DNF, обновление GRUB и защита сер...
Поиск самых больших файлов и каталогов в Linux с помощью du, find и ncdu. Проверка логов, очистка Docker, анализ занятого места на диске и способы предотвратить...