En esta guía estaré explicando como compilar el módulo Brotli para Nginx, un algoritmo de compresión desarrollado por Google, como alternativa a Gzip y Deflate. La razón de compilar el módulo es que Nginx no ha dado soporte oficial a la versión de código abierto, siendo que en su versión Nginx Plus sí lo tiene soportado.
Probado con los sistemas:
- Debian 10 Buster
- Debian 11 Bullseye
- Ubuntu 20.04 Focal Fossa
- Ubuntu 22.04 LTS Jammy Jellyfish
Usando las versiones de Nginx:
- Nginx 1.14
- Nginx 1.18
Instalar Nginx
Lo primero que necesitamos hacer es instalar Nginx. Si vamos a compilar el módulo de manera local hay que usar exactamente la misma distribución con los mismos repositorios. Ya que podemos simplemente copiarlo a producción, pero los entornos deben ser los mismos. Si en el sistema final usaremos el paquete nginx-full, nginx-extras o cualquier otro, no es mala idea instalarlos también, un pequeño detalle como este puede quitarnos muchas horas.
Instalamos con:
sudo apt -y install nginx
Instalar dependencias
Actualizamos los paquetes que tengan actualizaciones pendientes:
sudo apt update
sudo apt -y upgrade
Instalamos los siguientes paquetes:
sudo apt -y install git libpcre3 libpcre3-dev zlib1g zlib1g-dev libxslt1-dev openssl libssl-dev apt-src
Antes del siguiente paso editamos nuestro /etc/apt/sources.list
, y quitamos el símbolo #
de las líneas que tengan deb-src
, solo de los repositorios que sí se estén usando.
sudo nano /etc/apt/sources.list
En una instalación con Ubuntu, los repositorios vienen así:
deb http://archive.ubuntu.com/ubuntu focal main restricted
# deb-src http://archive.ubuntu.com/ubuntu focal main restricted
Tenemos que quitar el comentario de cada repositorio que encontremos debajo de cada deb
.
Luego de editarlo debe quedar similar a este:
deb http://archive.ubuntu.com/ubuntu focal main restricted
deb-src http://archive.ubuntu.com/ubuntu focal main restricted
Después actualizamos la caché de apt y de apt-src:
sudo apt update && sudo apt-src update
Descargar código fuente de Nginx y Brotli
Creamos un directorio para guardar todo en el directorio principal de nuestro usuario:
cd ~ && mkdir nginx-brotli && cd nginx-brotli
Empezamos descargando el código fuente de Nginx con apt-src
para que haga juego con la versión instalada del sistema:
sudo apt-src install nginx
Luego descargamos el código fuente de Brotli del repositorio oficial de Google:
cd ~/nginx-brotli
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli
git submodule update --init
Compilar Brotli como módulo dinámico
Cambiamos de directorio al de Nginx:
cd ~/nginx-brotli/nginx-*/
Ejecutamos lo siguiente:
sudo ./configure --with-compat --add-dynamic-module=../ngx_brotli
Si no aparece ningún error, ejecutamos:
sudo make modules
Y si todo salió bien nos dirigimos hasta la sección de Configuración de Nginx.
En caso de error usando configure
Cuando obtenemos error al ejecutar ./configure
anteriormente. Seguimos los siguientes pasos.
Ejecutamos el siguiente comando para ver las opciones de compilación que la versión de Nginx instalada uso:
sudo nginx -V
Copiamos todas las opciones después del texto configure arguments:
, le quitamos todas las opciones que comiencen con --add-dynamic-module
y le agregamos al final separado con un espacio:
--add-dynamic-module=../ngx_brotli
Al principio le agregamos sudo ./configure y un espacio para separar las opciones. Debe ser algo similar a lo siguiente:
sudo ./configure OPCIONES_DEL_COMANDO --add-dynamic-module=../ngx_brotli
El comando resultante normalmente es de varias líneas, lo resumí con "OPCIONES_DEL_COMANDO" para que sea más comprensible. Lo ejecutamos como un comando.
Podemos usar el siguiente comando para generar el comando completo en lugar de hacerlo manualmente:
sudo nginx -V 2>&1 | grep '^configure arguments:' | sed -r 's/--add-dynamic-module=(\S)+(\s|$)//g; s/$/\-\-add\-dynamic\-module=\.\.\/ngx_brotli/g; s/configure arguments:/sudo \.\/configure/g'
El comando anterior modifica la salida de nginx -V
y lo convierte en el comando que necesitamos para compilar Nginx. Lo copiamos y ejecutamos.
Copiar desde donde dice sudo ./configure...
.
Por último, ejecutamos:
sudo make modules
Configuración de Nginx
Copiamos los archivos resultantes ngx_http_brotli_filter_module.so
y ngx_http_brotli_static_module.so
al directorio /etc/nginx/modules-available
:
sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules-available
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules-available
Creamos el archivo /etc/nginx/modules-enabled/50-brotli.conf
:
sudo nano /etc/nginx/modules-enabled/50-brotli.conf
Y le agregamos las siguientes referencias a los módulos:
load_module /etc/nginx/modules-available/ngx_http_brotli_filter_module.so;
load_module /etc/nginx/modules-available/ngx_http_brotli_static_module.so;
Probamos la configuración y los módulos con:
sudo nginx -t
Si todo está bien nos aparecerá:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
De lo contrario, si existe algún problema, la salida será:
nginx: [emerg] module ngx_http_brotli_filter_module.so is not binary compatible in nginx.conf...
Si no sabemos por qué tenemos errores, hay que prestar atención al comando, configure
y revisar al final todos los errores que aparecen. También no estaría de más revisar si estamos usando la misma versión, y en el caso de que el sistema destino sea diferente con mayor razón. Mientras no reiniciemos Nginx no habría ningún problema porque el último comando solo revisa la configuración sin realizar cambio alguno.
Para terminar con todo el desastre que quedó, eliminamos los archivos de código fuente usados:
sudo rm -R ~/nginx-brotli/
Uso en otros sistemas de producción o en desarrollo
Ya que todo está comprobado y, las versiones del sistema operativo y software coinciden, podemos copiar los archivos que quedaron en /etc/nginx/modules-available
. Teniendo en cuenta que cada que exista una actualización por mínima que sea, tenemos que recompilar los módulos para que sean compatibles. No estaría de más renombrarlos para que tengan el formato, módulo-1.14-2.so
haciendo referencia a la versión de Nginx para la que fueron compilados. Además de copiarlos, tenemos que realizar los pasos anteriores, como el de volver a editar el archivo de configuración de Nginx para cargar los módulos y volver a comprobar la configuración antes de reiniciar.
Bloquear actualización de paquete Nginx
Si queremos evitar accidentes podemos usar la utilidad apt-mark para forzar al gestor de paquetes a que no actualice Nginx, pero si el resto de los paquetes.
Bloquear versión instalada:
sudo apt-mark hold nginx
Para desbloquear el paquete después de colocar nuevos módulos y comprobar su configuración nueva:
sudo apt-mark unhold nginx
Reiniciar Nginx si no hay ningún problema
Para reiniciar Nginx después de comprobar que los módulos si están funcionando usar:
sudo systemctl restart nginx
Activación y uso de los módulos
Hasta este momento Nginx ya tiene cargados los módulos, solo falta activarlos y configurar, y al final comprobaremos si están funcionando.
Editamos el archivo nginx.conf
:
nano /etc/nginx/nginx.conf
Exactamente, debajo de gzip on;
colocamos en una nueva línea:
brotli on;
Después buscamos una línea que tenga gzip_types
, si empieza con "#" se lo quitamos, la copiamos completamente y colocamos la nueva debajo, el resultado será algo similar:
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Ambas líneas deben tener los mismos argumentos para aprovechar al máximo el nuevo algoritmo de compresión.
Comprobamos que la configuración funcione con sudo nginx -t
y reiniciamos el servicio:
sudo systemctl restart nginx
Para el módulo ngx_http_brotli_static_module.so
hay que usarlo igual que la opción gzip_static
, podemos revisar la directiva en el repositorio de Google, o la directiva gzip_static en Nginx.
Comprobando funcionamiento del algoritmo de compresión
Para esto vamos a necesitar usar Firefox, Chrome, o cualquier navegador que soporte este algoritmo. En el caso de que sea el mismo sistema en donde tenemos instalado el paquete, abrimos 127.0.0.1 en el navegador y abrimos las herramientas para desarrolladores con F12, y nos dirigimos a la pestaña Red o Network. Hacemos clic en la URL y verificamos que en Response Headers en Content-Encoding salga "br", en Request Headers y Accept-Encoding verificamos que salga "gzip, deflate, br" en cualquier orden. Si en Content-Encoding no aparece "br", significa que el servidor no mandó el contenido con el nuevo algoritmo, y si en Accept-Encoding no aparece "br" puede ser que el navegador no lo soporte o simplemente no se encuentra activado para el tipo de documento.
Si tenemos problemas con Firefox podría tratarse porque Brotli no está soportado en conexiones sin SSL, y como en este caso usamos localhost puede no funcionar localmente. Si queremos probar sin SSL podemos usar Chrome, este al menos en la versión 84 lo soporta sin HTTPS.
Me basé en esta entrada de Website for Students, aunque tuve problemas en el paso de la compatibilidad del binario. En el repositorio oficial de Brotli viene un poco de información acerca de la compilación.