---
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.