Volver al blog
Agosto 19, 2026Guías

Cómo instalar el servidor web Caddy con HTTPS automático

Instalar Caddy en Ubuntu desde el repositorio oficial, escribir un Caddyfile para sitios estáticos y proxies inversos, entender los certificados automáticos, systemd, los registros y los errores habituales al migrar desde Nginx.

Cómo instalar el servidor web Caddy con HTTPS automático

Caddy es un servidor web que obtiene y renueva certificados TLS por defecto. En un VPS pequeño que aloja uno o dos dominios, eso elimina toda una clase de temporizadores Certbot y ficheros de fragmentos Nginx. El lenguaje de configuración (Caddyfile) es breve. Proxy inverso, gzip y HTTP/2 son funciones normales, no un fin de semana de módulos extra.

Nginx sigue siendo la elección correcta para algunos equipos: ya tenéis configs de batalla o necesitáis un módulo muy concreto. Esta guía es para el otro caso frecuente: quieres HTTPS que funcione en un VPS Hiddence nuevo sin memorizar fragmentos include. Instalaremos Caddy desde el repositorio apt oficial, explicaremos cómo habla con Let's Encrypt, serviremos un sitio estático, haremos proxy de una aplicación local, alojaremos varios dominios, veremos los registros y cubriremos las peleas habituales por el puerto 80 con Apache o un Nginx antiguo.

Cuándo encaja bien Caddy

El HTTPS automático es el titular, pero la ganancia diaria son menos piezas móviles. Caddy escucha en 80 y 443, redirige HTTP a HTTPS y guarda certificados en su directorio de datos. Sigues necesitando un dominio que apunte al VPS. Sigues sin poder romper ACME (cortafuegos 80/tcp, ningún otro proceso robando :80). Los certificados comodín necesitan un módulo de proveedor DNS: es un camino más largo que un certificado de un solo host.

  • Redirección HTTP→HTTPS automática y renovación de certificados
  • Caddyfile legible en lugar de bloques server largos
  • Proxy inverso capaz para Node, Python, PHP-FPM con config extra, o backends Docker
  • HTTP/2 y valores TLS modernos sin una hoja de cifrados
  • Unidad systemd del paquete oficial

Requisitos

Un dominio debe resolver a este VPS antes de que Caddy pueda demostrar ACME HTTP-01. Si el DNS aún se propaga, Caddy fallará la emisión y reintentará; parece que «Caddy está roto» cuando solo es DNS. Detén Apache o Nginx primero si poseen 80/443.

  • Ubuntu 22.04 o 24.04
  • Un registro A del dominio a la IP del VPS (y AAAA si usas IPv6)
  • Puertos 80 y 443 libres y permitidos en el cortafuegos
  • Root o sudo

Paso 1: Instalar Caddy desde el repositorio oficial

No instales un Caddy viejo al azar del universo Ubuntu si quieres comportamiento TLS y ACME actual. El proyecto Caddy documenta una fuente apt. Tras instalar, existe el usuario caddy y el servicio está habilitado.

bash
ssh root@YOUR_VPS_IP
apt update && apt -y install debian-keyring debian-archive-keyring apt-transport-https curl gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list

apt update
apt -y install caddy

caddy version
systemctl status caddy --no-pager

Paso 2: Primer Caddyfile: sitio estático

El Caddyfile por defecto es /etc/caddy/Caddyfile. Sustitúyelo por tu dominio. Caddy intentará obtener un certificado en cuanto cargue la configuración si el nombre de host no es localhost. Pon los ficheros del sitio en un directorio legible por el usuario caddy (a menudo permisos al estilo www-data, pero el paquete usa el usuario caddy).

bash
mkdir -p /var/www/example
echo '<h1>It works</h1>' > /var/www/example/index.html
chown -R caddy:caddy /var/www/example

cat >/etc/caddy/Caddyfile <<'EOF'
example.com {
    root * /var/www/example
    file_server
    encode gzip
}
EOF

caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy

# Watch issuance:
journalctl -u caddy -f

Paso 3: Proxy inverso de una aplicación local

Si Gunicorn, Node o Docker escuchan en 127.0.0.1:8000, Caddy debe ser el único proceso público. La directiva reverse_proxy reenvía Host y las cabeceras X-Forwarded-* de forma razonable para la mayoría de las aplicaciones. Si la aplicación genera URL HTTP absolutas, configura las opciones de proxy de confianza / HTTPS en la aplicación (Django SECURE_PROXY_SSL_HEADER, Express trust proxy, etc.).

bash
app.example.com {
    encode gzip
    reverse_proxy 127.0.0.1:8000
}

# Several hosts in one file are normal:
# blog.example.com {
#     root * /var/www/blog
#     file_server
# }

Paso 4: Cortafuegos y systemd

Permite 80 y 443. La unidad de Caddy es caddy.service; un reload basta tras editar el Caddyfile si el proceso está sano. Si cambias variables de entorno de un plugin DNS, un reinicio completo es más claro. Los certificados viven por defecto en /var/lib/caddy/.local/share/caddy/: incluye esa ruta en las copias si te importan los límites de tasa en una reinstalación.

bash
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

systemctl enable --now caddy
systemctl reload caddy

# Backup cert storage (path may vary slightly by version):
ls -la /var/lib/caddy/

Paso 5: Registros, compresión y cabeceras

Los registros de acceso ayudan cuando un bot machaca una ruta o cuando depuras 404. Puedes registrar por sitio. Añade cabeceras de seguridad si alojas una aplicación de navegador; no copies un paquete enorme de cabeceras sin entender HSTS (una vez fijas un max-age largo, los navegadores lo recuerdan).

bash
example.com {
    root * /var/www/example
    file_server
    encode gzip
    log {
        output file /var/log/caddy/example.log
    }
    header {
        X-Content-Type-Options nosniff
        Referrer-Policy no-referrer-when-downgrade
        -Server
    }
}

mkdir -p /var/log/caddy
chown caddy:caddy /var/log/caddy
systemctl reload caddy

Paso 6: PHP y otros extras

Caddy puede hablar con PHP-FPM con la directiva php_fastcgi. Basta para muchos alojamientos WordPress o Laravel, pero sigues necesitando php-fpm instalado y una ruta de socket que coincida. Si ya tienes un config PHP de Nginx perfecto, migrar en una tarde es opcional: Caddy brilla más en proxy inverso + estático + TLS automático.

bash
example.com {
    root * /var/www/example
    php_fastcgi unix//run/php/php8.3-fpm.sock
    file_server
}

# Confirm FPM is running:
systemctl status php8.3-fpm

Migrar desde Nginx sin sorpresas de interrupción

Detén Nginx antes de arrancar Caddy o pelearán por 80/443. Baja el TTL de DNS el día anterior si también cambias de IP. Prueba con curl --resolve para golpear el VPS nuevo antes de cambiar el registro A. Conserva los configs de Nginx en git una semana por si hay que volver atrás.

  • systemctl stop nginx && systemctl disable nginx
  • Instalar Caddy, validar el Caddyfile, arrancar Caddy
  • curl -I --resolve example.com:443:NEW_IP https://example.com
  • Solo entonces cambia el DNS si la IP es nueva
  • La reemisión es automática; no ejecutes también Certbot contra el mismo nombre de host

Resolución de problemas

Los fallos ACME casi siempre son DNS, cortafuegos u otro servicio en el puerto 80. Las líneas de registro de Caddy mencionan tls.obtain. Si el sitio funciona en HTTP pero no en HTTPS, la emisión nunca terminó. Si ves demasiados certificados, has chocado con los límites de tasa de Let's Encrypt: usa la CA de pruebas al ensayar, no la de producción.

  • validate falla: sintaxis del Caddyfile, llave que falta
  • permission denied en root: chown caddy para el directorio del sitio
  • bind: address already in use — ss -tulpn | grep -E ':80|:443'
  • tiempo de espera del certificado: dig +short del dominio desde el VPS, ufw allow 80
  • 502 reverse_proxy: backend caído, o proxiaste a localhost desde una red de contenedores de forma incorrecta

Notas de seguridad

Los valores TLS por defecto de Caddy son conservadores. Tu trabajo es la seguridad de la aplicación y SSH. No actives la API de administración de Caddy en una interfaz pública. El punto de administración por defecto es local; déjalo así. Si usas un Caddyfile de internet, lee cada matcher: un fragmento que hace reverse_proxy de /* a una IP interna puede convertirse en un proxy abierto.

  • No expongas la API de administración
  • Mantén el paquete actualizado
  • HSTS solo cuando estés seguro de que HTTPS funciona en todos los nombres de host
  • Separa nombres de host de prueba y de producción para proteger los límites de tasa ACME

Consejos

  • caddy fmt --overwrite /etc/caddy/Caddyfile mantiene el fichero legible
  • Usa fragmentos import cuando tengas muchos sitios similares
  • En Docker es habitual la imagen caddy:alpine con un Caddyfile montado
  • Los certificados comodín necesitan un módulo DNS y un token de API: protege ese token
  • Lee journalctl -u caddy antes de reescribir todo el fichero

Caddy en un VPS es: paquete oficial, un Caddyfile corto, puertos 80/443 abiertos, DNS ya apuntando al servidor y reload de systemd tras los cambios. Úsalo como servidor de ficheros estáticos o como proxy inverso delante de Gunicorn, Node o Docker. El HTTPS automático funciona cuando ACME puede responder en el puerto 80; si falla la emisión, corrige DNS y conflictos de puertos antes de culpar a Caddy. Haz copia de /var/lib/caddy si reinstalas a menudo.