Por qué cuidar su reverse proxy en un VPS
En un VPS, el servidor web frontal es la pieza que lo orquesta todo: termina el TLS, distribuye el tráfico hacia sus contenedores (aplicación, forja, servidor multimedia, LLM), sirve los archivos estáticos y aplica las cabeceras de seguridad. Bien elegido, simplifica radicalmente el paso a HTTPS de todos sus subdominios. Caddy obtiene y renueva los certificados Let's Encrypt automáticamente, sin configuración, con un archivo Caddyfile legible de unas pocas líneas. Nginx, referencia del mercado, ofrece un control extremadamente fino (caché, reglas de reescritura, balanceo de carga, rate limiting) pero exige una gestión manual o mediante Certbot de los certificados. La elección enfrenta el automatismo moderno al dominio total y contrastado.
Lo que un buen frontal aporta a su VPS
- Terminación TLS centralizada para todos sus subdominios
- Reverse proxy único hacia varios contenedores Docker
- Servicio de archivos estáticos rápido y compresión (gzip/brotli)
- Cabeceras de seguridad (HSTS, CSP, X-Content-Type-Options) aplicadas en un mismo punto
- Con Caddy: certificados Let's Encrypt obtenidos y renovados automáticamente
- Con Nginx: caché, rate limiting y balanceo de carga ajustados al detalle
- HTTP/3 y QUIC para reducir la latencia en conexiones degradadas
Requisitos: un frontal frugal
Un reverse proxy es muy ligero: tanto Caddy como Nginx funcionan con holgura en 1 vCPU y de 512 MB a 1 GB de RAM, incluso como frontal de varios servicios. El recurso que hay que vigilar es más bien el ancho de banda y el número de conexiones simultáneas. Necesita un dominio y sus subdominios apuntando a la IP del VPS (registros A/AAAA), los puertos 80 y 443 abiertos en el cortafuegos (el puerto 80 es necesario para la validación de los certificados) y Docker si contenedoriza el proxy. Ni GPU ni gran almacenamiento: aquí es la configuración la que marca la diferencia, no la potencia bruta.
Implementar Caddy (o Nginx) como reverse proxy
Apuntar los DNS
Cree los registros A (y AAAA si usa IPv6) para cada subdominio (app, git, media) hacia la IP del VPS. La validación de Let's Encrypt fallará mientras la resolución DNS no sea efectiva, así que compruébela antes con
dig app.yourdomain.como una herramienta en línea.Abrir los puertos 80 y 443
Autorice únicamente el 80 y el 443 en el cortafuegos (
ufw allow 80/tcp && ufw allow 443/tcp). El puerto 80 sigue siendo imprescindible para el desafío HTTP de Let's Encrypt y para redirigir automáticamente el tráfico hacia HTTPS.Redactar la configuración base
Con Caddy basta un bloque:
app.yourdomain.com { reverse_proxy 127.0.0.1:3000 }y el HTTPS es automático. Con Nginx, escriba un bloqueserverpor subdominio conproxy_passy las cabecerasX-Forwarded-*, y luego obtenga el certificado mediante Certbot:certbot --nginx -d app.yourdomain.com.Configurar varios subdominios
Con Caddy, liste cada bloque en el mismo
Caddyfile:git.yourdomain.com { reverse_proxy 127.0.0.1:3001 }. Con Nginx, cree un archivo por subdominio en/etc/nginx/conf.d/o/etc/nginx/sites-available/, y actívelo conln -s. Ambos enfoques permiten gestionar docenas de servicios sin repetición.Activar la compresión
Caddy activa gzip por defecto; para añadir brotli:
encode zstd br gzipen el bloque del sitio. En Nginx, añada anginx.conf:gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 256;. La compresión reduce el tamaño de las respuestas de texto entre un 60 y un 80% en la mayoría de los casos.Arrancar y recargar sin cortes
Inicie el servicio (
docker compose up -dosystemctl start caddy). Después de cada modificación, valide la configuración (nginx -tocaddy validate) y luego recargue en caliente (nginx -s reload/caddy reload) para no interrumpir nunca el tráfico.Verificar los certificados
Con Caddy, ejecute
caddy validate --config /etc/caddy/Caddyfilepara detectar errores antes de recargar, y consulte los logs (journalctl -u caddy -f) para confirmar la emisión del certificado. Con Nginx + Certbot,certbot certificateslista las fechas de vencimiento ycertbot renew --dry-runsimula la renovación.Reforzar la seguridad e implementar los logs
Active HSTS, oculte la versión del servidor (
server_tokens offen Nginx, automático en Caddy), fuerce TLS 1.2+ y añada un rate limiting básico. Active los logs de acceso y de error, y vigile los códigos 502/504 que revelan un contenedor inalcanzable detrás.
Una vez que el proxy está operativo y los certificados han sido emitidos, dos pasos complementarios refuerzan la seguridad y el rendimiento: la configuración avanzada de cabeceras y del rate limiting, y la implantación del monitoreo. El orden importa: valide primero que el enrutado básico funciona (curl -I https://app.yourdomain.com) antes de añadir capas de configuración.
Configuración avanzada: seguridad, compresión y HTTP/3
Una vez establecida la base, tres áreas mejoran concretamente la postura de su reverse proxy.
Cabeceras de seguridad. Aplique a nivel del proxy las cabeceras que cada servicio posterior olvidará: Strict-Transport-Security: max-age=31536000; includeSubDomains (HSTS), X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN y una Content-Security-Policy adaptada a su aplicación. Centralizar estas cabeceras en el proxy garantiza que cubran todos sus subdominios de un solo gesto.
Rate limiting. En Caddy, el módulo rate_limit (disponible mediante xcaddy build) permite acotar las peticiones por IP. En Nginx, la directiva limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m; en http {} y luego limit_req zone=api burst=10 nodelay; en el location correspondiente son suficientes para proteger una API contra abusos sin dependencias externas.
HTTP/3 y QUIC. Caddy activa HTTP/3 por defecto en cuanto el puerto UDP 443 está abierto. Nginx admite QUIC desde la rama mainline (parámetro quic en el bloque listen); compruebe la versión instalada con nginx -v antes de activar la directiva. HTTP/3 reduce la latencia percibida en conexiones móviles y redes con alta pérdida de paquetes, sin ningún cambio de comportamiento para los clientes que no lo admiten.
Caddy vs Nginx — tabla comparativa
Desplace la tabla
| Criterio | Caddy | Nginx |
|---|---|---|
| HTTPS / certificados | Automático, cero configuración | Manual o mediante Certbot |
| Sintaxis de configuración | Caddyfile, muy conciso | Más verbosa, muy expresiva |
| Curva de aprendizaje | Baja | De moderada a alta |
| Control fino (caché, rewrite, LB) | Bueno, a veces mediante plugins | Muy completo y contrastado |
| HTTP/3 / QUIC | Activo por defecto | Compatible (rama mainline) |
| Rate limiting nativo | Mediante módulo xcaddy | Integrado (`limit_req`) |
| Módulos dinámicos | Compilación mediante xcaddy | Módulos dinámicos (.so) |
| Uso de RAM en reposo | ~30–50 MB | ~20–40 MB (workers) |
| Formato de logs | JSON estructurado por defecto | Texto, configurable |
| Ideal para | Pasar rápido a HTTPS, multisubdominio | Ajustes avanzados, mucho tráfico |
Los pasos de despliegue cubren la configuración ideal. En la práctica, varios tipos de errores aparecen con regularidad: un certificado bloqueado por una red intermedia, un servicio posterior que todavía no responde, o un contenedor Docker inaccesible desde el proxy porque ambos están en redes distintas. El panel más útil en estas situaciones es el log del proxy (journalctl -u caddy -f o tail -f /var/log/nginx/error.log), combinado con curl en local para aislar el problema.
Resolución de problemas: los errores más frecuentes
Incluso un proxy bien configurado produce errores al arrancar o bajo carga. Aquí están los cinco casos que aparecen con más frecuencia.
Caddy — «no certificate» detrás de un balanceador de carga. Cuando Caddy está detrás de un balanceador que ya termina el TLS, no puede recibir el desafío HTTP-01 de Let's Encrypt y falla al emitir el certificado. Solución: usar el desafío DNS-01 mediante el plugin de su registrar (p. ej. tls { dns cloudflare {env.CF_API_TOKEN} }), o delegar completamente la gestión del TLS al balanceador y forzar que Caddy funcione en http:// internamente.
Nginx — 502 Bad Gateway (timeout de upstream). Un 502 persistente tras el arranque indica que el servicio posterior no está escuchando aún o ha fallado. Compruebe con curl -v http://127.0.0.1:<puerto> desde el servidor. Si el servicio tarda en arrancar, aumente proxy_read_timeout y proxy_connect_timeout. Un 502 intermitente bajo carga apunta a una falta de conexiones keepalive: añada keepalive 32; en el bloque upstream.
Caddy con Docker — contenedor inaccesible. Cuando Caddy y el servicio destino corren en redes Docker distintas, reverse_proxy 127.0.0.1:3000 no funciona: 127.0.0.1 es la dirección de loopback del contenedor Caddy, no del host. Solución: conecte ambos contenedores a la misma red Docker bridge con nombre y use el nombre del servicio como dirección destino: reverse_proxy nombre-del-servicio:3000.
Nginx — «too many open files» bajo carga. El error worker_connections are not enough o open() failed (24: Too many open files) aparece cuando el VPS recibe un pico de tráfico. Aumente el límite del sistema (ulimit -n 65535 o DefaultLimitNOFILE=65535 en la unit systemd) y alinee worker_connections 4096; en nginx.conf. El máximo de conexiones simultáneas es worker_processes * worker_connections.
Caddy — renovación bloqueada en silencio. Caddy renueva en segundo plano, pero si el puerto UDP 443 está cerrado por el cortafuegos, HTTP/3 falla y los logs pueden enmascarar la causa real. Monitorice journalctl -u caddy -f en torno a las fechas de renovación (60 días tras la emisión) y pruebe el desafío con caddy run --config /etc/caddy/Caddyfile --watch en primer plano para ver los errores en tiempo real.
Caddy, Nginx o Traefik: la tercera opción
Para una infraestructura con numerosos microservicios Docker y descubrimiento automático de contenedores, Traefik emerge como tercera opción: lee las etiquetas Docker (traefik.http.routers.myapp.rule=Host("app.yourdomain.com")) y configura las rutas al vuelo sin recargas manuales. El inconveniente es su configuración más compleja y su documentación más densa. Caddy y Nginx siguen siendo las opciones naturales para un VPS de tamaño razonable (1 a 20 servicios); Traefik toma el relevo más allá, en especial en un contexto de Kubernetes o Docker Swarm. Para una comparación completa de los tres, consulte el artículo elegir su reverse proxy para VPS: Caddy, Traefik o Nginx.
Combinar ambos en lugar de elegir
Si todavía duda, sepa que Caddy y Nginx no se excluyen. Un patrón habitual coloca Caddy como primer frontal para gestionar automáticamente el TLS de todos sus subdominios, y deja Nginx detrás para la caché fina y las reglas de reescritura de un servicio concreto. Así combina el automatismo de los certificados con el dominio del ajuste, sin elegir un bando definitivo.