--- title: "Cómo configurar la caché HTTP de HAProxy en Ubuntu 24.04" description: "Activa la caché HTTP integrada de HAProxy en Ubuntu 24.04: define la sección cache, controla el TTL, excluye rutas privadas y comprueba los aciertos con curl." category: "Caché y CDN" language: es source: https://cubepath.com/es/docs/caché-y-cdn/configuracion-de-cache-en-haproxy updated: 2026-09-25 --- # Cómo configurar la caché HTTP de HAProxy en Ubuntu 24.04 HAProxy incluye una caché HTTP en memoria que guarda las respuestas de los backends y las sirve directamente, sin herramientas adicionales como Varnish. Está pensada como una caché pequeña y rápida (a veces llamada *favicon cache*) para recursos que se piden mucho y cambian poco. En este tutorial activarás la caché en HAProxy sobre Ubuntu 24.04, ajustarás el tiempo de vida de las entradas, excluirás las rutas que no deben cachearse y verificarás los aciertos. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Una aplicación HTTP escuchando en `127.0.0.1:8080`. Si no tienes una, el paso 2 levanta un backend de prueba. - Conocimientos básicos de la estructura de `haproxy.cfg` (`frontend`, `backend`). ## Paso 1: Instalar HAProxy Ubuntu 24.04 incluye HAProxy 2.8, una versión LTS con la caché completa. Instálalo junto con `socat`, que usarás para consultar el estado de la caché: ```bash sudo apt update sudo apt install haproxy socat haproxy -v | head -n 1 ``` ```output HAProxy version 2.8.x 2024/xx/xx - https://haproxy.org/ ``` > Nota: si necesitas una versión más reciente, el PPA `ppa:vbernat/haproxy-3.2` mantiene paquetes de HAProxy 3.2 LTS para Ubuntu 24.04. La configuración de esta guía es válida en ambas. ## Paso 2: Levantar un backend de prueba Si ya tienes tu aplicación en el puerto 8080, salta este paso. Si no, sirve un directorio con Python en otra sesión SSH: ```bash mkdir -p ~/backend-demo/static echo '

Hola desde el backend

' > ~/backend-demo/index.html echo 'body { color: #333; }' > ~/backend-demo/static/app.css python3 -m http.server 8080 --bind 127.0.0.1 --directory ~/backend-demo ``` Este servidor envía la cabecera `Last-Modified`, que HAProxy necesita para considerar la respuesta cacheable cuando no hay `Cache-Control`. ## Paso 3: Entender qué cachea HAProxy Antes de configurar nada conviene saber las reglas, porque son más estrictas que las de Nginx o Varnish. HAProxy **solo** guarda una respuesta cuando se cumple todo lo siguiente: | Condición | Detalle | |---|---| | Método | Solo `GET`. | | Versión HTTP | La petición debe ser HTTP/1.1 o superior. | | Código de estado | Solo `200`. | | Autorización | La petición no puede llevar cabecera `Authorization`. | | Caducidad | La respuesta debe tener `Cache-Control: max-age` o `s-maxage`, `Expires`, o un validador (`ETag` o `Last-Modified`). | | Tamaño | Cabeceras más cuerpo no deben superar `max-object-size`. | | `Vary` | Sin `process-vary on`, las respuestas con `Vary` no se cachean. | Además, la caché vive en memoria compartida y se pierde al reiniciar HAProxy. Un `reload` también empieza con la caché vacía. ## Paso 4: Definir la caché y activarla El archivo `/etc/haproxy/haproxy.cfg` de Ubuntu ya trae las secciones `global` y `defaults`, con el socket de administración en `/run/haproxy/admin.sock`. Haz una copia y ábrelo: ```bash sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig sudo nano /etc/haproxy/haproxy.cfg ``` Añade al final del archivo, sin tocar lo que ya hay: ```text cache app_cache total-max-size 256 max-object-size 1048576 max-age 300 frontend web bind :80 mode http default_backend app http-response set-header X-Cache-Status HIT if { res.cache_hit } http-response set-header X-Cache-Status MISS if !{ res.cache_hit } backend app mode http http-request cache-use app_cache http-response cache-store app_cache server app1 127.0.0.1:8080 check ``` Qué hace cada parte: - `total-max-size 256` reserva 256 MB de RAM para la caché. El valor se expresa en megabytes y el máximo es 4095. - `max-object-size 1048576` limita cada objeto a 1 MB. Se expresa en bytes y no puede superar la mitad de `total-max-size`. Los objetos más grandes simplemente no se cachean. - `max-age 300` es el tiempo máximo en segundos. Si el backend indica un `max-age` menor, se usa el del backend; si indica uno mayor, se recorta a 300. Si no se configura, el valor por defecto es 60 segundos. - `cache-use` busca la respuesta en la caché antes de enviar la petición al servidor y `cache-store` guarda la respuesta al volver. - La muestra `res.cache_hit` indica si la respuesta salió de la caché. Se usa en el `frontend` para añadir la cabecera `X-Cache-Status` de diagnóstico. Valida la configuración antes de aplicarla: ```bash sudo haproxy -c -f /etc/haproxy/haproxy.cfg ``` ```output Configuration file is valid ``` Recarga el servicio: ```bash sudo systemctl reload haproxy sudo systemctl status haproxy --no-pager ``` ## Paso 5: Comprobar que la caché funciona Pide la misma página dos veces: ```bash curl -s -o /dev/null -D - http://127.0.0.1/ | grep -iE 'x-cache-status|^age' curl -s -o /dev/null -D - http://127.0.0.1/ | grep -iE 'x-cache-status|^age' ``` ```output X-Cache-Status: MISS X-Cache-Status: HIT age: 3 ``` HAProxy añade la cabecera `Age` a las respuestas servidas desde caché, con los segundos que lleva almacenada la entrada. En la terminal del backend de prueba verás que solo llegó la primera petición. Consulta el contenido de la caché a través del socket de administración: ```bash echo "show cache" | sudo socat stdio /run/haproxy/admin.sock ``` La salida muestra, para cada caché, los bloques libres y las entradas almacenadas con su tamaño y el tiempo que les queda de vida. ## Paso 6: Controlar el TTL y excluir rutas En una aplicación real no todo debe cachearse igual. Un patrón habitual es cachear solo los recursos estáticos, con un TTL largo, y dejar pasar el resto. Edita el backend: ```bash sudo nano /etc/haproxy/haproxy.cfg ``` Sustituye la sección `backend app` por esta versión: ```text backend app mode http acl es_estatico path_beg /static/ acl es_estatico path_end .css .js .png .jpg .svg .woff2 acl sesion req.cook(sessionid) -m found http-request set-var(txn.cacheable) bool(true) if es_estatico !sesion http-request cache-use app_cache if { var(txn.cacheable) -m bool } http-response set-header Cache-Control "public, max-age=300" if { var(txn.cacheable) -m bool } !{ res.hdr(Cache-Control) -m found } http-response cache-store app_cache if { var(txn.cacheable) -m bool } server app1 127.0.0.1:8080 check ``` Cómo funciona: - Las ACL `es_estatico` se definen dos veces con el mismo nombre; HAProxy las combina con un OR, así que basta con que se cumpla una. - La variable `txn.cacheable` se marca al recibir la petición cuando es un recurso estático y no lleva la cookie de sesión `sessionid` (sustitúyela por la de tu aplicación). Es necesaria porque las muestras de la petición, como `path` o `req.cook`, no están disponibles en las reglas `http-response`: HAProxy avisaría de que la ACL nunca coincide. Las variables con ámbito `txn` duran toda la transacción y sí se pueden leer en la respuesta. - `cache-use` y `cache-store` solo actúan sobre las peticiones marcadas. El resto va siempre al backend y nunca se guarda. - Si el backend no envía `Cache-Control` para un recurso estático, HAProxy le añade `max-age=300` antes de guardarlo. Las reglas `http-response` se evalúan en orden, por eso la línea `set-header` va antes de `cache-store`. Valida y recarga: ```bash sudo haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy ``` Comprueba que el CSS se cachea y la página principal no: ```bash curl -s -o /dev/null -D - http://127.0.0.1/static/app.css | grep -i x-cache-status curl -s -o /dev/null -D - http://127.0.0.1/static/app.css | grep -i x-cache-status curl -s -o /dev/null -D - http://127.0.0.1/ | grep -i x-cache-status curl -s -o /dev/null -D - http://127.0.0.1/ | grep -i x-cache-status ``` ```output X-Cache-Status: MISS X-Cache-Status: HIT X-Cache-Status: MISS X-Cache-Status: MISS ``` ## Paso 7 (opcional): Respuestas con cabecera Vary Si tu backend comprime las respuestas y envía `Vary: Accept-Encoding`, HAProxy no las cacheará salvo que actives la gestión de variantes. Añade estas líneas a la sección `cache app_cache`: ```text process-vary on max-secondary-entries 10 ``` Con `process-vary on`, HAProxy guarda una variante por cada valor distinto de las cabeceras que sabe gestionar, como `Accept-Encoding`. Si el backend usa `Vary` con otras cabeceras (por ejemplo `Cookie` o `User-Agent`), esas respuestas siguen sin cachearse, lo cual es el comportamiento correcto. `max-secondary-entries` limita cuántas variantes se guardan de una misma URL. Valida y recarga de nuevo con `sudo haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy`. ## Paso 8: Abrir el puerto en el firewall Si HAProxy va a recibir tráfico desde internet, permite el puerto 80 (y el 443 cuando configures TLS): ```bash sudo ufw allow 80/tcp sudo ufw allow 443/tcp ``` Para HTTPS, concatena certificado y clave privada en un único archivo PEM y añade `bind :443 ssl crt /etc/haproxy/certs/your_domain.pem` al `frontend`. La caché funciona igual con tráfico cifrado porque HAProxy termina el TLS. ## Solución de problemas **Siempre `MISS`.** Revisa la tabla del paso 3 contra las cabeceras reales del backend con `curl -sI http://127.0.0.1:8080/ruta`. Las causas más frecuentes son un código distinto de `200`, falta de `Cache-Control`, `Expires` y validadores, una cabecera `Vary` o un cuerpo mayor que `max-object-size`. **`haproxy -c` rechaza `max-object-size`.** El valor no puede superar la mitad de `total-max-size`. Reduce uno o aumenta el otro, y recuerda que `max-object-size` va en bytes y `total-max-size` en megabytes. **La caché se vacía sola.** Cada `systemctl reload` o `restart` arranca con la caché vacía. Es normal: la caché de HAProxy es solo en memoria y está pensada para objetos de vida corta. **`show cache` devuelve `Permission denied`.** Ejecuta `socat` con `sudo`, o añade tu usuario al grupo `haproxy`, dueño del socket. ## Conclusión HAProxy ya cachea en memoria los recursos estáticos de tu aplicación, respeta el TTL que envía el backend con un máximo de 300 segundos y deja pasar las peticiones con sesión. Como siguientes pasos puedes añadir más servidores al `backend` para balancear carga, activar la página de estadísticas de HAProxy para vigilar el tráfico o colocar Varnish o una CDN delante si necesitas una caché grande en disco con purga selectiva.