Skip to main content

Directivas de Caddy (uso personal)


Apunte rápido para tener recogidas las directivas que uso hoy en día. Si añado más en el futuro, irán aquí.


Recordatorio: cómo importar snippets

En Caddy los snippets se definen entre paréntesis y luego se importan con import. Ventaja: evitan repetir configuraciones y mantienen el Caddyfile más limpio. Si un snippet cambia, la modificación se aplica automáticamente en todos los sitios donde se importe.

Ejemplo usando la directiva más corta (TLS estricto), con un sitio definido para mostrar la estructura completa:

(tls_estricto) {
    tls {
        protocols tls1.3
    }
}

# Ejemplo ficticio de uso de imports
blog.ejemplo.org {
    import tls_estricto
    import seguridad_basica
    import log_json_global

    reverse_proxy http://10.0.0.5:8080 {
        import ip_headers
    }
}

Authentik

Snippet para preautenticación y proxy de assets. Asegura que todas las rutas pasen por Authentik y copia claims útiles.

(authentik) {
    reverse_proxy /outpost.goauthentik.io/* http://IP_INTERNO_AUTHENTIK:PUERTO

    forward_auth http://IP_INTERNO_AUTHENTIK:PUERTO {
        uri /outpost.goauthentik.io/auth/caddy

        copy_headers {
            X-Authentik-Username
            X-Authentik-Email
            X-Authentik-Groups
            X-Authentik-Name
            X-Authentik-Uid
        }

        header_up X-Real-IP {client_ip}
        header_up X-Client-IP {client_ip}
    }
}

TLS estricto

Snippet para forzar que todo vaya con TLS 1.3. Evita negociar versiones anteriores.

(tls_estricto) {
    tls {
        protocols tls1.3
    }
}

Seguridad básica

Cabeceras básicas de seguridad que suelo meter para endurecer la configuración.

(seguridad_basica) {
    header {
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "strict-origin-when-cross-origin"
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    }
}
  • X-Frame-Options: SAMEORIGIN → Evita que embeban la web en iframes externos.

  • X-Content-Type-Options: nosniff → Bloquea detección automática de tipo.

  • Referrer-Policy: strict-origin-when-cross-origin → Controla qué se envía en Referer.

  • Strict-Transport-Security → Obliga HTTPS y permite preload en navegadores.


IP real en headers

Útil para que los servicios backend reciban la IP del cliente en lugar de la del proxy.

(ip_headers) {
    header_up X-Real-IP {client_ip}
    header_up X-Client-IP {client_ip}
    header_up -X-Forwarded-Port
    header_up X-Forwarded-Port 443
}

Registro de logs en JSON

Genera logs en formato JSON. En mi caso lo uso para CrowdSec, pero puede adaptarse a cualquier otra necesidad (centralizar logs, enviar a un SIEM, etc.).

(log_json_global) {
    log {
        output file /var/log/caddy/crowdsec-global.json
        format json
        level INFO
    }
}

Errores comunes

  • Poner import fuera del bloque del sitio → no funciona, siempre debe ir dentro.
  • Reutilizar el mismo nombre en dos snippets → Caddy solo acepta uno, el último pisa al anterior.
  • Olvidar importar un snippet en un sitio concreto → el sitio queda sin la configuración esperada (ej. sin TLS estricto o sin logs).
  • Colocar import después de una directiva que dependa de él → puede dar lugar a comportamientos inesperados.