TL;DR — Resumen Rápido
Guía completa de Caddy como proxy inverso con HTTPS automático. Configura SSL sin esfuerzo, balanceo de carga, verificaciones de salud y hosting multi-sitio.
Caddy es un servidor web en Go que convierte el HTTPS automático en el comportamiento predeterminado, no en una tarea adicional. A diferencia de Nginx o Apache donde TLS implica instalar certbot, escribir scripts de renovación y depurar cron jobs, Caddy negocia certificados con Let’s Encrypt o ZeroSSL en el momento en que agregas un dominio a tu configuración.
Requisitos Previos
- Un servidor Linux (Ubuntu 22.04/24.04, Debian, RHEL o Docker).
- Un dominio con registros DNS A apuntando a la IP pública de tu servidor.
- Puertos 80 y 443 abiertos en el firewall — Caddy los necesita para el desafío ACME HTTP-01.
- Servicios backend ejecutándose en puertos localhost (Node.js, Python, PHP, etc.).
Arquitectura de Caddy
Caddy es un binario estático único escrito en Go sin dependencias de tiempo de ejecución.
HTTPS automático via ACME. Cuando configuras un dominio, Caddy:
- Detecta que el dominio requiere un certificado.
- Ejecuta un desafío ACME HTTP-01 o TLS-ALPN-01.
- Almacena el certificado en
~/.local/share/caddy/(o/var/lib/caddy/para instalaciones del sistema). - Programa la renovación 30 días antes del vencimiento — automáticamente.
- Adjunta respuestas OCSP a los handshakes TLS para verificaciones más rápidas de revocación.
API de administración. Caddy expone una API REST en localhost:2019 para cambios de configuración en vivo — sin necesidad de reiniciar.
Instalación
apt (Ubuntu/Debian — recomendado)
sudo apt install -y 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
Docker
docker run -d \
--name caddy \
-p 80:80 -p 443:443 -p 443:443/udp \
-v $PWD/Caddyfile:/etc/caddy/Caddyfile \
-v caddy_data:/data \
caddy:latest
xcaddy — Compilaciones Personalizadas con Plugins
xcaddy build \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-ratelimit
Sintaxis del Caddyfile
Bloques de sitio:
example.com {
reverse_proxy localhost:3000
}
Opciones globales:
{
email admin@example.com
}
Fragmentos reutilizables:
(cabeceras_comunes) {
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
-Server
}
}
example.com {
import cabeceras_comunes
reverse_proxy localhost:3000
}
Configuración del Proxy Inverso
Proxy Inverso Básico
example.com {
reverse_proxy localhost:3000
}
Caddy gestiona automáticamente la redirección HTTP→HTTPS, la emisión del certificado, la renovación y el grapado OCSP.
Balanceo de Carga
example.com {
reverse_proxy app1:3000 app2:3000 app3:3000 {
lb_policy round_robin
}
}
| Política | Descripción |
|---|---|
round_robin | Distribuye solicitudes uniformemente entre backends |
least_conn | Dirige al backend con menos conexiones activas |
ip_hash | Hash de IP del cliente para sesiones fijas |
cookie | Usa una cookie para persistencia de sesión |
uri_hash | Hash de la URI de la solicitud |
Verificaciones de Salud Activas y Pasivas
example.com {
reverse_proxy app1:3000 app2:3000 {
lb_policy least_conn
health_uri /health
health_interval 10s
health_timeout 5s
fail_duration 30s
max_fails 3
}
}
Manipulación de Cabeceras
example.com {
reverse_proxy localhost:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
header_down -Server
header_down -X-Powered-By
}
}
HTTPS Automático en Profundidad
Cómo Caddy Obtiene Certificados
- Llega una solicitud para
example.com. - Caddy verifica su almacén de certificados — no se encuentra ninguno.
- Caddy ejecuta un desafío ACME HTTP-01.
- El servidor ACME (Let’s Encrypt) verifica el token.
- Caddy recibe el certificado firmado y lo almacena.
- HTTP redirige automáticamente a HTTPS.
- Caddy renueva el certificado 30 días antes del vencimiento.
TLS Bajo Demanda
Para plataformas SaaS donde los usuarios agregan dominios personalizados:
{
on_demand_tls {
ask http://localhost:8080/verificar-dominio
interval 2m
burst 5
}
}
CA Interna para Desarrollo Local
localhost {
tls internal
reverse_proxy localhost:3000
}
Ejecuta caddy trust para instalar la CA local de Caddy en el almacén de confianza del sistema.
Patrones Comunes del Caddyfile
SPA con Enrutamiento del Lado del Cliente
app.example.com {
root * /var/www/app
try_files {path} /index.html
file_server
}
PHP con PHP-FPM
php.example.com {
root * /var/www/php-app
php_fastcgi unix//run/php/php8.3-fpm.sock
file_server
}
Servidor de Archivos Estáticos con Compresión
files.example.com {
root * /var/www/archivos
encode gzip zstd
file_server browse
}
Caddy vs Nginx vs Traefik vs HAProxy
| Característica | Caddy | Nginx | Traefik | HAProxy |
|---|---|---|---|---|
| HTTPS automático | Integrado, predeterminado | Manual (certbot) | Integrado | Manual |
| Sintaxis de configuración | Simple Caddyfile | Complejo nginx.conf | YAML/TOML | Complejo |
| Recarga en tiempo real | Sí (API + señal) | Sí (señal) | Sí | Sí |
| Balanceo de carga | 8 políticas | Round-robin, IP hash | Múltiples | Extenso |
| API de administración | REST JSON | No | REST JSON | Socket |
| HTTP/3 (QUIC) | Sí | Sí (v1.25+) | Sí | No |
| Mejor para | HTTPS automático, simplicidad | Archivos estáticos de alto rendimiento | Docker/K8s | Balanceo TCP |
Caddyfile de Producción: Hosting Multi-Sitio
{
email ops@example.com
admin localhost:2019
}
(cabeceras_seguridad) {
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy strict-origin-when-cross-origin
-Server
}
}
app.example.com {
import cabeceras_seguridad
encode gzip zstd
reverse_proxy app1:3000 app2:3000 {
lb_policy least_conn
health_uri /health
health_interval 15s
fail_duration 30s
}
}
api.example.com {
import cabeceras_seguridad
reverse_proxy localhost:8080 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
www.example.com {
import cabeceras_seguridad
encode gzip zstd
root * /var/www/marketing
try_files {path} /index.html
file_server
}
example.com {
redir https://www.example.com{uri} 301
}
Errores Comunes y Casos Especiales
- El puerto 80 debe ser accesible. Caddy usa el desafío ACME HTTP-01. Si el puerto 80 está bloqueado, usa el desafío DNS-01 con un plugin DNS via xcaddy.
- Límites de tasa en Let’s Encrypt. Máximo 50 certificados por dominio por semana. Usa la CA de staging durante las pruebas.
header_up Hostpuede romper algunos backends. Prueba primero sin esta directiva.- La API de administración es solo localhost por defecto. Nunca expongas el puerto 2019 públicamente.
- Recarga vs reinicio. Usa siempre
systemctl reload caddyen producción para evitar tiempo de inactividad.
Resumen
- HTTPS automático — Caddy obtiene y renueva certificados de Let’s Encrypt/ZeroSSL sin configuración.
- Sintaxis simple — Cinco líneas en el Caddyfile reemplazan cientos de líneas de configuración de Nginx.
- 8 políticas de balanceo de carga — incluyendo sesiones fijas via cookie e IP hash.
- Verificaciones de salud activas y pasivas — elimina y re-agrega backends fallidos automáticamente.
- TLS bajo demanda — emite certificados dinámicamente para dominios de usuarios.
- API REST de administración — cambios de configuración en vivo en
localhost:2019sin reinicios.