__HOST__ root * /opt/waving-hands/build encode gzip zstd header { Strict-Transport-Security "max-age=31536000" X-Content-Type-Options "nosniff" X-Frame-Options "DENY" Referrer-Policy "no-referrer" } log { output file /var/lib/caddy/access.log { roll_size 10MiB roll_keep 30 } } # The duel server answers the API and the websocket; a deploy restarts it for # a few seconds, and the proxy holds requests that land in that gap. @duel path /api/* /ws handle @duel { reverse_proxy localhost:8788 { lb_try_duration 30s lb_try_interval 250ms } } # Everything else is the static site. SvelteKit writes each route as # .html, so /rules is tried as /rules.html before falling back to the # app shell, which serves the rooms. Hashed assets under _app/immutable are # cached for a year; every other response is revalidated so a deploy shows # up on the next load. The two header matchers are disjoint. handle { @immutable path /_app/immutable/* header @immutable Cache-Control "public, max-age=31536000, immutable" @mutable not path /_app/immutable/* header @mutable Cache-Control "no-cache" try_files {path} {path}.html /index.html file_server }