Caddyfile 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. # FrankenPHP Caddyfile for the ui container.
  2. # Serves Slim from public/ on :8080.
  3. {
  4. frankenphp
  5. order php_server before file_server
  6. auto_https off
  7. admin off
  8. servers {
  9. trusted_proxies static private_ranges
  10. }
  11. }
  12. :8080 {
  13. root * /app/public
  14. encode zstd gzip
  15. # ── Security headers (M14) ──────────────────────────────────────────
  16. header {
  17. -Server
  18. -X-Powered-By
  19. X-Content-Type-Options "nosniff"
  20. X-Frame-Options "DENY"
  21. Referrer-Policy "strict-origin-when-cross-origin"
  22. Permissions-Policy "geolocation=(), microphone=(), camera=()"
  23. # CSP for the ui:
  24. # - script-src needs 'unsafe-eval' for Alpine.js v3's Function()
  25. # constructor. Migrating to @alpinejs/csp would let us drop it
  26. # but requires rewriting every x-data="..." inline expression.
  27. # Documented trade-off.
  28. # - style-src 'unsafe-inline' for inline style attrs that drive
  29. # score bars and dynamic widths.
  30. # - img-src data: for inline SVG icons.
  31. Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
  32. }
  33. @prod expression `{env.APP_ENV} == "production"`
  34. header @prod Strict-Transport-Security "max-age=31536000; includeSubDomains"
  35. php_server
  36. }