HTTP/2 permite enviar muchas peticiones en paralelo sobre una sola conexión TCP, comprime las cabeceras y reduce la latencia frente a HTTP/1.1, sobre todo en páginas con muchos recursos. Todos los navegadores actuales lo soportan, pero solo sobre HTTPS, y lo negocian durante el handshake TLS mediante ALPN. En este tutorial activarás HTTP/2 en Nginx y en Apache en Ubuntu 24.04 y comprobarás que el servidor lo usa realmente.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, y un usuario no root con privilegios sudo.
  • Nginx o Apache instalado desde los repositorios de Ubuntu.
  • Un sitio que ya sirva HTTPS con un certificado válido, por ejemplo de Let's Encrypt. En la guía se usa your_domain como marcador de tu dominio.
  • El puerto 443 abierto en el firewall.

Las versiones de Ubuntu 24.04 son Nginx 1.24 y Apache 2.4.58, ambas con soporte HTTP/2 incluido. No necesitas compilar nada ni añadir repositorios.

Paso 1: Comprobar el protocolo actual

Antes de cambiar nada, comprueba qué protocolo negocia hoy el servidor. La opción --http2 de curl pide HTTP/2 y vuelve a HTTP/1.1 si el servidor no lo ofrece:

curl -sI --http2 https://your_domain | head -n 1
HTTP/1.1 200 OK

Si ya aparece HTTP/2 200, HTTP/2 está activo y no necesitas continuar.

Paso 2: Activar HTTP/2 en Nginx

El paquete de Nginx de Ubuntu está compilado con el módulo HTTP/2. Puedes confirmarlo:

nginx -V 2>&1 | grep -o with-http_v2_module
with-http_v2_module

Abre el archivo de tu sitio:

sudo nano /etc/nginx/sites-available/your_domain

En Nginx 1.24, que es la versión de Ubuntu 24.04, HTTP/2 se activa con el parámetro http2 en las directivas listen del puerto 443. Si Certbot configuró el sitio, las líneas terminarán con # managed by Certbot; basta con añadir http2:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name your_domain www.your_domain;

    ssl_certificate     /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;

    # resto de la configuración del sitio
}

HTTP/2 se aplica a nivel de dirección y puerto: si varios sitios escuchan en 443, basta con activarlo en uno para que lo usen todos, pero es más claro añadirlo en cada bloque.

Valida la sintaxis 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

Pasa al paso 5 para verificarlo.

Paso 3: Activar HTTP/2 en Apache

En Ubuntu, el módulo mod_http2 viene incluido en el paquete apache2, pero no está habilitado. Actívalo:

sudo a2enmod http2

La directiva Protocols indica qué protocolos ofrece Apache y en qué orden de preferencia. Declárala en el VirtualHost HTTPS de tu sitio para que el comportamiento quede explícito. Si Certbot creó el sitio, el archivo será your_domain-le-ssl.conf:

sudo nano /etc/apache2/sites-available/your_domain-le-ssl.conf

Añade la línea Protocols dentro del bloque <VirtualHost *:443>:

<VirtualHost *:443>
    ServerName your_domain
    Protocols h2 http/1.1

    # resto de la configuración del sitio
</VirtualHost>

h2 es HTTP/2 sobre TLS; los clientes que no lo soporten seguirán usando http/1.1. Si quieres aplicarlo a todos los sitios, puedes poner la misma línea fuera de cualquier <VirtualHost>, por ejemplo al final de /etc/apache2/apache2.conf.

Valida la configuración, pero no recargues todavía: primero revisa el MPM en el paso siguiente.

sudo apache2ctl configtest
Syntax OK

Paso 4: Usar el MPM event en Apache

Apache procesa las conexiones con un MPM (módulo de multiprocesamiento). HTTP/2 funciona correctamente con event, que es el predeterminado en Ubuntu. Con prefork, mod_http2 se desactiva: Apache sigue funcionando, pero solo con HTTP/1.1, y lo avisa en el log de errores. El caso típico es haber instalado libapache2-mod-php, que cambia el servidor a prefork. Comprueba cuál usas:

sudo apache2ctl -V | grep -i mpm
Server MPM:     event

Si ves event, recarga Apache y pasa al paso 5:

sudo systemctl reload apache2

Si ves prefork porque usas PHP como módulo, cambia a PHP-FPM. Ubuntu 24.04 incluye PHP 8.3. Instala PHP-FPM:

sudo apt install php8.3-fpm

Desactiva el módulo de PHP y prefork, y activa event junto con los módulos que conectan Apache con PHP-FPM:

sudo a2dismod php8.3 mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif
sudo a2enconf php8.3-fpm

La configuración php8.3-fpm que proporciona el paquete envía los archivos .php al socket /run/php/php8.3-fpm.sock. Valida y reinicia Apache (el cambio de MPM necesita un reinicio completo, no basta con recargar):

sudo apache2ctl configtest
sudo systemctl restart apache2

Confirma que ahora usa event y que PHP-FPM está activo:

sudo apache2ctl -V | grep -i mpm
systemctl is-active php8.3-fpm
Server MPM:     event
active

Abre una página PHP de tu sitio para asegurarte de que sigue funcionando. Ten en cuenta que los ajustes de PHP ya no se leen de /etc/php/8.3/apache2/php.ini sino de /etc/php/8.3/fpm/php.ini.

Paso 5: Verificar HTTP/2

Repite la petición del paso 1:

curl -sI --http2 https://your_domain | head -n 1
HTTP/2 200

Para ver la negociación ALPN en detalle, usa el modo detallado de curl:

curl -sv --http2 -o /dev/null https://your_domain 2>&1 | grep -i alpn
* ALPN: curl offers h2,http/1.1
* ALPN: server accepted h2

En el navegador, abre las herramientas de desarrollo, ve a la pestaña Red (Network), haz clic derecho sobre el encabezado de las columnas y activa Protocolo. Las peticiones a tu dominio deben mostrar h2.

Si quieres medir el rendimiento, el paquete nghttp2-client incluye h2load, un generador de carga para HTTP/2:

sudo apt install nghttp2-client
h2load -n 1000 -c 10 -m 10 https://your_domain/

-n es el número total de peticiones, -c el de conexiones simultáneas y -m el de flujos paralelos por conexión. Ejecútalo desde otra máquina para no medir la carga del propio generador. La línea requests: del resumen debe mostrar todas las peticiones como succeeded.

Solución de problemas

  • curl sigue mostrando HTTP/1.1: comprueba que accedes por https://; los navegadores y --http2 no usan HTTP/2 sobre HTTP sin cifrar. En Nginx, revisa que todas las directivas listen del puerto 443 tengan http2. En Apache, confirma que el módulo está cargado con sudo apache2ctl -M | grep http2.
  • Apache escribe en el log The mpm module (prefork.c) is not supported by mod_http2: sigue el paso 4 para pasar a event y PHP-FPM.
  • nginx: [emerg] unknown directive "http2": estás usando http2 on; con Nginx 1.24. Usa el parámetro http2 en listen, como en el paso 2.
  • nginx: [warn] the "listen ... http2" directive is deprecated: tu Nginx es 1.25.1 o posterior. Cambia a listen 443 ssl; y http2 on;.
  • Error ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY en Chrome: la configuración TLS permite cifrados que HTTP/2 prohíbe. Limita los protocolos a TLS 1.2 y 1.3 y usa la lista de cifrados predeterminada del servidor.

Conclusión

Has activado HTTP/2 en Nginx o Apache, has cambiado Apache al MPM event con PHP-FPM cuando era necesario y has comprobado con curl y con el navegador que el servidor negocia h2. Los clientes antiguos siguen usando HTTP/1.1 sin ningún cambio.

Como siguientes pasos puedes:

  • Revisar tu estrategia de recursos: con HTTP/2 ya no compensa unir todos los archivos CSS o JS en uno ni repartir recursos entre subdominios.
  • Evitar HTTP/2 Server Push, que los navegadores han dejado de soportar y que Nginx eliminó en la versión 1.25.1; usa en su lugar <link rel="preload">.
  • Estudiar HTTP/3 (QUIC), disponible en las versiones recientes de Nginx del repositorio oficial de nginx.org.