{ email {$ACME_EMAIL} } www.teeoff.no { redir https://teeoff.no{uri} permanent } # Gammelt domene (2026-08-05-flyttingen til teecup.golf) -- permanent # redirect fremfor å bare slutte å svare, slik at gamle bokmerker/delte # lenker/QR-koder på fysiske scorekort fortsatt havner riktig sted. teecup.teeoff.no { redir https://teecup.golf{uri} permanent } teecup.golf, www.teecup.golf { encode zstd gzip log { output stdout format console } # Sikkerhetshoder (sikkerhetsgjennomgang 2026-08-09, se # ARCHITECTURE_DECISIONS.md-tillegg). CSP-en er bevisst IKKE en streng # nonce-basert policy -- appen bruker inline `style`-attributter mange # steder (React `style={{...}}`, bl.a. den "clubhouse"-pallet-tonede # UI-en) og Next.js sin egen hydrerings-oppstart kan trenge inline # script, så 'unsafe-inline' er beholdt for script-src/style-src for å # unngå å knekke appen blindt. Verdien ligger likevel i det som ER # strammet inn: object-src/frame-ancestors/base-uri blokkerer hele # klasser av angrep, og connect-src/img-src er begrenset til KUN de # eksterne vertene appen faktisk bruker (Mapbox for slagmåling-kartet, # ADR-048) -- en fremtidig XSS-bug kan dermed ikke enkelt eksfiltrere # data til en vilkårlig tredjeparts-vert. header { X-Frame-Options "DENY" X-Content-Type-Options "nosniff" Referrer-Policy "strict-origin-when-cross-origin" Strict-Transport-Security "max-age=31536000; includeSubDomains" Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://api.mapbox.com; connect-src 'self' https://api.mapbox.com https://events.mapbox.com wss://teecup.golf; worker-src 'self' blob:; frame-ancestors 'none'; base-uri 'self'; object-src 'none'" } # Offentlig, anonym lesing av opplastede bilder (MinIO, public-read # bucket-policy) -- bucket-navnet ligger i selve stien (path-style # adressering), derav /teecup-media/* som prefiks, ikke et eget # subdomene (unngår en DNS-avhengighet som viste seg ikke å peke på # denne serveren -- se CLAUDE.md-status). handle /teecup-media/* { reverse_proxy teecup-minio:9000 } # WebSocket-trafikk (ADR-025, Kommunikasjon) -- rett til teecup_api, # IKKE via Next.js sin rewrites()/teecup_frontend. Next.js proxyer ikke # WebSocket-oppgraderinger pålitelig i "standalone"-modus; Caddy sin # reverse_proxy håndterer Upgrade-headeren transparent uten egen config. handle /ws/* { reverse_proxy teecup_api:8000 } handle { reverse_proxy teecup_frontend:3000 } } teeoff.no { encode zstd gzip log { output stdout format console } # This upload route is implemented in Next.js, not FastAPI. handle /api/admin/uploads/images* { reverse_proxy frontend:3000 } # All other /api traffic goes to the FastAPI backend. # Use handle, not handle_path, so the /api prefix is preserved. handle /api/* { reverse_proxy api:8000 } # Everything else is served by Next.js. handle { reverse_proxy frontend:3000 } }