Caddy Server es un servidor web de código abierto que pone HTTPS a sus sitios sin que usted se lo pida: consigue el certificado, lo renueva y redirige las visitas. Además, Caddy funciona como proxy inverso, o reverse proxy, y se configura con un archivo de texto muy corto, el Caddyfile. Por eso se ha vuelto una alternativa frecuente a Nginx y Apache cuando se quiere menos configuración. En esta guía verá cómo instalar Caddy, cómo escribir su configuración y cómo resolver sus errores más buscados.
Esta guía sirve a dos lectores. Si usted decide en una empresa, le bastan los apartados sobre qué es, para qué sirve, qué beneficios trae y qué límites tiene. Si administra los sistemas, además encontrará el sistema base, las arquitecturas soportadas, la instalación, la configuración básica, los comandos más comunes, varios escenarios de ejemplo y los errores frecuentes.
Por otra parte, no nos quedamos en la documentación. Instalamos la versión vigente, la 2.11.7, en un entorno aislado y la medimos con peticiones reales. Así comprobamos cinco cosas que conviene saber antes de usarlo. Primero, un archivo con errores no tumba nada: Caddy lo rechaza y sigue con la configuración anterior. Segundo, sin dos líneas adicionales, un servidor caído se lleva la mitad de las visitas. Tercero, recargar no detiene el servicio, pero cierra algunas conexiones abiertas. Cuarto, los certificados se renuevan cuando les queda un tercio de vida, sin cortar nada. Y quinto, varias protecciones que muchos dan por incluidas no vienen activadas.
Qué es Caddy Server y para qué sirve
Caddy Server es un programa gratuito y de código abierto que cumple dos papeles. Por un lado, es un servidor web: entrega las páginas y los archivos de un sitio. Por otro, es un proxy inverso: recibe las visitas y las pasa a las aplicaciones que usted tiene detrás. En ambos casos cifra la conexión con HTTPS sin configuración adicional.
Su documentación lo presenta como el primer servidor web que usó HTTPS de forma automática y por defecto. De hecho, esa es su mayor diferencia frente a Nginx o Apache. En ellos, el certificado se pide y se renueva con otra herramienta o con un módulo que hay que activar.
Explicado sin tecnicismos
Piense en la recepción de una empresa. El recepcionista entrega los folletos que le piden, anuncia a cada visitante y lo acompaña a la oficina correcta. Además, revisa la cerradura de la puerta y la cambia antes de que se dañe, sin que nadie se lo recuerde.
Caddy es ese recepcionista. Los folletos son los archivos de su sitio web. Las oficinas son sus aplicaciones internas, como el inventario o la wiki. Y la cerradura es el certificado que cifra la conexión, ese que el navegador muestra como un candado.
En cambio, con un servidor web tradicional alguien tiene que acordarse de la cerradura. Es decir, debe instalar otra herramienta, programar la renovación y revisar que no falle. Cuando ese alguien se olvida, el navegador avisa de que el sitio no es seguro y los visitantes se van.
Caddy Server en cifras
Caddy nació en 2015 y está escrito en Go. La versión 2, la actual, se publicó en mayo de 2020 y fue una reescritura completa. Además, tiene licencia Apache 2.0 y no existe una edición de pago.
Su repositorio oficial supera las 77.000 estrellas en GitHub. Por su parte, la imagen oficial de Docker acumula más de 739 millones de descargas. La versión vigente es la 2.11.7, del 3 de octubre de 2026.
Sin embargo, sigue siendo minoritario. Según las estadísticas de W3Techs, al 8 de octubre de 2026 lo usa el 1,1 % de los sitios cuyo servidor web se conoce. En cambio, Nginx llega al 30,7 % y Apache al 21,8 %.
Qué hay dentro de Caddy Server
Caddy no es un conjunto de programas, sino uno solo. Todo viaja dentro de un único ejecutable de 52 MB, sin librerías ni intérpretes que instalar aparte. Esto es lo que trae la versión 2.11.7 estándar:
| Pieza | Qué hace |
|---|---|
| Servidor HTTP | Atiende HTTP/1.1, HTTP/2 y HTTP/3, los tres activos de fábrica |
| Gestor de certificados | Pide y renueva los certificados con Let’s Encrypt y ZeroSSL |
| Autoridad interna | Firma certificados para nombres locales y direcciones IP |
| Proxy inverso | Reparte las visitas entre sus aplicaciones y vigila si responden |
| Servidor de archivos | Entrega sitios estáticos, comprime y lista carpetas |
| Adaptador del Caddyfile | Convierte su archivo de texto en la configuración interna, que es JSON |
| API de administración | Cambia la configuración en caliente desde el propio equipo |
En total son 135 módulos estándar y 40 directivas de configuración. Además, se le pueden añadir módulos de terceros. Sin embargo, eso obliga a compilar una versión propia, como veremos más adelante.
Usos comunes de Caddy Server
Casi todos los usos de Caddy Server caben en dos ideas: servir un sitio o poner una puerta de entrada con HTTPS delante de otras aplicaciones.
| Uso | Ejemplo | Directiva que se usa |
|---|---|---|
| Servir un sitio estático | La página corporativa o la documentación interna | file_server |
| Publicar aplicaciones internas | El inventario y la wiki, cada uno con su nombre | reverse_proxy |
| Servir aplicaciones PHP | WordPress u otra aplicación con PHP-FPM | php_fastcgi |
| Repartir la carga | Dos copias de la misma aplicación | reverse_proxy con varios destinos |
| Usar HTTPS dentro de la oficina | Nombres internos con certificado propio | tls internal |
| Probar con HTTPS en el equipo propio | localhost con un certificado local | Autoridad interna |
| Compartir una carpeta por la red | Un listado de archivos que se navega | file_server browse |
| Poner contraseña a una zona | Un panel de administración | basic_auth |
| Mover un dominio | El dominio antiguo lleva al nuevo | redir |
| Avisar de un mantenimiento | Responder 503 mientras se actualiza | respond |
Por eso se le ve tanto en laboratorios caseros y en empresas pequeñas, sobre todo junto a contenedores de Docker. En cambio, si solo busca un proxy inverso con panel web, compare antes con Nginx Proxy Manager.
Beneficios de Caddy Server y sus límites
Estos son los beneficios de Caddy Server que comprobamos, con el dato de nuestra prueba cuando lo hay:
| Beneficio | En la práctica |
|---|---|
| HTTPS automático | Pide el certificado, lo renueva y redirige HTTP a HTTPS sin configurarlo |
| Configuración corta | Un sitio con HTTPS cabe en tres líneas de texto |
| Un solo ejecutable | 52 MB sin dependencias: se copia y funciona |
| Cambios sin reiniciar | En nuestra prueba, una recarga tardó 0,17 segundos y no detuvo el servicio |
| Tolera errores de sintaxis | Si el archivo nuevo tiene un error, lo rechaza y sigue con el anterior |
| Valores de fábrica prudentes | TLS 1.2 como mínimo, credenciales ocultas en los registros y API solo local |
| HTTP/3 incluido | Viene activo, junto a HTTP/1.1 y HTTP/2 |
| Ligero | 11 MiB de memoria en reposo y 23 MiB tras 20.000 peticiones |
| Gratuito | Licencia Apache 2.0, sin edición de pago ni límite de sitios |
Lo que Caddy Server no hace
Conviene conocer los límites antes de adoptarlo, porque casi todos se descubren tarde:
- No tiene panel web. Todo se configura con texto o por su API, y las interfaces gráficas que existen son de terceros.
- No comprime con Brotli al vuelo. La versión estándar trae zstd y gzip; Brotli solo se entrega si el archivo ya está comprimido en el disco.
- No incluye los módulos de los proveedores de DNS. Por tanto, el certificado comodín exige compilar una versión propia.
- No limita las peticiones por visitante ni filtra ataques. Es decir, no es un cortafuegos de aplicaciones.
- No reenvía tráfico TCP o UDP genérico. De fábrica, el proxy inverso trabaja con HTTP.
- Solo la última versión recibe correcciones de seguridad, y en 2026 el proyecto ya publicó 17 avisos.
- Es menos común que Nginx o Apache. Por eso es probable que su equipo tenga que aprenderlo.
Sistema base y arquitecturas soportadas
Caddy Server no es un sistema operativo ni depende de uno concreto. Es un ejecutable estático: no usa librerías del sistema, así que el mismo archivo funciona en cualquier distribución de Linux. Además, el proyecto publica ejecutables oficiales para cuatro sistemas operativos:
| Sistema operativo | Arquitecturas con ejecutable oficial en la 2.11.7 |
|---|---|
| Linux | amd64, arm64, armv5, armv6, armv7, ppc64le, riscv64 y s390x |
| Windows | amd64 y arm64 |
| macOS | amd64 (Intel) y arm64 (Apple Silicon) |
| FreeBSD | amd64, arm64, armv6 y armv7 |
Son 16 combinaciones. Es decir, corre igual en un servidor con procesador Intel o AMD, en una Raspberry Pi o en un portátil con ARM. Si quiere repasar la diferencia, la explicamos en la comparativa AMD64 vs ARM64.
En cuanto a Docker, la imagen oficial se construye sobre Alpine Linux 3.23 y se publica para siete arquitecturas de Linux. Además, existen imágenes para contenedores de Windows Server 2022 y 2025.
Requisitos de Caddy Server: lo que midió nuestra prueba
La documentación no publica requisitos mínimos, así que los medimos. Usamos la imagen oficial 2.11.7 en Docker Desktop y el ejecutable de Windows en el mismo equipo:
| Dato | Resultado |
|---|---|
| Descarga del ejecutable para Linux amd64 | 18,1 MB comprimido |
| Tamaño del ejecutable | 52 MB |
| Imagen de Docker | 24,9 MB de descarga y 68 MB de contenido |
| Arranque hasta la primera respuesta | 0,66 segundos |
| Memoria en reposo | 11 MiB |
| Memoria con cuatro sitios, tras 20.000 peticiones | 23 MiB |
| Memoria en Windows 11, con un sitio | 35 MiB |
| Copia de seguridad de datos y configuración | 3,5 KB comprimida |
Por tanto, cabe en casi cualquier equipo. Sin embargo, medimos en un computador de 20 núcleos y con poco tráfico. Con muchos sitios, certificados y visitas simultáneas, la memoria crece. Por otra parte, los tamaños van en MB decimales, de un millón de bytes, y la memoria en MiB, como la muestra Docker.
Puertos que usa Caddy Server
| Puerto | Para qué |
|---|---|
| 80/TCP | HTTP, redirección a HTTPS y validación del certificado |
| 443/TCP | HTTPS |
| 443/UDP | HTTP/3 |
| 2019/TCP | API de administración, solo desde el propio equipo |
Así que, si va a publicar un sitio en internet, su firewall debe dejar pasar los tres primeros. En cambio, el 2019 no se abre nunca hacia afuera.
Instalar Caddy Server en Linux, Windows, macOS y Docker
Hay cuatro caminos para instalar Caddy: el paquete de su distribución, un gestor de paquetes, el ejecutable suelto y Docker. Sin embargo, no todos entregan la misma versión. Lo comprobamos el 7 de octubre de 2026, cuatro días después de publicarse la 2.11.7:
| Canal de instalación | Versión que entregaba |
|---|---|
| Repositorio oficial para Debian y Ubuntu | 2.11.7 |
| Paquete propio de Debian 13 y de Ubuntu 24.04 y 26.04 | 2.6.2, de octubre de 2022 |
| Repositorio COPR oficial para Fedora y RHEL | 2.11.4, de junio de 2026 |
| Paquete propio de Fedora 44 | 2.10.2 |
| Alpine 3.23 y Arch Linux | 2.11.4 |
| Imagen oficial de Docker | 2.11.7 |
| Homebrew, winget, Scoop y Chocolatey | 2.11.7 |
El dato importante está en la segunda fila. Si escribe apt install caddy sin añadir antes el repositorio oficial, Debian y Ubuntu le instalan la 2.6.2. Es decir, una versión de hace cuatro años, que ya no mantiene el proyecto sino la distribución. Por eso conviene comprobar siempre el resultado con caddy version.
Instalar Caddy en Ubuntu y Debian
Para instalar Caddy en Ubuntu, Debian o Raspberry Pi OS, añada primero el repositorio oficial. Probamos estas órdenes en Debian 13, Ubuntu 24.04 y Ubuntu 26.04:
sudo apt install --yes 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 chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
El paquete deja a Caddy funcionando como servicio. En concreto, crea el usuario caddy, instala la unidad de systemd y arranca con una página de bienvenida en el puerto 80. Compruébelo así:
caddy version
systemctl status caddy
curl -I http://localhost
Instalar Caddy en Fedora, RHEL y otras distribuciones
Para instalar Caddy en Fedora, el proyecto mantiene un repositorio COPR:
sudo dnf install dnf5-plugins
sudo dnf copr enable @caddy/caddy
sudo dnf install caddy
sudo systemctl enable --now caddy
En RHEL y sus derivados, el primer paquete se llama dnf-plugins-core. Además, a diferencia de Debian, aquí el servicio no arranca solo: por eso existe la última línea. En cambio, en Arch Linux basta pacman -Syu caddy y en Alpine, apk add caddy.
Sin embargo, tenga presente la tabla anterior. Estos tres canales entregaban la 2.11.4 cuando ya existía la 2.11.7. Por tanto, si necesita la última corrección el mismo día, use el ejecutable oficial o Docker.
Instalar Caddy en Windows
Para instalar Caddy en Windows no hay asistente: es un único caddy.exe. Puede obtenerlo de cuatro maneras, y las cuatro entregaban la 2.11.7:
| Método | Orden |
|---|---|
| winget | winget install CaddyServer.Caddy |
| Scoop | scoop install caddy |
| Chocolatey | choco install caddy |
| Manual | Descargar el archivo zip de la página de versiones en GitHub |
Nosotros descargamos el zip oficial, de 18,5 MB, y comprobamos su suma SHA-512 contra el archivo de sumas de la versión. Dentro viene un caddy.exe de 53 MB. Después de copiarlo a una carpeta, pruébelo con un servidor de una línea:
cd C:\caddy
.\caddy.exe version
.\caddy.exe file-server --listen 127.0.0.1:8080 --browse
En nuestro Windows 11 respondió a los 0,6 segundos. Además, anote tres avisos que comprobamos o que da la documentación:
- El ejecutable no lleva firma digital de Windows. Por eso el sistema puede mostrar una advertencia al abrirlo, y la suma SHA-512 es su garantía de que el archivo es el original.
- Los certificados y el estado se guardan en
%AppData%\Caddy, dentro del perfil del usuario que lo ejecuta. - Si atiende visitas de otros equipos, el firewall de Windows debe permitirlo.
Para dejarlo como servicio, la documentación propone sc.exe, desde una consola de administrador. Esta parte no la ejecutamos, porque modifica el equipo:
sc.exe create caddy start= auto binPath= "C:\caddy\caddy.exe run --config C:\caddy\Caddyfile"
sc.exe start caddy
Por último, un servicio de Windows no se recarga desde el panel de servicios. Para aplicar cambios, use caddy reload.
Instalar Caddy en macOS
Para instalar Caddy en macOS se usa Homebrew, que también entregaba la 2.11.7:
brew install caddy
Caddy con Docker Compose
Con Docker no hace falta instalar Caddy en el sistema: basta la imagen oficial. Lo habitual es usar Compose, y este es el archivo que recomienda la documentación, con la versión fijada:
services:
caddy:
image: caddy:2.11.7
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./conf:/etc/caddy
- ./site:/srv
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Antes de arrancar, cree la carpeta conf y ponga dentro su Caddyfile. Después use estas tres órdenes para arrancar, recargar y leer el registro:
docker compose up -d
docker compose exec -w /etc/caddy caddy caddy reload
docker compose logs -n 100 caddy
Además, cuatro detalles de ese archivo importan:
- El volumen
caddy_dataguarda los certificados. Si lo pierde, Caddy los pide todos otra vez. - El puerto
443/udpes el de HTTP/3. Sin él, el sitio funciona, pero solo con HTTP/1.1 y HTTP/2. - Dentro de un contenedor,
localhostes el propio contenedor. Por eso el destino del proxy es el nombre del otro servicio, comoapp:8080. - La imagen se ejecuta como
rooty no trae comprobación de salud.
Si Compose es nuevo para usted, empiece por nuestra guía de Docker Compose.
Dónde deja Caddy Server cada archivo
| Qué | Paquete de Linux | Docker | Windows |
|---|---|---|---|
| Configuración | /etc/caddy/Caddyfile | /etc/caddy/Caddyfile | Donde usted la ponga |
| Certificados y estado | /var/lib/caddy/.local/share/caddy | /data/caddy | %AppData%\Caddy |
| Última configuración aplicada | /var/lib/caddy/.config/caddy | /config/caddy | %AppData%\Caddy |
| Sitio de ejemplo | /usr/share/caddy | /usr/share/caddy | No trae |
| Registros | journalctl -u caddy | docker compose logs | La consola |
| Usuario | caddy | root | El que lo ejecuta |
Por último, sus archivos web deben estar donde el usuario caddy pueda leerlos. La documentación recomienda /var/www/html o /srv, y advierte que desde /home no funciona.
El Caddyfile: configuración básica de Caddy Server
El Caddyfile es el archivo de texto donde usted le dice a Caddy Server qué sitios atender y qué hacer con cada visita. No lleva extensión y, en Linux, suele estar en /etc/caddy/Caddyfile. Además, es corto a propósito. Este es un sitio completo, con HTTPS, compresión y registro de visitas:
www.example.com {
root * /var/www/html
encode
file_server
log
}
La primera línea es la dirección del sitio. Como es un nombre de dominio, Caddy activa el HTTPS automático: pide el certificado y redirige lo que llegue por HTTP. Después, dentro de las llaves, van las directivas, una por línea.
Estructura de un Caddyfile
Un Caddyfile con varios sitios tiene tres clases de bloques. Este ejemplo de Caddyfile los reúne:
{
email admin@example.com
}
(comun) {
encode
log
}
www.example.com {
import comun
root * /var/www/html
file_server
}
app.example.com {
import comun
reverse_proxy 127.0.0.1:8080
}
| Parte | Qué es | Regla |
|---|---|---|
| Opciones globales | Ajustes para todo el servidor | Es el primer bloque y no lleva nombre |
| Fragmento | Configuración que se reutiliza | Se define entre paréntesis y se trae con import |
| Bloque de sitio | Un sitio y sus directivas | Empieza por su dirección |
| Directiva | Una orden sobre la visita | Es la primera palabra de la línea |
| Subdirectiva | Un ajuste de esa directiva | Va entre las llaves de la directiva |
| Comentario | Texto que Caddy ignora | Empieza por # |
Además, hay tres reglas de escritura que explican la mayoría de los errores. Primero, la llave de apertura va al final de su línea, después de un espacio. Segundo, la llave de cierre va sola en la suya. Tercero, toda directiva vive dentro de un bloque de sitio. Es decir, no hay ajustes compartidos fuera de las opciones globales.
La dirección del sitio decide si hay HTTPS
Lo que usted escribe como dirección en el Caddyfile determina el protocolo, el puerto y el certificado:
| Dirección del sitio | Resultado |
|---|---|
example.com | HTTPS con un certificado público |
*.example.com | HTTPS con un certificado comodín, que exige el desafío DNS |
localhost | HTTPS con un certificado de la autoridad interna |
192.168.1.10 | HTTPS con un certificado interno para esa IP |
http://example.com | Solo HTTP, sin certificado |
:8080 | HTTP en ese puerto, para cualquier nombre |
example.com:8443 | HTTPS en un puerto distinto del 443 |
Por tanto, basta escribir un nombre para tener HTTPS, y basta anteponer http:// para no tenerlo. Además, cuando el sitio lleva nombre, Caddy solo atiende las visitas que lo piden con ese nombre.
Las directivas del Caddyfile que más se usan
| Directiva | Qué hace | Ejemplo |
|---|---|---|
root | Fija la carpeta del sitio | root * /var/www/html |
file_server | Entrega archivos estáticos | file_server |
reverse_proxy | Pasa la visita a otra aplicación | reverse_proxy 127.0.0.1:8080 |
php_fastcgi | Envía los archivos PHP a PHP-FPM | php_fastcgi 127.0.0.1:9000 |
encode | Comprime las respuestas con zstd o gzip | encode |
redir | Redirige a otra dirección | redir https://www.example.com{uri} |
header | Añade o quita cabeceras | header X-Content-Type-Options nosniff |
basic_auth | Pide usuario y contraseña | Vea el escenario 6 |
handle_path | Agrupa directivas por ruta y quita el prefijo | Vea el escenario 2 |
request_body | Limita el tamaño de lo que se sube | max_size 10MB |
log | Activa el registro de visitas | log |
tls | Ajusta el certificado del sitio | tls internal |
respond | Contesta un texto fijo | respond "En mantenimiento" 503 |
import | Trae un fragmento u otros archivos | import sitios/* |
Además, el orden en que usted las escribe en el Caddyfile no importa, porque Caddy las ejecuta según un orden interno. Por ejemplo, redir se evalúa antes que reverse_proxy, y file_server queda casi al final. En cambio, dentro de un bloque route sí se respeta el orden escrito.
Rutas y condiciones en el Caddyfile
Una directiva del Caddyfile puede limitarse a ciertas visitas. La forma más simple es una ruta: reverse_proxy /api/* 127.0.0.1:9000 solo actúa sobre lo que empieza por /api/. Además, puede definir condiciones con nombre. Por ejemplo, esta deja pasar solo a la red interna:
intranet.example.com {
@fuera not remote_ip private_ranges
respond @fuera "Acceso solo desde la red interna" 403
reverse_proxy 127.0.0.1:8080
}
Sin embargo, hay un detalle que comprobamos y que causa muchos 404: /app/* no incluye /app a secas. En nuestra prueba, /uno/informes llegó a la aplicación, pero /uno devolvió «No encontrado». Por eso conviene acompañar la regla con una redirección, como redir /app /app/.
Variables de entorno en el Caddyfile
Para no dejar datos sensibles en el Caddyfile, Caddy lee variables de entorno con la forma {$NOMBRE}. Por ejemplo, {$DOMINIO:localhost} usa la variable DOMINIO y, si no existe, el valor localhost. Así el mismo Caddyfile sirve en el equipo de pruebas y en el servidor.
Validar, dar formato y ver el JSON
Antes de aplicar un cambio en el Caddyfile, compruébelo. Caddy trae tres órdenes para eso:
caddy validate --config /etc/caddy/Caddyfile
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
caddy adapt --config /etc/caddy/Caddyfile --pretty
La primera carga la configuración sin ponerla en marcha y avisa de los errores. La segunda corrige la sangría del Caddyfile. Y la tercera muestra el JSON que Caddy usa por dentro. En nuestra prueba, un Caddyfile de 65 líneas útiles se convirtió en 484 líneas de JSON.
Además, validate es más estricta que adapt. Por ejemplo, un sitio que apuntaba a un certificado inexistente pasó adapt sin errores. En cambio, validate lo detectó, porque intenta cargar de verdad cada archivo.
Caddy HTTPS: cómo funciona el HTTPS automático
El HTTPS automático es la razón de ser de Caddy Server. Cuando usted escribe un nombre de dominio como dirección del sitio, Caddy activa el HTTPS y hace cuatro cosas sin más instrucciones:
- Pide un certificado a una autoridad pública: Let’s Encrypt y, si esta falla, ZeroSSL.
- Lo guarda en su directorio de datos y lo renueva antes de que caduque.
- Redirige a HTTPS todo lo que llega por HTTP.
- Negocia TLS 1.2 o 1.3 y ofrece HTTP/2 y HTTP/3.
Sin embargo, para que funcione con un dominio público deben cumplirse cinco condiciones:
- El registro DNS del dominio apunta a la IP pública de su servidor. Si no tiene claros los registros A y AAAA, repáselos en la guía del servidor DNS.
- Los puertos 80 y 443 están abiertos desde internet.
- Caddy puede escuchar en esos puertos, o le llegan reenviados.
- El directorio de datos se puede escribir y no se borra.
- El nombre del dominio aparece en el Caddyfile.
Además, en nuestra prueba Caddy redirigió de HTTP a HTTPS con el código 308 y conservó la ruta y los parámetros de la dirección.
Los tres desafíos de validación
Antes de entregar un certificado, la autoridad comprueba que el dominio es suyo. A esa comprobación se le llama desafío, y hay tres:
| Desafío | Cómo comprueba | Qué exige | ¿Sirve para comodín? |
|---|---|---|---|
| HTTP | Pide un archivo temporal por el puerto 80 | Puerto 80 abierto | No |
| TLS-ALPN | Abre una conexión TLS especial al puerto 443 | Puerto 443 abierto | No |
| DNS | Busca un registro TXT en su dominio | Un módulo para su proveedor de DNS | Sí |
Los dos primeros vienen activos y Caddy elige entre ellos. En cambio, el desafío DNS no necesita puertos abiertos, pero exige un módulo que la versión estándar no trae. Además, es el único que Let’s Encrypt acepta para los certificados comodín.
Cuándo renueva Caddy un certificado: lo que medimos
Caddy renueva cada certificado cuando le queda un tercio de su vida. Lo comprobamos con una autoridad de pruebas local, que emitía certificados de seis minutos. Caddy los renovó a los cuatro minutos, cuando faltaban dos. Mientras tanto, enviamos 6.492 peticiones seguidas. Solo falló una, casi cuatro minutos antes de la renovación, y ninguna mientras Caddy renovaba.
Trasladado a Let’s Encrypt, cuyos certificados duran 90 días, eso significa renovar hacia el día 60. Además, ese margen importa cada vez más. Según Let’s Encrypt, las normas del sector bajarán la vigencia máxima a 100 días en marzo de 2027 y a 47 días en marzo de 2029. Es decir, renovar a mano dejará de ser viable.
También medimos la primera emisión. Con la autoridad local, el primer sitio de Caddy respondió por HTTPS 1,1 segundos después de arrancar. Mientras tanto, quien llegaba por HTTPS recibía un error de TLS. Con una autoridad pública el trámite tarda más, porque interviene internet. Por otra parte, al añadir un sitio nuevo con una recarga, los que ya existían siguieron atendiendo mientras se emitía su certificado: de 38 peticiones a esos sitios solo falló una.
HTTPS en la red interna: la autoridad local
No todos los sitios tienen un dominio público. Para localhost, las direcciones IP y los nombres que terminan en .internal, .local, .localhost o .home.arpa, Caddy no acude a internet. En su lugar, crea su propia autoridad de certificación y firma los certificados él mismo. Además, usted puede forzarlo en cualquier sitio con la directiva tls internal.
| Dato de la autoridad interna | Lo que medimos |
|---|---|
| Certificado de cada sitio | Vale 12 horas y se renueva solo |
| Certificado intermedio | Vale 7 días |
| Certificado raíz | Vale 3.600 días, casi 10 años |
| Tipo de clave | ECDSA P-256 |
| Primera respuesta por HTTPS | 1,5 segundos después de arrancar |
| Permisos de las claves | Solo las lee el usuario de Caddy |
Ahora bien, esa autoridad solo la conoce su servidor. Por eso, cada equipo que visite el sitio verá una advertencia hasta que usted instale en él el certificado raíz. El archivo está en el directorio de datos, en pki/authorities/local/root.crt. En el propio servidor lo instala la orden sudo caddy trust: la probamos en Debian 13 y, desde entonces, el sistema aceptó el certificado sin advertencias.
Los límites de Let’s Encrypt y el entorno de pruebas
Let’s Encrypt limita cuántos certificados entrega, y un servidor mal configurado agota esos límites rápido. Estos son los que más se alcanzan, según su documentación de límites:
| Límite de Let’s Encrypt | Valor |
|---|---|
| Certificados por dominio registrado | 50 cada 7 días |
| Certificados para el mismo conjunto exacto de nombres | 5 cada 7 días |
| Validaciones fallidas por nombre y cuenta | 5 por hora |
| Nombres en un mismo certificado | 100 |
Por eso hay dos reglas. Primero, no borre el directorio de datos: sin él, Caddy pide todos los certificados de nuevo. Segundo, mientras hace pruebas, use el entorno de pruebas de Let’s Encrypt con esta opción global:
{
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
Sus certificados no los acepta el navegador, pero sus límites son mucho más amplios. Además, si una emisión falla, Caddy reintenta por su cuenta. Primero cambia de desafío, luego de autoridad y después espera cada vez más, hasta un día entre intentos.
Lo que el HTTPS de Caddy no activa: HSTS
Revisamos las cabeceras de un sitio recién creado y falta una que muchos dan por hecha. Se llama HSTS y le ordena al navegador usar siempre HTTPS con ese sitio. Sin embargo, Caddy no la envía por su cuenta, aunque el sitio ya use HTTPS. Si la quiere, añádala cuando el HTTPS lleve semanas estable:
header Strict-Transport-Security "max-age=31536000"
Hágalo al final y con calma, porque el navegador recordará esa orden durante un año.
Caddy reverse proxy: publicar aplicaciones internas
El segundo gran uso de Caddy Server es el reverse proxy, o proxy inverso: recibe la visita, la pasa a una aplicación interna y devuelve la respuesta. Si el concepto es nuevo para usted, lo explicamos con un ejemplo cotidiano en la guía de Nginx Proxy Manager. En Caddy, la forma mínima ocupa tres líneas:
app.example.com {
reverse_proxy 127.0.0.1:8080
}
Con eso, Caddy pone el certificado, redirige HTTP y entrega las visitas a la aplicación del puerto 8080. Además, los WebSockets funcionan sin ninguna opción adicional: en nuestra prueba, la conexión se abrió a la primera.
Qué recibe la aplicación detrás del reverse proxy
Una aplicación detrás de un proxy necesita saber quién la visita de verdad. Para eso, Caddy le envía tres cabeceras. Las pusimos a prueba enviando valores falsos desde el visitante:
| Cabecera | Lo que envió el visitante | Lo que recibió la aplicación |
|---|---|---|
X-Forwarded-For | Una IP inventada | La IP real de quien se conectó |
X-Forwarded-Proto | https | http, que era el protocolo real |
X-Forwarded-Host | Un nombre inventado | El nombre pedido de verdad |
X-Real-IP | Una IP inventada | La misma IP inventada |
Host | El nombre del sitio | El mismo nombre, sin cambios |
Es decir, como reverse proxy, Caddy descarta las tres primeras cuando vienen de fuera, para que nadie se haga pasar por otro. Sin embargo, no toca X-Real-IP. Por tanto, si su aplicación confía en esa cabecera, fíjela usted:
app.example.com {
reverse_proxy 127.0.0.1:8080 {
header_up X-Real-IP {remote_host}
}
}
Por último, la cabecera Host solo se conserva cuando el destino habla HTTP. En cambio, si el destino es HTTPS, Caddy la sustituye por la dirección de ese destino desde la versión 2.11. Lo vimos al encadenar dos servidores Caddy: el segundo dejó de reconocer el nombre del sitio.
Detrás de Cloudflare o de otro proxy
Si delante de Caddy hay otro proxy, la IP que él ve es la de ese proxy y no la del visitante. Para que confíe en lo que este le informa, declárelo en las opciones globales:
{
servers {
trusted_proxies static 203.0.113.10/32
}
}
Ponga solo las direcciones de su proxy. De lo contrario, cualquiera podría falsear su IP con una cabecera.
Balanceo de carga y destinos caídos: lo que medimos
Con dos o más destinos, el reverse proxy de Caddy reparte las visitas entre ellos. De fábrica elige al azar. Sin embargo, tiene un comportamiento que conviene conocer: por defecto no comprueba si los destinos responden.
Lo medimos con dos destinos, uno de ellos caído, y 200 peticiones por cada configuración:
| Configuración del proxy | Respuestas correctas | Errores 502 | Tiempo medio |
|---|---|---|---|
| De fábrica, sin nada más | 94 | 106 | 13 ms |
lb_try_duration 5s: reintenta con otro destino | 200 | 0 | 282 ms |
fail_duration 30s: recuerda el fallo | 199 | 1 | 11 ms |
health_uri cada 2 segundos: comprobación activa | 200 | 0 | 10 ms |
fail_duration 30s y lb_try_duration 5s juntas | 200 | 0 | 12 ms |
Por tanto, con los valores de fábrica, la mitad de los visitantes vio un error. En cambio, bastan dos líneas para evitarlo: una que recuerde los fallos y otra que reintente. Este bloque reúne lo recomendable:
app.example.com {
reverse_proxy 10.0.0.11:8080 10.0.0.12:8080 {
lb_policy round_robin
fail_duration 30s
lb_try_duration 5s
health_uri /salud
health_interval 10s
}
}
Aquí lb_policy cambia el reparto al azar por turnos. Además, existen otras políticas, como least_conn, ip_hash o first, que sirve para tener un servidor principal y otro de reserva. La ruta de health_uri debe existir en su aplicación y responder 200. El concepto general lo tratamos en la guía de alta disponibilidad.
Tiempos de espera del reverse proxy
También medimos cuánto espera el reverse proxy de Caddy a un destino antes de rendirse:
| Situación | Respuesta | Tardó |
|---|---|---|
| El puerto de destino está cerrado | 502 | 0,02 segundos |
| La IP de destino no contesta | 502 | 3,0 segundos |
| La aplicación tarda 70 segundos en responder | 200 | 70,0 segundos |
| La aplicación tarda, con un límite de 2 segundos | 504 | 2,0 segundos |
Es decir, Caddy espera 3 segundos para conectar, pero no pone límite a la respuesta. Así, un informe lento no se corta; una aplicación colgada, tampoco. Si quiere un límite, declárelo:
app.example.com {
reverse_proxy 127.0.0.1:8080 {
transport http {
response_header_timeout 60s
}
}
}
Comandos más comunes de Caddy Server
Caddy Server trae 24 órdenes. Estas son las que se usan a diario:
| Orden | Qué hace |
|---|---|
caddy version | Muestra la versión instalada |
caddy run | Arranca en primer plano; es lo que usan systemd y Docker |
caddy start y caddy stop | Arrancan en segundo plano y detienen |
caddy reload | Aplica el Caddyfile nuevo sin detener el servicio |
caddy validate | Comprueba la configuración sin aplicarla |
caddy fmt --overwrite | Corrige la sangría del Caddyfile |
caddy adapt --pretty | Muestra el JSON equivalente |
caddy hash-password | Cifra una contraseña para basic_auth |
caddy list-modules | Lista los módulos incluidos |
caddy trust | Instala el certificado raíz de la autoridad interna |
caddy environ | Muestra las rutas y el entorno que usa |
caddy upgrade | Reemplaza el ejecutable por la última versión; es experimental |
Órdenes del día a día en un servidor Linux
Con el paquete oficial, el servicio se maneja con systemd. Esta es la rutina habitual después de editar el Caddyfile:
sudo nano /etc/caddy/Caddyfile
caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
systemctl status caddy
sudo journalctl -u caddy --since "10 minutes ago"
Es decir, se edita, se valida, se recarga y se mira el registro. Además, si el servicio no arranca, journalctl muestra el motivo en sus últimas líneas. Eso sí, úselo con sudo: en nuestra prueba con Debian 13, un usuario normal no vio ni una línea del registro sin él.
Servidores de una línea
Para una prueba rápida no hace falta ni el Caddyfile. Cada una de estas órdenes levanta un servidor:
caddy file-server --listen :8080 --browse
caddy reverse-proxy --from :8081 --to 127.0.0.1:3000
caddy respond --listen :8082 --status 503 "En mantenimiento"
La primera comparte la carpeta actual, con listado de archivos y compresión. La segunda pone un proxy inverso delante de la aplicación del puerto 3000. Y la tercera responde siempre lo mismo, lo que sirve durante un mantenimiento. Sin embargo, comprobamos que las tres arrancan sin la API de administración. Por tanto, no se pueden recargar: para cambiar algo hay que detenerlas y lanzarlas de nuevo.
Recargar no es reiniciar: lo que medimos
La regla de oro de Caddy Server es no reiniciar para cambiar la configuración. Lo medimos con un sondeo continuo mientras aplicábamos cambios:
| Acción | Duración | Peticiones fallidas |
|---|---|---|
caddy reload con un archivo válido | 0,17 segundos | 0 de 78 |
caddy reload con un archivo con errores | 0,14 segundos | 0 de 96; siguió la configuración anterior |
| Reiniciar el contenedor | 2,4 segundos | 80 de 158: 1,9 segundos sin servicio |
Sin embargo, la recarga no es del todo invisible. Al cambiar de configuración, Caddy cierra las conexiones que estaban abiertas y sin uso. Por tanto, si un programa reutiliza la suya justo entonces, esa petición se pierde.
Lo vimos en 10 de 20 recargas espaciadas. En total fallaron 19 peticiones de 44.753, y 18 eran de clientes que reutilizaban la conexión. En cambio, de las 23.496 que abrieron una conexión nueva solo falló una.
Un navegador reintenta solo y el visitante no nota nada. En cambio, un programa que llama a una API sin reintentos puede ver el error. Por eso conviene agrupar los cambios y no recargar en bucle.
La API de administración de Caddy Server
Caddy se administra también por una API que escucha en localhost:2019. De hecho, caddy reload la usa por dentro. Con ella puede leer la configuración o ver el estado de los destinos:
curl -s localhost:2019/config/
curl -s localhost:2019/reverse_proxy/upstreams
Además, comprobamos tres cosas sobre ella. Primero, solo escucha en el propio equipo: en Docker, publicar el puerto 2019 no la expone. Segundo, rechaza con un 403 las peticiones que llegan con otro nombre de equipo o desde otro origen. Tercero, lo que usted cambie por la API se pierde al reiniciar si Caddy arranca desde el Caddyfile, que es lo habitual. Por eso conviene elegir un solo método: el archivo o la API.
Escenarios de ejemplo con Caddy Server
Estos seis escenarios cubren la mayoría de los casos. Los probamos todos con la versión 2.11.7 antes de publicarlos, tal como aparecen aquí y con certificados de prueba en lugar de públicos.
Escenario 1: un sitio estático con HTTPS
www.example.com {
root * /var/www/html
encode
file_server
header {
X-Content-Type-Options nosniff
-Server
}
handle_errors {
respond "{err.status_code} {err.status_text}"
}
}
example.com {
redir https://www.example.com{uri} permanent
}
El segundo bloque del Caddyfile lleva al nombre con www a quien escriba el dominio sin él. La palabra permanent hace definitiva esa redirección, con el código 301. Sin ella, comprobamos que Caddy responde con un 302, que es temporal. Además, la directiva header añade una cabecera de protección y quita la que anuncia el programa. En cuanto a handle_errors, evita una sorpresa que comprobamos: sin esa directiva, un 404 de Caddy llega con el cuerpo vacío.
Escenario 2: Caddy como reverse proxy de dos aplicaciones con Docker Compose
Este compose.yaml levanta Caddy como reverse proxy y dos aplicaciones detrás. Las imágenes son de ejemplo: sustitúyalas por las suyas.
services:
caddy:
image: caddy:2.11.7
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./conf:/etc/caddy
- caddy_data:/data
- caddy_config:/config
inventario:
image: traefik/whoami:v1.12.0
restart: unless-stopped
wiki:
image: traefik/whoami:v1.12.0
restart: unless-stopped
volumes:
caddy_data:
caddy_config:
Y este es el Caddyfile, en la carpeta conf:
inventario.example.com {
reverse_proxy inventario:80
}
wiki.example.com {
reverse_proxy wiki:80
}
Ninguna de las dos aplicaciones publica puertos: solo Caddy queda expuesto. Además, si prefiere un solo nombre con rutas, use handle_path, que quita el prefijo antes de pasar la visita:
portal.example.com {
redir /inventario /inventario/
handle_path /inventario/* {
reverse_proxy inventario:80
}
redir /wiki /wiki/
handle_path /wiki/* {
reverse_proxy wiki:80
}
handle {
respond "No encontrado" 404
}
}
Sin embargo, muchas aplicaciones no funcionan dentro de una ruta si no se les configura su dirección base. Por eso suele ser más sencillo darle a cada una su propio nombre.
Escenario 3: WordPress u otra aplicación PHP
blog.example.com {
root * /var/www/wordpress
encode
php_fastcgi unix//run/php/php8.4-fpm.sock
file_server
request_body {
max_size 64MB
}
@bloqueadas path /xmlrpc.php *.sql /wp-content/uploads/*.php
rewrite @bloqueadas /index.php
}
Caddy no ejecuta PHP: lo delega en PHP-FPM, que se instala aparte. La directiva php_fastcgi le envía cada archivo PHP y deja que index.php atienda las rutas que no existen en el disco. En nuestra prueba con PHP 8.4, la aplicación recibió la dirección original y la IP correcta del visitante.
Las dos últimas líneas de este Caddyfile vienen de la documentación oficial. Envían a index.php los accesos a XML-RPC, a los volcados de base de datos y a los archivos PHP subidos a la carpeta de medios. Así, WordPress los responde como «no encontrado» y ninguno se ejecuta ni se descarga, como comprobamos. Eso sí, quite /xmlrpc.php de la lista si alguna aplicación suya lo necesita.
Además, un aviso sobre max_size: sus unidades son decimales. Lo comprobamos con 1MB: un envío de 1.000.000 de bytes pasó y uno de 1.000.001 recibió un error 413. Si quiere la unidad binaria, escriba MiB.
Escenario 4: una intranet con HTTPS sin salir a internet
intranet.empresa.internal {
tls internal
reverse_proxy 127.0.0.1:8080
}
Con este Caddyfile, Caddy no pide nada a internet: firma el certificado con su autoridad interna. Después, copie el certificado raíz a los equipos de la oficina e instálelo como autoridad de confianza. Con el paquete de Linux, el archivo está en /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt.
Mientras no lo haga, cada navegador mostrará una advertencia. Además, el nombre debe resolverse en su DNS interno.
Escenario 5: una página de mantenimiento cuando la aplicación no responde
app.example.com {
reverse_proxy 127.0.0.1:8080
handle_errors 502 503 {
root * /var/www/mantenimiento
rewrite * /index.html
file_server
}
}
Con este Caddyfile, cuando la aplicación está caída, el visitante ve su página de mantenimiento en lugar de una pantalla en blanco. Además, la respuesta conserva el código de error, así que los buscadores entienden que la caída es temporal.
Escenario 6: una zona privada con contraseña y registro de visitas
Primero, genere el resumen cifrado de la contraseña. La orden la pide dos veces y no la muestra:
caddy hash-password
Después, pegue el resultado en el Caddyfile, en lugar del valor de ejemplo:
admin.example.com {
basic_auth {
operador $2a$14$UKwiSebRioE.PcpGKqoz7uOH9O.Xbijp99PQByk1mDIidOSz6W9jG
}
reverse_proxy 127.0.0.1:9000
log {
output file /var/log/caddy/admin.log
}
}
Sin embargo, cada comprobación de contraseña cuesta. Con el algoritmo de fábrica, bcrypt, medimos 0,8 segundos por cada contraseña nueva, acertada o no. Caddy recuerda las ya comprobadas, así que el usuario legítimo solo espera la primera vez. En cambio, alguien que pruebe contraseñas al azar le hará gastar procesador. Por eso conviene combinar la contraseña con la restricción por red que vimos antes.
En cuanto al registro, las cabeceras con credenciales se guardan como REDACTED: lo comprobamos con Authorization y Cookie. Además, el archivo rota al llegar a 100 MiB y conserva hasta 10 copias durante 90 días.
Errores frecuentes en Caddy Server y su causa
Casi todos los errores de Caddy Server caen en tres grupos: el certificado no está, el destino no responde o el Caddyfile tiene un fallo. Reprodujimos los más buscados para ver qué los causa.
ERR_SSL_PROTOCOL_ERROR y «tlsv1 alert internal error»
Es el error más consultado de Caddy. Aparece cuando alguien pide por HTTPS un nombre para el que Caddy no tiene certificado. Lo reprodujimos de dos maneras: con un nombre que no estaba en el Caddyfile y entrando por la dirección IP. En ambos casos Caddy cortó la conexión con una alerta de TLS y Chrome mostró ERR_SSL_PROTOCOL_ERROR. Además, en su nivel normal de registro Caddy no anotó nada.
Las causas habituales son dos:
- El nombre que usted escribe no coincide con la dirección del sitio. Por ejemplo, entra por la IP y el sitio está definido con un nombre.
- El certificado todavía no se emitió, o la emisión falló.
Por tanto, revise primero qué nombre está pidiendo. Después, active la opción global debug y repita la visita: el registro mostrará qué nombre llegó y que no había certificado para él.
En cambio, si Chrome muestra ERR_CERT_AUTHORITY_INVALID, el problema es otro. Lo vimos con un sitio de la autoridad interna: el certificado existe, pero ese equipo todavía no confía en quien lo firma. La solución es instalar el certificado raíz, como explica el escenario 4.
Los errores 502 y 504 de Caddy Server
El error 502 significa que Caddy recibió la visita, pero no pudo hablar con la aplicación. En cambio, el 504 indica que la aplicación tardó más que el límite que usted fijó. Esto fue lo que reprodujimos:
| Causa | Respuesta | Tardó | Lo que anota el registro |
|---|---|---|---|
| El puerto de destino está cerrado | 502 | 0,02 segundos | connection refused |
| El nombre de destino no existe | 502 | 3,0 segundos | lookup con no such host o i/o timeout |
| La IP de destino no contesta | 502 | 3,0 segundos | i/o timeout |
| La respuesta supera su límite de tiempo | 504 | El límite | El tiempo agotado |
Así que, ante un 502, revise tres cosas en este orden. Primero, que la aplicación esté en marcha. Después, que el nombre o la IP sean correctos. Por último, que el puerto coincida. Además, en Docker recuerde que localhost es el propio contenedor de Caddy.
Errores al cargar el Caddyfile
Estos son los mensajes que obtuvimos al provocar cada fallo. Todos indican el archivo y la línea:
| Mensaje de Caddy | Causa |
|---|---|
unrecognized directive | La directiva está mal escrita o pertenece a un módulo que no tiene |
unrecognized subdirective | Lo mismo, dentro de una directiva |
directives must appear in a site block | Hay una directiva fuera de un bloque de sitio |
unexpected token, expecting '}' | Falta una llave de cierre |
ambiguous site definition | Dos sitios tienen la misma dirección |
cannot natively multiplex HTTP and HTTPS | Un mismo puerto mezcla un sitio HTTP y otro HTTPS |
Caddyfile input is not formatted | Es solo un aviso sobre la sangría; lo corrige caddy fmt --overwrite |
no such file or directory | Un certificado o un archivo que usted indicó no existe |
Además, recuerde lo que medimos: si el error aparece al recargar, el servicio sigue funcionando con la configuración anterior.
Otros problemas habituales de Caddy Server
| Síntoma | Causa | Qué hacer |
|---|---|---|
| El certificado no llega | El DNS no apunta al servidor o los puertos 80 y 443 están cerrados | Corrija el DNS y el firewall antes de reintentar |
address already in use al arrancar | Otro programa ocupa el puerto 80 o el 443 | Detenga el otro servidor web |
| 403 con archivos que existen | El usuario caddy no puede leer la carpeta, como ocurre dentro de /home | Use /var/www/html o /srv y revise los permisos |
404 en /app, pero no en /app/ | La ruta /app/* no incluye /app | Añada redir /app /app/ |
| La IP del visitante es siempre la misma | Hay otro proxy delante | Declare trusted_proxies |
| 413 al subir un archivo | Supera el valor de max_size | Suba el límite; recuerde que MB es decimal |
| El cambio no se aplica | Editó el archivo, pero no recargó | Ejecute sudo systemctl reload caddy o, sin systemd, caddy reload |
| Demasiadas redirecciones detrás de Cloudflare | Cloudflare le habla por HTTP y Caddy redirige a HTTPS | Use el modo de cifrado completo en Cloudflare |
Operación: registros, copias y actualizaciones
Los registros de Caddy Server
Caddy escribe su registro en formato JSON. Con el paquete de Linux se lee con sudo journalctl -u caddy y en Docker, con docker compose logs. Sin embargo, el registro de visitas no viene activo: hay que pedirlo con la directiva log en cada sitio.
Además, Caddy publica métricas en formato Prometheus en su API de administración, en localhost:2019/metrics. Sin embargo, las de cada petición solo aparecen con la opción global metrics: lo comprobamos, y sin ella no había ninguna. Así es posible verlas en un tablero como los de Grafana.
Qué copiar: el Caddyfile y el directorio de datos
Lo único que Caddy no puede reconstruir son sus certificados y sus claves. Por eso la copia tiene dos partes: el Caddyfile y el directorio de datos. En nuestra prueba, todo cabía en 3,5 KB.
Después restauramos esa copia en una segunda instancia. Sirvió HTTPS de inmediato y con el mismo certificado, sin pedir uno nuevo. Eso sí, trate la copia como un secreto, porque incluye las claves privadas.
Actualizar Caddy Server: solo la última versión recibe correcciones
La política de seguridad del proyecto es explícita: solo la última versión recibe correcciones. Y en 2026 hubo motivos para actualizar. Entre febrero y julio el proyecto publicó 17 avisos de seguridad, 7 de gravedad alta.
El más reciente, de julio, afecta a las versiones anteriores a la 2.11.5. Sin embargo, esa versión nunca llegó a publicarse: la primera que trae la corrección es la 2.11.6, del 1 de octubre de 2026. Por tanto, los canales que entregaban la 2.11.4 seguían sin ella.
Además, actualizar tampoco es inocuo. La 2.11.6 trajo cambios incompatibles y varias regresiones. Dos días después, la 2.11.7 las corrigió y recomendó dejar la anterior. Por eso conviene fijar la versión, leer las notas y actualizar con calendario. Con el paquete de Debian o Ubuntu se hace así:
sudo apt update
sudo apt install --only-upgrade caddy
En Docker, cambie primero la etiqueta de la imagen en su compose.yaml y después ejecute:
docker compose pull
docker compose up -d
Ambos métodos reinician Caddy, así que hay un corte breve. Lo medimos con un sondeo continuo mientras pasábamos de una versión anterior a la 2.11.7. Con el paquete de Debian, que reinicia el servicio por su cuenta, fueron 0,1 segundos sin servicio. Con Docker, que crea un contenedor nuevo, fue menos de un segundo: 0,9 en una pasada y 0,7 en otra. Además, en Docker el certificado siguió siendo el mismo, porque el volumen de datos se conserva.
Extender Caddy Server con módulos
Los módulos de terceros no se cargan en caliente: se compilan dentro del ejecutable con la herramienta xcaddy. El caso más común es el desafío DNS. Con Docker, la imagen builder lo resuelve en un Dockerfile de cuatro líneas:
FROM caddy:2.11.7-builder AS builder
RUN xcaddy build --with github.com/caddy-dns/cloudflare
FROM caddy:2.11.7
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
Lo construimos para comprobarlo: tardó menos de tres minutos y el módulo quedó incluido. Sin embargo, el precio es claro: esa versión ya no la actualiza ningún gestor de paquetes. La mantiene usted, y debe reconstruirla con cada versión nueva.
Recomendaciones para usar Caddy Server en una empresa
Caddy Server funciona bien con sus valores de fábrica, pero una empresa necesita algo más. Estas son nuestras recomendaciones, y casi todas salen de lo que medimos:
- Instale desde el repositorio oficial o con la imagen oficial, y compruebe el resultado con
caddy version. El paquete de la distribución puede llevar años de retraso. - Fije la versión y actualice con calendario, después de leer las notas. Solo la última recibe correcciones.
- Guarde el Caddyfile en un control de versiones y valide cada cambio antes de recargar.
- Recargue en lugar de reiniciar, y agrupe los cambios para no recargar varias veces seguidas.
- Copie el directorio de datos junto con el Caddyfile, y pruebe a restaurarlo al menos una vez.
- Con más de un destino, añada siempre
fail_durationylb_try_duration, o una comprobación activa. - Ponga un límite de tiempo a las aplicaciones que pueden colgarse y un tamaño máximo a las subidas.
- No publique nunca la API de administración. Déjela en
localhost. - Restrinja por red los paneles de administración. No confíe solo en la contraseña.
- Añada las cabeceras que Caddy no pone, como HSTS, cuando el HTTPS esté asentado.
- Use el entorno de pruebas de Let’s Encrypt mientras experimenta.
- Vigile desde fuera que el sitio responda y que el certificado no esté por caducar. Lo explicamos en la guía de monitoreo de servidores.
- Recuerde que es un único punto de entrada. Por tanto, documente cómo levantarlo en otro servidor con la copia.
Caddy Server vs Nginx, Apache y otras alternativas
Caddy Server no es el único servidor web ni el único proxy inverso. La diferencia principal está en cómo se configura cada uno y en quién se ocupa del certificado:
| Servidor | Licencia | Cómo se configura | HTTPS automático | Cuándo conviene |
|---|---|---|---|---|
| Caddy 2.11 | Apache 2.0 | Caddyfile, JSON o API | Sí, de fábrica | Quiere HTTPS sin mantenimiento y una configuración corta |
| Nginx 1.30 | BSD de dos cláusulas | Archivos de texto | Con un módulo aparte o con Certbot | Su equipo ya lo domina o depende de su ecosistema |
| Apache 2.4 | Apache 2.0 | Archivos de texto y .htaccess | Con el módulo mod_md | Sus aplicaciones dependen de .htaccess |
| Traefik 3.7 | MIT | Etiquetas en los contenedores | Sí | Tiene muchos contenedores que cambian a menudo |
| Nginx Proxy Manager 2.16 | MIT | Panel web | Sí, con Certbot | Prefiere un formulario a un archivo |
Además, la popularidad cuenta. Según W3Techs, Nginx está en el 30,7 % de los sitios cuyo servidor se conoce y Apache en el 21,8 %, frente al 1,1 % de Caddy. Es decir, para Nginx y Apache hay más manuales, más ejemplos y más personas que los conocen. Por otra parte, si su caso son muchos contenedores que cambian, compare con nuestra guía de Traefik.
Sobre el rendimiento no publicamos cifras. Depende del equipo, del tráfico y de la configuración, y no hicimos una comparación rigurosa. Por tanto, la elección práctica es otra. Si valora no ocuparse de los certificados y leer la configuración de un vistazo, Caddy encaja. En cambio, si su equipo ya opera Nginx sin problemas, cambiar tiene poco sentido.
Preguntas frecuentes sobre Caddy Server
¿Caddy Server es gratis?
Sí. Caddy Server es software libre con licencia Apache 2.0, sin edición de pago y sin límite de sitios. Además, los certificados de Let’s Encrypt y de ZeroSSL que obtiene tampoco cuestan. Lo único que usted paga es el servidor donde corre y el dominio.
¿Sirve Caddy para un entorno de producción?
Sí, con condiciones. W3Techs lo detecta en subdominios de organizaciones como Wise, cPanel o Archive.org. Sin embargo, de fábrica no vigila los destinos ni limita los tiempos de espera. Por tanto, en producción conviene fijar la versión, copiar el directorio de datos y añadir esas dos protecciones.
¿Qué es mejor, Caddy o Nginx?
Depende de su equipo. Caddy gana en sencillez: el HTTPS es automático y la configuración es corta. En cambio, Nginx está mucho más extendido y tiene más documentación. Si empieza de cero y quiere menos mantenimiento, Caddy es una buena opción. Si ya domina Nginx, no hay motivo para cambiar.
¿Necesito un dominio para tener HTTPS con Caddy?
No siempre. Para localhost, las direcciones IP y los nombres internos, Caddy usa su propia autoridad de certificación. Sin embargo, tendrá que instalar su certificado raíz en cada equipo. En cambio, para un certificado público sí necesita un dominio que apunte a su servidor.
¿Qué puertos usa Caddy?
Caddy usa el 80 para HTTP y para validar los certificados, y el 443 para HTTPS. Además, usa el 443 por UDP para HTTP/3. Por otra parte, la API de administración escucha en el 2019, pero solo dentro del propio equipo. Ese puerto no debe abrirse hacia afuera.
¿Caddy funciona en Windows?
Sí. Para Windows se publica un único caddy.exe, para procesadores de 64 bits y para ARM. No tiene asistente de instalación: se copia a una carpeta y se ejecuta. Además, puede dejarse como servicio con sc.exe. En nuestra prueba en Windows 11 arrancó en medio segundo.
¿Puede Caddy servir WordPress o PHP?
Sí, pero no ejecuta PHP por sí mismo. Caddy entrega los archivos estáticos y pasa los archivos PHP a PHP-FPM con la directiva php_fastcgi. Por tanto, necesita instalar PHP-FPM aparte. El escenario 3 de esta guía trae un Caddyfile completo para WordPress.
¿Dónde guarda Caddy los certificados?
En su directorio de datos. Con el paquete de Linux es /var/lib/caddy/.local/share/caddy. En cambio, en Docker es /data/caddy y en Windows, %AppData%\Caddy. Ese directorio debe conservarse entre reinicios. Si se pierde, Caddy pide todos los certificados de nuevo y puede agotar los límites de Let’s Encrypt.
Cómo lo aborda KHARONTE
Un servidor web es una pieza dentro de una cadena: el servidor donde corre, la red que lo separa del resto y el firewall que deja entrar las visitas. Esa cadena es nuestro trabajo. En la línea de infraestructura de TI dimensionamos, implementamos y administramos los servidores y las máquinas virtuales donde viven herramientas como esta. Además, en la línea de redes y conectividad nos ocupamos del firewall perimetral, con sus reglas y la publicación de servicios, la segmentación por VLAN y las VPN.
Cada cambio entra como caso en nuestra mesa de servicio TI, con su criticidad y su historial. No comercializamos los equipos.
Si prefiere un técnico dedicado a su plataforma, lo ofrecemos como outsourcing de infraestructura de TI. Y si busca servicios administrados de TI que reúnan los servidores, la red y el soporte, conozca el resto de nuestros servicios de TI para empresas.




