Ctrl K
ComunidadGuías…

Caddyfile.example

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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
        }
    }
}