--- title: "Cómo activar HTTP/3 y QUIC con Nginx en Ubuntu 24.04" description: "Activa HTTP/3 sobre QUIC en Ubuntu 24.04 con Nginx del repositorio oficial o con Caddy, abre el puerto UDP 443 y comprueba que el navegador usa el protocolo h3." category: "Proxy y Equilibrio de Carga" language: es source: https://cubepath.com/es/docs/proxy-y-equilibrio-de-carga/configuracion-de-http3-quic updated: 2026-09-25 --- # Cómo activar HTTP/3 y QUIC con Nginx en Ubuntu 24.04 HTTP/3 es la versión de HTTP que funciona sobre QUIC, un transporte cifrado que va sobre UDP en lugar de TCP. Integra TLS 1.3 en el propio transporte, establece conexiones con menos viajes de ida y vuelta y evita que un paquete perdido bloquee todas las peticiones de la conexión, lo que se nota sobre todo en redes móviles o con pérdidas. En esta guía activarás HTTP/3 en Nginx en Ubuntu 24.04 usando el paquete oficial de nginx.org, abrirás el puerto UDP necesario y comprobarás que los navegadores lo usan. Al final verás cómo hacerlo con Caddy, que lo trae activado de serie. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Un dominio (`your_domain` en los ejemplos) con un registro DNS A apuntando a la IP pública del servidor. - Los puertos 80/TCP, 443/TCP y 443/UDP abiertos. Si tienes un firewall de red además de UFW, abre también el UDP 443 allí. > Nota: el Nginx 1.24 que incluye Ubuntu 24.04 no tiene soporte para HTTP/3. El módulo `ngx_http_v3_module` existe desde Nginx 1.25, así que esta guía usa el repositorio oficial de nginx.org, cuyos paquetes lo incluyen compilado. ## Cómo se negocia HTTP/3 Un navegador no intenta HTTP/3 a ciegas. La primera conexión va por TCP con HTTP/2 o HTTP/1.1, y el servidor anuncia en la cabecera `Alt-Svc` que también atiende HTTP/3 en el puerto UDP 443: ```text alt-svc: h3=":443"; ma=86400 ``` A partir de ahí el navegador intenta QUIC y, si el UDP está bloqueado, sigue usando TCP sin que el usuario note nada. Por eso HTTP/3 siempre se configura junto a HTTPS por TCP, nunca en su lugar. ## Paso 1: Instalar Nginx desde el repositorio de nginx.org Si tienes instalado el Nginx de Ubuntu, haz copia de tu configuración y elimínalo, porque los paquetes de nginx.org lo sustituyen: ```bash sudo cp -r /etc/nginx ~/nginx-backup sudo apt remove nginx nginx-common ``` Instala las herramientas para añadir el repositorio y descarga la clave de firma: ```bash sudo apt update sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /etc/apt/keyrings/nginx-archive-keyring.gpg ``` Añade el repositorio de la rama estable: ```bash echo "deb [signed-by=/etc/apt/keyrings/nginx-archive-keyring.gpg] https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list ``` Da prioridad a estos paquetes frente a los de Ubuntu para que una actualización no te devuelva a la versión 1.24: ```bash printf "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx ``` Instala Nginx y arráncalo: ```bash sudo apt update sudo apt install nginx sudo systemctl enable --now nginx ``` Comprueba que la versión es 1.25 o superior y que el módulo HTTP/3 está compilado: ```bash nginx -V 2>&1 | grep -o 'nginx/[0-9.]*\|with-http_v3_module' ``` ```output nginx/1.28.0 with-http_v3_module ``` El número de versión que veas será el de la rama estable vigente. Lo importante es que aparezca `with-http_v3_module`. > Importante: los paquetes de nginx.org no usan `sites-available` ni `sites-enabled`. Cargan los archivos `*.conf` de `/etc/nginx/conf.d/`. ## Paso 2: Abrir los puertos en el firewall QUIC usa UDP, así que además de los puertos TCP habituales necesitas el UDP 443: ```bash sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 443/udp sudo ufw status ``` ```output Status: active To Action From -- ------ ---- 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere 443/udp ALLOW Anywhere ... ``` Olvidar el UDP 443 es la causa más habitual de que HTTP/3 "no funcione": el sitio carga igual por TCP y el fallo pasa desapercibido. ## Paso 3: Obtener un certificado TLS QUIC exige TLS 1.3 y un certificado válido. Instala Certbot: ```bash sudo apt install certbot python3-certbot-nginx ``` Crea un bloque HTTP mínimo para tu dominio. Primero desactiva el sitio por defecto del paquete: ```bash sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled sudo nano /etc/nginx/conf.d/your_domain.conf ``` ```nginx server { listen 80; listen [::]:80; server_name your_domain; root /usr/share/nginx/html; } ``` Recarga Nginx y pide el certificado. Con `certonly` Certbot solo obtiene el certificado y no modifica tu configuración, que escribirás a mano en el siguiente paso: ```bash sudo nginx -t && sudo systemctl reload nginx sudo certbot certonly --nginx -d your_domain ``` ```output Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem Key is saved at: /etc/letsencrypt/live/your_domain/privkey.pem ``` Certbot instala un temporizador de systemd que renueva el certificado automáticamente. ## Paso 4: Configurar HTTP/3 en Nginx Sustituye el contenido de `/etc/nginx/conf.d/your_domain.conf`: ```bash sudo nano /etc/nginx/conf.d/your_domain.conf ``` ```nginx server { listen 443 quic reuseport; listen [::]:443 quic reuseport; listen 443 ssl; listen [::]:443 ssl; http2 on; server_name your_domain; root /usr/share/nginx/html; ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; add_header Alt-Svc 'h3=":443"; ma=86400' always; } server { listen 80; listen [::]:80; server_name your_domain; return 301 https://$host$request_uri; } ``` Qué hace cada parte: - `listen 443 quic reuseport`: escucha QUIC en el UDP 443. `reuseport` reparte los paquetes entre los procesos worker de forma que cada conexión QUIC llegue siempre al mismo worker. Solo puede aparecer en un bloque `server` por cada combinación de dirección y puerto: si alojas más dominios, en los demás pon `listen 443 quic;` sin `reuseport`. - `listen 443 ssl` y `http2 on`: mantienen HTTPS por TCP para la primera conexión y para clientes sin HTTP/3. - `ssl_protocols`: QUIC usa siempre TLS 1.3, TLSv1.2 queda solo para clientes TCP antiguos. - `add_header Alt-Svc`: anuncia HTTP/3. `always` hace que se envíe también en respuestas de error. `ma=86400` indica al navegador que recuerde el anuncio durante un día. Comprueba la sintaxis y recarga: ```bash sudo nginx -t sudo systemctl reload nginx ``` ```output nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` > Nota: si usas `add_header` dentro de un bloque `location`, Nginx deja de heredar los `add_header` del nivel `server`. Repite la línea `Alt-Svc` en esos bloques. ## Paso 5: Comprobar que HTTP/3 funciona Primero confirma que Nginx escucha en el UDP 443: ```bash sudo ss -ulpn 'sport = :443' ``` ```output State Recv-Q Send-Q Local Address:Port Peer Address:Port Process UNCONN 0 0 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=2311,fd=6),...) UNCONN 0 0 [::]:443 [::]:* users:(("nginx",pid=2311,fd=7),...) ``` Después comprueba desde tu equipo que el servidor envía la cabecera `Alt-Svc`: ```bash curl -sI https://your_domain | grep -i alt-svc ``` ```output alt-svc: h3=":443"; ma=86400 ``` El `curl` de Ubuntu 24.04 no está compilado con soporte HTTP/3, así que la prueba final se hace con el navegador: 1. Abre `https://your_domain` en Chrome o Firefox y abre las herramientas de desarrollo (F12), pestaña **Red**. 2. Haz clic derecho en la cabecera de las columnas y activa **Protocolo**. 3. Recarga la página dos veces. La primera carga puede ir por `h2`, porque es la que recibe el anuncio `Alt-Svc`. En las siguientes debe aparecer `h3`. También puedes registrar el protocolo en el log de acceso. Añade este formato en el bloque `http` de `/etc/nginx/nginx.conf`: ```nginx log_format proto '$remote_addr [$time_local] "$request" $status $server_protocol'; ``` Y dentro del bloque `server` de tu dominio: ```nginx access_log /var/log/nginx/your_domain.access.log proto; ``` Tras recargar Nginx y navegar por el sitio, las peticiones por QUIC aparecen como `HTTP/3.0`: ```bash sudo tail -n 3 /var/log/nginx/your_domain.access.log ``` ```output 203.0.113.25 [25/Sep/2026:10:14:02 +0000] "GET / HTTP/3.0" 200 HTTP/3.0 203.0.113.25 [25/Sep/2026:10:14:02 +0000] "GET /favicon.ico HTTP/3.0" 404 HTTP/3.0 ``` ## Alternativa: HTTP/3 con Caddy Caddy activa HTTP/3 automáticamente en todos los sitios con HTTPS, sin configuración adicional. Es una alternativa a Nginx, no un complemento: ambos usan los puertos 80 y 443, así que úsalo en un servidor sin Nginx o detén Nginx antes con `sudo systemctl disable --now nginx`. Instálalo desde su repositorio oficial: ```bash sudo apt install debian-keyring debian-archive-keyring apt-transport-https curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy ``` Edita `/etc/caddy/Caddyfile` con un sitio mínimo que sirve la página de bienvenida incluida en el paquete: ```bash sudo nano /etc/caddy/Caddyfile ``` ```caddy your_domain { root * /usr/share/caddy file_server } ``` Recarga Caddy. Obtendrá el certificado de Let's Encrypt, servirá HTTP/1.1, HTTP/2 y HTTP/3 y enviará la cabecera `Alt-Svc` por sí mismo: ```bash sudo systemctl reload caddy ``` Caddy usa la biblioteca quic-go, que recomienda buffers UDP mayores que los que trae el kernel por defecto. Si ves el aviso `failed to sufficiently increase receive buffer size` en `journalctl -u caddy`, auméntalos: ```bash printf "net.core.rmem_max=7500000\nnet.core.wmem_max=7500000\n" | sudo tee /etc/sysctl.d/60-quic-buffers.conf sudo sysctl --system sudo systemctl restart caddy ``` Recuerda abrir también el UDP 443 con UFW, igual que en el paso 2. ## Solución de problemas - **El navegador siempre usa `h2`.** Comprueba que el UDP 443 está abierto en UFW y en cualquier firewall de red, que la cabecera `Alt-Svc` llega (el `curl -sI` del paso 5) y que no hay otro proceso escuchando en el UDP 443. Algunas redes corporativas bloquean QUIC; prueba desde otra conexión. - **`nginx: [emerg] invalid parameter "quic"`.** Estás ejecutando un Nginx sin el módulo HTTP/3, normalmente el de Ubuntu. Revisa `nginx -V` y el pin del paso 1. - **`duplicate listen options for 0.0.0.0:443`.** Has puesto `reuseport` en más de un bloque `server` para el mismo puerto. Déjalo solo en uno. - **HTTP/3 funciona por IPv4 pero no por IPv6.** Falta la línea `listen [::]:443 quic` o la regla de UFW para IPv6. Revisa con `sudo ufw status` que aparece `443/udp (v6)`. ## Conclusión Tu servidor atiende ahora HTTP/3 sobre QUIC en el UDP 443 y lo anuncia con `Alt-Svc`, manteniendo HTTP/2 por TCP para los clientes que no pueden usar UDP. Como siguientes pasos, puedes activar HSTS cuando todo tu sitio funcione por HTTPS, usar el log con `$server_protocol` para medir qué porcentaje de tráfico llega por HTTP/3 y aplicar la misma configuración a los bloques `server` que hagan de proxy inverso hacia tus aplicaciones.