# Filtre dels registres: IP escapçada, sense query i sense els noms de # professor o assignatura de la URI. Comproveu-lo en desplegar amb una petició # de prova (DESPLEGAMENT.md): una configuració vàlida no vol dir que filtri. (format-registres) { format filter { request>remote_ip ip_mask 24 48 request>client_ip ip_mask 24 48 request>headers>X-Forwarded-For delete request>uri multi_regexp { regexp "[?].*$" "" # Substitucions: absències, hores-professor i assignació manual; # Estadístiques: detall del professor. regexp "^(/api/(?:substitucions/[^/]+/[^/]+|estadistiques/professor)/).+$" "${1}{professor}" regexp "^(/api/config/assignatures/[^/]+/).+$" "${1}{nom}" regexp "^(/api/prioritats/no-substituir/).+$" "${1}{assignatura}" } wrap json } } { # El filtre també s'aplica als errors interns de Caddy amb una petició. log default { import format-registres } } el-teu-domini.exemple.com { encode zstd gzip # Access log persistent. # # Sense aquest bloc, l'únic registre de peticions són els logs del # contenidor (`docker compose logs`), que es perden cada cop que es # reconstrueix la imatge — és a dir, a cada desplegament. Escriure'l a un # volum del host permet revisar a posteriori l'activitat del servidor. # El `docker-compose.yml.example` ja hi munta `./logs/caddy`. # # Les adreces IP es desen escapçades (vegeu `format filter`), de manera que # el registre no identifica ningú. Els fitxers rotats es conserven com a màxim 30 dies (720 h), # també limitats a 10 còpies. El filtre treu la query i els noms de la URI. log { output file /var/log/caddy/access.log { roll_size 10MiB roll_keep 10 roll_keep_for 720h } # Sense l'adreça IP sencera: només la xarxa (83.45.127.19 → 83.45.127.0), # que no identifica ningú i permet comptar visites aproximades. import format-registres } header { X-Frame-Options "SAMEORIGIN" X-Content-Type-Options "nosniff" # Filtre XSS antic dels navegadors, desactivat: la CSP en fa la feina X-XSS-Protection "0" Referrer-Policy "strict-origin-when-cross-origin" # Sempre per https durant un any (només aquest domini, no els subdominis) Strict-Transport-Security "max-age=31536000" # Només es pot carregar codi, estils i dades del mateix domini. Si # afegiu recursos externs (fonts, analítiques...), cal afegir-los aquí. Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'" Permissions-Policy "camera=(), microphone=(), geolocation=()" # No anunciar quin programari hi ha al darrere -Server -Via } # Memòria cau: les dades de l'API no es guarden mai al navegador (ordinadors # compartits); els fitxers amb hash al nom no canvien mai; l'HTML es revalida # sempre, perquè després d'un desplegament apunti als fitxers nous. @api path /api/* @assets path /assets/* @html not path /api/* /assets/* header @api >Cache-Control "no-store" header @assets >Cache-Control "public, max-age=31536000, immutable" header @html >Cache-Control "no-cache" # Les pujades (XML d'horari, logo, CSV) són petites request_body { max_size 10MB } handle /api/* { reverse_proxy backend:8000 { header_down -Server } } handle { reverse_proxy frontend:80 { header_down -Server } } }