Optimizando aplicaciones web con Caddy

2025–02–06

Hace unos meses escribi el artículo Como he creado mi sitio web con barf, mostrando que facil es construir tu propio sitio web o blog personal, tomando barf y caddy como herramientas.

Hoy quiero hacer otro artículo, explicare como optimizar tu sitio web, añadiendo algunas de las mejores practicas que mejoraran la seguridad, contra algunos ataques maliciosos, la privacidad, tambien la usabilidad y experiencia de tu sitio web, blog, o aplicaciones web.

Para hacer la configuración de nuestro servidor proxy Caddy, tenemos que abrir el archivo /etc/caddy/Caddyfile con el editor de terminal de su elección (ejemplo nano) y seguir los pasos.

Añadiendo Security headers (cabeceras de seguridad)

(security_headers) {
    header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Content-Security-Policy "default-src 'self';"
        Referrer-Policy "strict-origin"
        Permissions-Policy "camera=(), microphone=()"
   }
}

Explicacion:

Un sitio con habilitado HSTS ayuda a proteger de los siguientes ataques realizados por un atacante.

El valor max-age=31536000; includeSubDomains; preload" significa que (HSTS) se aplica al dominio del host, y todos los subdominios, permaneciendo en vigor un un año.

Es aconsejable asignar a la directiva max-age un valor no menos de 31536000 (un año).

Referencias: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security

Puedes registrar tu dominio en https://hstspreload.org/#submission-form .

El valor nosniff bloquea una petición si el destino de la petición es de tipo style y el tipo MIME no es text/css, o de tipo script y el tipo MIME no es un tipo MIME JavaScript.

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options

El valor DENY hace que la página no puede mostrarse en un <frame>, aunque el sitio lo intente.

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options

El valor default-src 'self'; define la política por defecto para la obtención de recursos como JavaScript, imágenes, CSS, fuentes, solicitudes AJAX, marcos, HTML5 Media. Permite cargar recursos desde el mismo origen (mismo sistema, host y puerto).

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP

El valor strict-origin envia el origen solo cuando el nivel de seguridad del protocolo permanezca igual (HTTPS→HTTPS). No envia la cabecera Referer a destinos menos seguros (HTTPS→HTTP).

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

Ejemplo:

Restringe el uso de dispositivos sensibles como la cámara, el micrófono, geolocalización …

Referencia: https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy

Comprobar las encabezadas de noesto sitio, ejemplo con mi sitio web.

Activar el registro de acceso

Los registros de errores pueden proporcionar detalles sobre los problemas y errores que se producen en su sitio web, por esto es muy recomendable activar esta opcion.

Instalar Caddy transform-encoder modulo:

$ sudo caddy add-package github.com/caddyserver/transform-encoder

Añadir estas lineas en tu Caddyfile:

(logging) {
  log {
      output file /var/log/caddy/access.log
      format transform `{request>remote_ip} - {user_id} [{ts}] "{request>method} {request>uri} {request>proto}" {status} {size} "{request>headers>Referer>[0]}" "{request>headers>User-Agent>[0]}"` {
      time_format "02/Jan/2006:15:04:05 -0700"
      }
  }
}

Puedes ver como inspeccionar estos registros con goaccess, tengo una publicacion sobre esto Inspeccionar los registros de Caddy con GoAccess.

Control de errores

Puedemos decirle a Caddy qué hacer con los errores HTTP específicos. En este ejemplo, reenviaremos todo el tráfico 404 a una página /404 designada para cada sitio web utilizando este fragmento.

handle_errors {
     @404 {
        expression {http.error.status_code} == 404
   }

   rewrite @404 /404/index.html
   file_server
}

Ejemplo con mi sitio web https://ivaylokuzev.eu/estapaginanoexiste.

Si no queremos usar una pagina 404 personalizada, podemos hacer que caddy el propio servidor responda con mensaje de error, poniendo esto.

handle_errors {
    respond "{http.error.status_code} {http.error.status_text}"
}

Añadir avisos por correo sobre el estado de los certificados de sitio web

Se utiliza principalmente para crear una cuenta ACME con su CA, y es muy recomendable en caso de que haya problemas con sus certificados.

{
    email admin@dominio.com
}

Referencia: https://caddyserver.com/docs/caddyfile/options#email

Configuración del directorio

dominio.com {
   import logging
   import security_headers
   encode gzip zstd
   root * /var/www/dominio.com
   file_server
}

Breve explicacion:

Poner todo en uno

Al final el archivo de configuracion:

{
   email admin@dominio.com
}

(logging) {
  log {
      output file /var/log/caddy/access.log
      format transform `{request>remote_ip} - {user_id} [{ts}] "{request>method} {request>uri} {request>proto}" {status} {size} "{request>headers>Referer>[0]}" "{request>headers>User-Agent>[0]}"` {
      time_format "02/Jan/2006:15:04:05 -0700"
      }
  }
}

(security_headers) {
    header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Content-Security-Policy "default-src 'self';"
        Referrer-Policy "strict-origin"
        Permissions-Policy "camera=(), microphone=()"
   }
}

dominio.com {
   import logging
   import security_headers
   encode gzip zstd
   root * /var/www/dominio.com
   file_server

   # Handle errors status code 404
   handle_errors {
     @404 {
        expression {http.error.status_code} == 404
   }

   rewrite @404 /404/index.html
   file_server
   }
}

Este artículo fue inspirado de Caddy Ninja por Bradley Taunt que describe como configurar un servidor web HTTPS con Caddy en Alpine Linux.