Comprimir las respuestas de texto (HTML, CSS, JavaScript, JSON, SVG) reduce su tamaño entre un 60 % y un 90 %, con lo que las páginas cargan antes y se consume menos ancho de banda. Todos los navegadores actuales admiten Gzip y Brotli, y este último consigue ficheros algo más pequeños con un coste de CPU similar. En este tutorial activarás Gzip y Brotli en Nginx y en Apache sobre Ubuntu 24.04 y comprobarás con curl qué codificación sirve el servidor en cada caso. Sigue solo la parte del servidor web que uses.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Nginx (
sudo apt install nginx) o Apache (sudo apt install apache2) instalado y sirviendo una web. curlpara las comprobaciones (viene instalado por defecto).
Qué comprimir y qué no
La compresión solo tiene sentido para formatos de texto. Las imágenes JPEG, PNG y WebP, los vídeos, los ficheros ZIP y las fuentes WOFF2 ya están comprimidos, y volver a comprimirlos gasta CPU sin reducir su tamaño. Los tipos MIME que conviene comprimir son:
| Tipo de contenido | Tipos MIME |
|---|---|
| HTML | text/html |
| Hojas de estilo | text/css |
| JavaScript | text/javascript, application/javascript |
| Datos | application/json, application/xml, text/xml, application/rss+xml |
| Texto plano | text/plain |
| Gráficos vectoriales | image/svg+xml |
Tampoco merece la pena comprimir respuestas muy pequeñas: por debajo de unos cientos de bytes, la cabecera de compresión puede ocupar más de lo que se ahorra.
Nginx
Paso 1: Configurar Gzip
Nginx en Ubuntu trae el módulo gzip y lo activa en /etc/nginx/nginx.conf con gzip on;, pero con la configuración por defecto solo comprime text/html. Las demás opciones aparecen comentadas en ese fichero. En lugar de editarlo, crea un fichero propio en conf.d, que Nginx carga dentro del bloque http:
sudo nano /etc/nginx/conf.d/compression.conf
# Gzip (gzip on ya está en nginx.conf)
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
Qué hace cada directiva:
gzip_vary on: añade la cabeceraVary: Accept-Encodingpara que las cachés intermedias y las CDN guarden por separado la versión comprimida y la sin comprimir.gzip_proxied any: comprime también las respuestas a peticiones que llegan a través de un proxy o CDN.gzip_comp_level 5: nivel de 1 a 9. A partir de 5 o 6 la reducción de tamaño es mínima y el coste de CPU sigue subiendo.gzip_min_length 256: no comprime respuestas de menos de 256 bytes.gzip_types: tipos MIME a comprimir, además detext/html, que se comprime siempre.
No declares ninguna de estas directivas también en nginx.conf sin comentar, o Nginx dará un error de directiva duplicada.
Comprueba la configuración y recarga:
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Paso 2: Instalar y configurar Brotli
Ubuntu 24.04 incluye el módulo de Brotli para Nginx en dos paquetes: libnginx-mod-http-brotli-filter, que comprime al vuelo, y libnginx-mod-http-brotli-static, que sirve ficheros .br precomprimidos. Instálalos:
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
Los paquetes cargan los módulos automáticamente mediante enlaces en /etc/nginx/modules-enabled/:
ls /etc/nginx/modules-enabled/
50-mod-http-brotli-filter.conf
50-mod-http-brotli-static.conf
Añade la configuración de Brotli al mismo fichero compression.conf:
sudo nano /etc/nginx/conf.d/compression.conf
# Brotli
brotli on;
brotli_comp_level 5;
brotli_min_length 256;
brotli_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
# Servir ficheros precomprimidos .br y .gz si existen junto al original
brotli_static on;
gzip_static on;
Cuando el navegador acepta ambos formatos, Nginx sirve Brotli; los clientes que solo admiten Gzip siguen recibiendo Gzip. Con brotli_static y gzip_static, si existe app.js.br o app.js.gz junto a app.js, Nginx envía directamente el fichero precomprimido sin gastar CPU. Muchas herramientas de build de frontend pueden generar estos ficheros.
Comprueba y recarga:
sudo nginx -t
sudo systemctl reload nginx
Apache
Paso 1: Revisar Gzip (mod_deflate)
En Apache la compresión Gzip la hace mod_deflate, que en Ubuntu viene activado por defecto con una lista de tipos en /etc/apache2/mods-available/deflate.conf. Compruébalo:
apache2ctl -M | grep -E 'deflate|filter'
deflate_module (shared)
filter_module (shared)
Si solo necesitas Gzip, ya lo tienes funcionando y puedes pasar a la sección de verificación.
Paso 2: Activar Brotli (mod_brotli)
El módulo mod_brotli viene incluido en el paquete apache2 de Ubuntu 24.04, pero desactivado. Actívalo:
sudo a2enmod brotli
Hay un detalle importante: si dejas la configuración de deflate.conf tal como está y añades Brotli por separado, Apache aplica primero Gzip y el navegador nunca recibe Brotli. La solución es declarar ambos filtros en una sola directiva, en el orden BROTLI_COMPRESS;DEFLATE: Brotli comprime si el cliente lo admite y, si no, lo hace Gzip.
Primero desactiva las líneas por defecto de deflate.conf:
sudo nano /etc/apache2/mods-available/deflate.conf
Comenta las líneas AddOutputFilterByType para que el fichero quede así:
<IfModule mod_filter.c>
# AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
# AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
# AddOutputFilterByType DEFLATE application/rss+xml
# AddOutputFilterByType DEFLATE application/wasm
# AddOutputFilterByType DEFLATE application/xml
</IfModule>
Después crea un fichero de configuración propio con los dos filtros encadenados:
sudo nano /etc/apache2/conf-available/compression.conf
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS;DEFLATE text/html text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml image/svg+xml
BrotliCompressionQuality 5
</IfModule>
BrotliCompressionQuality va de 0 a 11 y por defecto es 5, un buen equilibrio para compresión al vuelo. Los valores altos (10 u 11) son muy lentos y solo tienen sentido para ficheros precomprimidos.
Activa la configuración, comprueba la sintaxis y recarga Apache:
sudo a2enconf compression
sudo apache2ctl configtest
sudo systemctl reload apache2
Syntax OK
Verificar la compresión
La comprobación es la misma para Nginx y Apache. Pide una página indicando qué codificaciones acepta el cliente con la cabecera Accept-Encoding y mira la cabecera Content-Encoding de la respuesta. Sustituye your_domain por tu dominio o la IP del servidor.
Un cliente que acepta Gzip y Brotli, como cualquier navegador moderno, debe recibir Brotli:
curl -s -o /dev/null -D - -H 'Accept-Encoding: gzip, deflate, br' http://your_domain/ | grep -i -E 'content-encoding|vary'
Vary: Accept-Encoding
Content-Encoding: br
Un cliente que solo acepta Gzip debe recibir Gzip:
curl -s -o /dev/null -D - -H 'Accept-Encoding: gzip' http://your_domain/ | grep -i -E 'content-encoding|vary'
Vary: Accept-Encoding
Content-Encoding: gzip
Para ver el ahorro, compara los bytes descargados sin compresión y con Brotli:
curl -s -o /dev/null -w 'sin compresión: %{size_download} bytes\n' http://your_domain/
curl -s -o /dev/null -w 'brotli: %{size_download} bytes\n' -H 'Accept-Encoding: br' http://your_domain/
sin compresión: 10671 bytes
brotli: 2722 bytes
Repite la prueba con un fichero CSS o JavaScript de tu web, por ejemplo http://your_domain/assets/app.css. También puedes comprobarlo en el navegador: en las herramientas de desarrollo, pestaña Red, la columna o cabecera Content-Encoding muestra br o gzip para cada recurso.
Solución de problemas
- No aparece
Content-Encoding: la respuesta es más pequeña que el mínimo configurado o su tipo MIME no está en la lista. Comprueba el tipo concurl -sI http://your_domain/ruta | grep -i content-type. - Apache sirve Gzip aunque el cliente acepta Brotli: siguen activas las líneas
AddOutputFilterByType DEFLATEdedeflate.confu otra directivaDEFLATEen tus virtual hosts o en un.htaccess. Elimínalas y deja solo la cadenaBROTLI_COMPRESS;DEFLATE. unknown directive "brotli"en Nginx: el módulo no está cargado. Comprueba que los paquetes están instalados y que existen los enlaces en/etc/nginx/modules-enabled/.- Detrás de Cloudflare u otra CDN: la CDN puede recomprimir o descomprimir las respuestas hacia el visitante. Comprueba las cabeceras directamente contra la IP del servidor para aislar el comportamiento de tu origen.
- Uso de CPU alto: baja
gzip_comp_level,brotli_comp_leveloBrotliCompressionQuality, y sirve ficheros estáticos precomprimidos cuando sea posible.
Conclusión
Tu servidor web comprime ahora las respuestas de texto con Brotli para los navegadores que lo admiten y con Gzip para el resto, y sabes comprobarlo con curl. Como siguientes pasos, configura cabeceras de caché del navegador para los ficheros estáticos, activa HTTP/2 junto con HTTPS y mide el efecto de cada cambio con Apache Bench o con las herramientas de desarrollo del navegador.
