Скорость отдачи веб-страниц и статических ассетов — один из ключевых факторов ранжирования сайтов в поисковых системах и прямого комфорта пользователей. Исторически стандартным инструментом сжатия текстовых данных в вебе являлся алгоритм Gzip (Deflate), созданный еще в 1990-х годах. Однако в современных веб-приложениях с многомегабайтными бандлами JavaScript, тяжелыми CSS-фреймворками и объемными JSON API алгоритм Brotli от Google выигрывает у Gzip от 15% до 25% в размере передаваемых данных без дополнительной нагрузки на процессор (глобальная поддержка в современных браузерах превышает 97% по данным Can I Use).
В этом практическом руководстве мы подробно разберем, как установить и настроить динамический модуль ngx_brotli для Nginx на сервере под управлением Ubuntu 24.04 LTS (Noble Numbat), настроить параллельную работу Brotli и Gzip для безопасного fallback устаревшим клиентам, оптимизировать уровни сжатия под мощности VDS и организовать раздачу предварительно сжатой статики с нулевой нагрузкой на CPU.
📌 Коротко о ключевых выгодах
- Экономия входящего трафика: среднее уменьшение размера JS/CSS-файлов на 18–22% по сравнению с Gzip уровня 6.
- Ускорение Core Web Vitals: снижение показателя Largest Contentful Paint (LCP) и ускорение синтаксического анализа кода браузером.
- Статическое сжатие: возможность сжать ассеты максимальным уровнем (11) при сборке проекта и отдавать их с диска без расхода тактов процессора.
1. Зачем нужен Brotli в 2026 году: сравнение с Gzip и устройство алгоритма
Алгоритм Brotli был представлен инженерами Google в 2015 году специально для оптимизации передачи веб-контента. В его основе лежит модернизированная вариация алгоритма LZ77, энтропийное кодирование Хаффмана и контекстное моделирование 2-го порядка. Однако главное революционное отличие Brotli от Gzip заключается во встроенном статическом словаре размером 120 КБ (ровно 122 784 байта, 13 504 записи согласно спецификации RFC 7932).
В этот статический словарь зашиты более 13 000 общеупотребительных слов, HTML-тегов, атрибутов, CSS-свойств, конструкций синтаксиса JavaScript и фрагментов популярных библиотек:
- Стандартные теги и конструкции:
<html>,<div class=",<script src=",<meta name="; - Свойства стилей:
position: absolute;,display: inline-block;,margin: 0 auto;; - Заголовки и системные слова:
Content-Type: application/json,authorization: Bearer,addEventListener.
Когда веб-сервер упаковывает файл через Gzip, алгоритм вынужден строить таблицу совпадений с нуля исключительно на основе передаваемого файла. Brotli же сразу заменяет типовые последовательности веб-кода крошечными ссылками на встроенный словарь. В результате даже небольшие HTML-страницы и компактные скрипты сжимаются значительно плотнее.
| Параметр | Gzip (Deflate) | Brotli (динамический, уровень 5) | Brotli (статический, уровень 11) |
|---|---|---|---|
| Степень сжатия JS/CSS | Базовая (эталон 100%) | На 15–20% плотнее Gzip | На 25–30% плотнее Gzip |
| Нагрузка на CPU хоста | Низкая | Сравнима с Gzip-6 | Нулевая (отдача через sendfile) |
| Словарь данных | Фиксированное окно 32 КБ (Deflate) | Динамическое окно скольжения (до 16 МБ, директива brotli_window) + статический словарь 120 КБ (13 504 записи) |
Динамическое окно скольжения (до 16 МБ) + статический словарь 120 КБ (13 504 записи) |
| Поддержка браузерами | 100% клиентов | > 97% клиентов (по HTTPS) | > 97% клиентов (по HTTPS) |
| Протоколы передачи | HTTP и HTTPS | Только HTTPS (защита от атак) | Только HTTPS (защита от атак) |
⚠️ Важное требование безопасности: только HTTPS
Согласно спецификации RFC 7932 и политикам безопасности всех современных браузеров (Google Chrome начиная с версии 50, Mozilla Firefox с 44, Apple Safari с iOS 11/macOS High Sierra), заголовок Accept-Encoding: br передается исключительно при защищенном соединении по протоколу HTTPS (защита от атак BREACH/CRIME). Если сайт открыт по HTTP, браузер запросит только gzip. Проверить корректность SSL-сертификата и настройки TLS вашего сервера можно в SSL-чекере онлайн.
2. Способы установки ngx_brotli в Ubuntu 24.04: готовый репозиторий против компиляции
В стандартную поставку пакета nginx из базовых репозиториев Ubuntu 24.04 LTS модуль Brotli не входит по умолчанию из-за строгой политики лицензирования и версионирования дистрибутива. При попытке прописать директиву brotli on; в немодифицированном Nginx сервер завершится с ошибкой unknown directive "brotli".
Для интеграции модуля ngx_brotli существуют два проверенных производственных пути:
-
Способ №1: Установка через проверенный PPA Ondřej Surý. Подходит для 90% стандартных серверов, где используется дистрибутивный стек Nginx + PHP. Репозиторий поддерживается признанным Debian/Ubuntu-мейнтейнером Ондржеем Сури (автором официальных пакетов PHP и Nginx для Debian), содержит актуальные бинарные пакеты
libnginx-mod-http-brotli-filterиlibnginx-mod-http-brotli-staticи автоматически обновляется штатными командамиapt upgrade. -
Способ №2: Сборка динамического модуля
--with-compat. Рекомендуется, если на сервере установлен официальный Nginx из репозиторияnginx.org(ветка Stable или Mainline) либо если политика безопасности компании запрещает добавление сторонних PPA-репозиториев. Мы компилируем только файл.soбез переустановки самого веб-сервера.
3. Способ №1: быстрая установка через доверенный репозиторий PPA Ondřej Surý
Если вы хотите получить полнофункциональный модуль за 2 минуты без установки компиляторов и заголовочных файлов ядра, этот метод является оптимальным решением.
Подключитесь к вашему VDS по SSH с правами sudo и добавьте официальный PPA:
# 1. Установка вспомогательной утилиты для управления PPA
sudo apt update
sudo apt install -y software-properties-common
# 2. Добавление официального репозитория Nginx от Ondřej Surý
sudo add-apt-repository -y ppa:ondrej/nginx
# 3. Обновление списков пакетов
sudo apt update
Теперь установите готовый пакет модуля сжатия:
# Установка модулей Brotli для Nginx (актуальные пакеты PPA Ondřej Surý)
sudo apt install -y libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
Примечание: В старых сборках дистрибутива существовал единый метапакет libnginx-mod-brotli, однако в современных репозиториях PPA модуль разделен на два отдельных пакета — фильтр сжатия на лету и модуль отдачи статики. Установка обоих гарантирует полную функциональность.
Пакетный менеджер автоматически скопирует скомпилированные динамические библиотеки ngx_http_brotli_filter_module.so и ngx_http_brotli_static_module.so в системный каталог /usr/lib/nginx/modules/ и создаст конфигурационный симлинк в каталоге /etc/nginx/modules-enabled/.
Убедитесь, что модуль подключен к веб-серверу:
ls -l /etc/nginx/modules-enabled/*brotli*
Вывод должен подтвердить наличие символической ссылки на файл 50-mod-brotli.conf, в котором объявлены директивы load_module.
4. Способ №2: сборка динамического модуля для официального Nginx (--with-compat)
Если вы используете официальные сборки веб-сервера из репозиториев nginx.org (ветки Mainline или Stable) либо хотите избежать подключения сторонних PPA, самым чистым решением является независимая сборка динамического модуля с флагом двоичной совместимости --with-compat.
Принцип работы прост: мы скачиваем исходный код в точности той же версии Nginx, которая уже работает на сервере, компилируем только разделяемые библиотеки .so модуля ngx_brotli и подключаем их в основной файл конфигурации.
💡 Шаг 1: Определение точной версии установленного Nginx
Перед началом сборки проверьте текущую версию веб-сервера командой nginx -v. Модуль должен компилироваться строго против исходных кодов вашей версии, иначе при старте Nginx откажется загружать библиотеку из-за несоответствия бинарного API.
# Проверка текущей версии веб-сервера
nginx -v
# Пример вывода: nginx version: nginx/1.26.1
Установите необходимые пакеты для сборки и библиотеки сжатия:
# Установка компилятора, git и заголовочных файлов библиотек
sudo apt update
sudo apt install -y build-essential git libpcre3-dev zlib1g-dev libssl-dev libbrotli-dev wget
Создайте временный рабочий каталог, скачайте исходники Nginx и репозиторий ngx_brotli:
# Переход во временный каталог
mkdir -p /tmp/nginx-build && cd /tmp/nginx-build
# Клонирование репозитория модуля Brotli со всеми подмодулями
git clone --recurse-submodules -j4 https://github.com/google/ngx_brotli.git
# Получение номера установленной версии Nginx
NGINX_VER=$(nginx -v 2>&1 | awk -F'/' '{print $2}')
# Загрузка и распаковка исходного кода идентичной версии Nginx
wget https://nginx.org/download/nginx-${NGINX_VER}.tar.gz
tar -zxvf nginx-${NGINX_VER}.tar.gz
cd nginx-${NGINX_VER}
Теперь запустите конфигуратор сборщика с флагом --with-compat и скомпилируйте исключительно динамические модули:
# Конфигурация Nginx с флагом совместимости для сборки динамического модуля
./configure --with-compat --add-dynamic-module=/tmp/nginx-build/ngx_brotli
# Сборка модулей (бинарники веб-сервера перезаписываться не будут)
make modules
После завершения компиляции в каталоге objs/ появятся два файла библиотек. Скопируйте их в системный каталог модулей Nginx:
# Создание каталога модулей при его отсутствии
sudo mkdir -p /etc/nginx/modules
# Копирование скомпилированных модулей
sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules/
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules/
# Очистка временных файлов сборки
cd /tmp && rm -rf /tmp/nginx-build
Подключите модули в самом начале конфигурационного файла /etc/nginx/nginx.conf (до блока events и http):
# /etc/nginx/nginx.conf (в самом верху файла)
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
user www-data;
worker_processes auto;
pid /run/nginx.pid;
...
5. Эталонная конфигурация Nginx: параллельная работа Brotli и Gzip
Для максимальной совместимости и эффективности продакшена правильной архитектурой является двухуровневый стек сжатия. Если входящий HTTP-запрос от современного браузера содержит поддержку алгоритма br, веб-сервер упаковывает ответ алгоритмом Brotli. Если запрос отправлен поисковым роботом без поддержки Brotli или устаревшим клиентом — Nginx автоматически откатывается на стандартный Gzip.
Создайте конфигурационный файл /etc/nginx/conf.d/brotli.conf:
# /etc/nginx/conf.d/brotli.conf
# Активация динамического сжатия Brotli на лету
brotli on;
# Раздача предварительно сжатых файлов с расширением .br без расхода CPU
brotli_static on;
# Оптимальный уровень сжатия на лету (баланс между плотностью и нагрузкой на VDS)
brotli_comp_level 5;
# Минимальный размер ответа для включения сжатия (файлы меньше 256 байт сжимать невыгодно)
brotli_min_length 256;
# MIME-типы файлов, подлежащих компрессии
brotli_types
text/plain
text/css
text/javascript
text/xml
application/javascript
application/x-javascript
application/json
application/xml
application/xml+rss
application/manifest+json
image/svg+xml;
Параллельно убедитесь, что в файле /etc/nginx/conf.d/gzip.conf (или внутри блока http) настроен fallback-стек для Gzip:
# /etc/nginx/conf.d/gzip.conf
# Включение сжатия Gzip для клиентов без поддержки Brotli
gzip on;
gzip_static on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_buffers 16 8k;
gzip_proxied any;
# Обязательный заголовок Vary: Accept-Encoding для промежуточных CDN и кэширующих прокси
gzip_vary on;
gzip_types
text/plain
text/css
text/javascript
text/xml
application/javascript
application/x-javascript
application/json
application/xml
application/xml+rss
application/manifest+json
image/svg+xml;
💡 Подводные камни директив: brotli_buffers и отсутствие brotli_vary
Обратите внимание на две критические особенности директив при настройке веб-сервера:
- Почему не нужна директива brotli_buffers: В актуальном исходном коде модуля
google/ngx_brotliдирективаbrotli_buffersофициально помечена как устаревшая (в структуре C-кода сохранена какdeprecated_unused_bufsисключительно ради обратной совместимости, но не влияет на работу). Модуль управляет памятью динамически через библиотеку brotlienc, поэтому указывать буферы вручную не требуется. - Ошибка unknown directive "brotli_vary": Некоторые администраторы по аналогии с Gzip пытаются прописать
brotli_vary on;, после чего Nginx падает при старте с ошибкойnginx: [emerg] unknown directive "brotli_vary". В официальном модуле Google такой директивы не существует! Корректная отправка заголовкаVary: Accept-Encodingдля кэширующих прокси и CDN обеспечивается стандартной директивойgzip_vary on;в блоке http либо явным правиломadd_header Vary Accept-Encoding;.
⚡ Связка с микрокэшированием и FastCGI Cache
Если на вашем сервере используется обратный прокси или генерация страниц на PHP, обязательно объединяйте сжатие с кэшированием ответов. О том, как выдерживать тысячи запросов в секунду на недорогом сервере, читайте в нашем руководстве по микрокэшированию в Nginx FastCGI Cache, а быстро собрать готовый конфиг проксирования поможет генератор конфигураций Nginx Reverse Proxy.
6. Подбор уровней сжатия: почему brotli_comp_level 11 опасен для динамики
Шкала директивы brotli_comp_level варьируется от 0 до 11 (где 0 — сквозной режим копирования без сжатия, 1 — наивысшая скорость, 11 — максимальная компрессия, по умолчанию — 6). Новичкам часто кажется заманчивым выставить максимальное значение brotli_comp_level 11 ради получения наименьшего возможного размера файла. Это фатальная ошибка на боевом сервере!
Время работы алгоритма компрессии растет нелинейно:
- Уровни 1–3 (Сверхбыстрые): по плотности сжатия сопоставимы со стандартным Gzip уровней 5–6, но выполняются быстрее Deflate. Отличный выбор для высоконагруженных API-шлюзов с тысячами RPS на ядро.
- Уровни 4–6 (Золотая середина для продакшена): уровень 4 по степени сжатия уже приближается к максимальному Gzip-9, а уровни 5–6 сжимают еще на 15–20% плотнее Gzip-6. При этом время упаковки типичной динамической страницы на PHP/Node.js занимает всего несколько миллисекунд и не приводит к росту TTFB.
- Уровни 7–9 (Высокие): целесообразны только для редко меняющихся страниц с включенным кэшированием FastCGI или Nginx.
- Уровни 10–11 (Экстремальные): время сжатия одного файла JS размером 500 КБ может превышать 200–400 миллисекунд! Процессор VDS мгновенно уходит в 100% Load Average, а показатель Time to First Byte (TTFB) катастрофически деградирует.
🚨 Железное правило сисадмина
Никогда не ставьте brotli_comp_level выше 5 или 6 для директивы динамического сжатия brotli on;. Уровень 11 предназначен исключительно для фонового статического предсжатия файлов во время CI/CD деплоя или локальной сборки проекта.
7. Предварительное сжатие статики (brotli_static): нулевая нагрузка на CPU
Самый мощный архитектурный прием высоконагруженных веб-серверов — полное исключение сжатия тяжелых статических файлов (JavaScript-бандлов, CSS-стилей, иконок SVG) в рантайме. С помощью директивы brotli_static on; Nginx проверяет наличие готовых файлов с расширением .br прямо на жестком диске.
Механика работы brotli_static:
- Браузер запрашивает файл
https://example.com/assets/app.jsс заголовкомAccept-Encoding: br. - Nginx проверяет, существует ли в том же каталоге файл
app.js.brс датой изменения не старше оригинальногоapp.js. - Если файл существует, Nginx отдает его клиенту напрямую с заголовком
Content-Encoding: brчерез системный вызов ядра Linuxsendfile().
При этом на этапе сборки проекта вы можете сжать файлы максимальным уровнем 11, получив минимально возможный размер без расхода тактов процессора VDS в момент отдачи!
🛠️ Вариант А: Однострочник для генерации статики на сервере
Установите официальный консольный архиватор Brotli и запустите фоновое сжатие каталога со статикой:
# Установка консольной утилиты brotli
sudo apt install -y brotli
# Поиск и сжатие всех JS, CSS, SVG и JSON файлов максимальным качеством (уровень 11)
find /var/www/site/dist -type f \( -name "*.js" -o -name "*.css" -o -name "*.svg" -o -name "*.json" \) \
-exec brotli -f -k -q 11 {} \;
# Создание fallback-копий для gzip (уровень 9)
find /var/www/site/dist -type f \( -name "*.js" -o -name "*.css" -o -name "*.svg" -o -name "*.json" \) \
-exec gzip -f -k -9 {} \;
Флаги утилиты brotli:
-f(force) — перезаписывать существующие архивные файлы;-k(keep) — сохранять исходный исходный файл (не удалять.js);-q 11(quality) — наивысшая плотность сжатия.
Если вы собираете фронтенд во Vite или Webpack, компрессию можно автоматизировать прямо в пайплайне сборщика. Например, с помощью плагина vite-plugin-compression:
// vite.config.js
import { defineConfig } from 'vite';
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
// Генерация файлов .br (Brotli)
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
threshold: 512,
}),
// Генерация файлов .gz (Gzip fallback)
viteCompression({
algorithm: 'gzip',
ext: '.gz',
threshold: 512,
})
]
});
8. Проверка отдачи и замеры экономии трафика: curl и онлайн-инструменты
После редактирования конфигурации обязательно протестируйте синтаксис Nginx и примените изменения без разрыва текущих сетевых соединений:
# Проверка синтаксиса конфигурационных файлов
sudo nginx -t
# Мягкая перезагрузка воркеров Nginx
sudo systemctl reload nginx
Для проверки работы сжатия в терминале используйте утилиту curl, передавая различные значения заголовка Accept-Encoding:
# 1. Запрос с поддержкой Brotli
curl -I -H "Accept-Encoding: br" https://example.com/assets/app.js
# Ожидаемый ответ:
# HTTP/2 200
# content-type: application/javascript
# content-encoding: br
# vary: Accept-Encoding
# 2. Запрос с поддержкой только Gzip
curl -I -H "Accept-Encoding: gzip" https://example.com/assets/app.js
# Ожидаемый ответ:
# HTTP/2 200
# content-encoding: gzip
# 3. Запрос без поддержки сжатия (проверка отдачи чистого контента)
curl -I https://example.com/assets/app.js
Сравните реальный размер ответа в байтах на боевом сайте:
# Исходный размер без сжатия:
curl -s https://example.com/assets/app.js | wc -c
# Результат: 482150 байт (~470 КБ)
# Размер со сжатием Gzip:
curl -s -H "Accept-Encoding: gzip" https://example.com/assets/app.js | wc -c
# Результат: 124800 байт (~121 КБ)
# Размер со сжатием Brotli:
curl -s -H "Accept-Encoding: br" https://example.com/assets/app.js | wc -c
# Результат: 98120 байт (~95 КБ)
Разница между Gzip и Brotli в приведенном примере составляет 26.68 КБ (более 21% дополнительной экономии) на одном единственном скрипте! На масштабе десятков тысяч посещений это экономит гигабайты сетевого трафика и ускоряет рендеринг страницы на мобильных устройствах с нестабильным 4G/LTE интернетом.
🔎 Диагностика доступности веб-сервера онлайн
При настройке сетевых интерфейсов и портов убедитесь, что ваш веб-сервер корректно доступен внешнему миру. Проверьте конфигурацию сетевых служб через онлайн сканер открытых портов и удостоверьтесь в корректности распознавания инфраструктуры в череке хостинга сайтов.
9. Диагностика неполадок: почему браузер не получает заголовок br и как исправить
В практике настройки ngx_brotli встречаются несколько распространенных проблем:
Симптом 1: Браузер упорно получает content-encoding: gzip
- Причина 1: Сайт открыт по HTTP вместо HTTPS. Браузеры не отправляют маркер
brпо открытому каналу 80 порта. Настройте принудительный редирект 301 на HTTPS. - Причина 2: Проксирование через Cloudflare. Если домен подключен через Cloudflare с оранжевым облаком (Proxy), Cloudflare сам выполняет сжатие ответов между CDN и посетителем. Убедитесь, что в панели Cloudflare во вкладке Speed → Optimization активирован переключатель Brotli.
- Причина 3: Корпоративный прокси или антивирус. Некоторые антивирусные сетевые фильтры или старые корпоративные шлюзы вырезают неизвестные им значения заголовка
Accept-Encoding. Проверяйте ответ через чистыйcurlна сервере.
Симптом 2: Ошибка unknown directive "brotli" при перезапуске Nginx
Веб-сервер не загрузил модуль. Убедитесь, что:
- При сборке из PPA файл
/etc/nginx/modules-enabled/50-mod-brotli.confсуществует и содержит корректные строкиload_module; - При ручной сборке директивы
load_module modules/ngx_http_brotli_filter_module.so;расположены в самом начале/etc/nginx/nginx.confдо первого блокаevents {}илиhttp {}.
Симптом 3: Ошибка module is not binary compatible
Возникает, если дистрибутивный Nginx обновился через apt upgrade, а динамический модуль остался скомпилированным под предыдущую версию. Решение — пересобрать модуль против исходников новой версии либо использовать PPA, где модули обновляются синхронно с веб-сервером.
Симптом 4: Nginx не отдает готовые файлы .br из папки со статикой
При использовании директивы brotli_static on; Nginx сверяет время модификации (mtime): если сжатый файл app.js.br на диске оказывается старше исходного app.js, веб-сервер расценивает его как устаревший и переключается на динамическое сжатие. Рекомендуется обновлять метку командой touch app.js.br после деплоя либо использовать режим brotli_static always;, если вы гарантируете актуальность предварительно собранных бандлов.
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud — Быстрые NVMe VDS
Идеально подходит для Nginx и сжатия Brotli: высокочастотные процессоры до 3.3 ГГц сжимают страницы с минимальной задержкой TTFB.
Selectel — Премиум VDS Tier III
Сертифицированные дата-центры в РФ и широкие аплинки до 1 Гбит/с для скоростной отдачи статики и тяжелого веб-контента.
Beget — Надежные VDS с почасовой оплатой
Чистые дистрибутивы Ubuntu 24.04 LTS и мгновенная переустановка для безопасного тестирования сборок модулей Nginx.
При настройке динамического сжатия алгоритмом Brotli на лету производительность напрямую зависит от однопоточной скорости CPU: для средненагруженных сайтов на VDS рекомендуется выбирать тарифы с современными ядрами от 3 ГГц, чтобы поддерживать уровень сжатия 5–6 без микрозадержек в TTFB.