This commit is contained in:
parent
fb2f6079cc
commit
934c94cb5c
50 changed files with 10464 additions and 758 deletions
|
|
@ -1,21 +1,97 @@
|
|||
# catcrafts.net Caddy site block
|
||||
#
|
||||
# The WASM app (Crafter.Graphics) needs a cross-origin-isolated context
|
||||
# (SharedArrayBuffer / threads), which requires these response headers. They
|
||||
# are NOT optional — without them the page loads but the runtime fails.
|
||||
# Two upstreams: Caddy's file_server for build artifacts, and catcrafts-server
|
||||
# for everything else. Point `root` at the host directory you bind-mount into
|
||||
# the runner as /deploy (the "-v /path/to/webroot:/deploy" in the runner's
|
||||
# config.yaml).
|
||||
#
|
||||
# If you already have a `catcrafts.net { ... }` block, you only need to ADD the
|
||||
# three Cross-Origin-* header lines to it. This file is the complete block for
|
||||
# reference. Point `root` at the host directory you bind-mount into the runner
|
||||
# as /deploy (the "-v /path/to/webroot:/deploy" in the runner's config.yaml).
|
||||
# catcrafts-server speaks PLAINTEXT HTTP/1.1 on localhost — Caddy terminates
|
||||
# TLS. That is also why the backend uses Crafter.Network's ListenerHTTP1 rather
|
||||
# than its HTTP/3 listener: Caddy cannot reverse_proxy to an h3 upstream.
|
||||
# Do not expose port 8081 directly.
|
||||
|
||||
catcrafts.net {
|
||||
root * /srv/catcrafts.net
|
||||
|
||||
header Cross-Origin-Opener-Policy "same-origin"
|
||||
header Cross-Origin-Embedder-Policy "require-corp"
|
||||
header Cross-Origin-Resource-Policy "same-origin"
|
||||
|
||||
encode zstd gzip
|
||||
file_server
|
||||
|
||||
header {
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
X-Content-Type-Options "nosniff"
|
||||
-Server
|
||||
}
|
||||
|
||||
# ── cross-origin isolation, scoped ────────────────────────────────────
|
||||
#
|
||||
# The WASM runtime needs a cross-origin-isolated context (SharedArrayBuffer
|
||||
# / threads), and these three headers are what provide it. They are NOT
|
||||
# optional on a page that boots the module — without them it loads and the
|
||||
# runtime fails.
|
||||
#
|
||||
# But they are scoped to the paths that actually load it, rather than applied
|
||||
# site-wide. COEP: require-corp blocks every cross-origin subresource that
|
||||
# does not opt in, so applying it to pages that have no wasm would constrain
|
||||
# them for no benefit — and the shop's payment pages later must not inherit
|
||||
# that restriction.
|
||||
@isolated path /demos/* /catcrafts*.wasm /runtime.js /dom-env.js /dom-webgpu.js \
|
||||
/catcrafts-head.js /files.json /variants.json /*.wgsl
|
||||
header @isolated {
|
||||
Cross-Origin-Opener-Policy "same-origin"
|
||||
Cross-Origin-Embedder-Policy "require-corp"
|
||||
Cross-Origin-Resource-Policy "same-origin"
|
||||
}
|
||||
# Subresources an isolated document pulls in must carry CORP themselves.
|
||||
header /styles.css Cross-Origin-Resource-Policy "same-origin"
|
||||
header /favicon.svg Cross-Origin-Resource-Policy "same-origin"
|
||||
|
||||
# ── build artifacts: served from disk ─────────────────────────────────
|
||||
#
|
||||
# file_server does sendfile, precompressed variants and range requests far
|
||||
# better than the backend would. `precompressed` serves the .zst / .gz
|
||||
# siblings the CI build produces, so the ~800 KB module is never recompressed
|
||||
# per request. Cache-busted by the ?v=<buildId> in index.html.
|
||||
@static path /catcrafts*.wasm /runtime.js /dom-env.js /dom-webgpu.js \
|
||||
/catcrafts-head.js /files.json /variants.json /styles.css \
|
||||
/favicon.svg /robots.txt /*.wgsl /*.jpg /posts.json /rates.json
|
||||
handle @static {
|
||||
header Cache-Control "public, max-age=31536000, immutable"
|
||||
file_server {
|
||||
precompressed zstd gzip
|
||||
}
|
||||
}
|
||||
|
||||
# ── mirrored post media ──────────────────────────────────────────────
|
||||
#
|
||||
# Deliberately NOT under the web root: that directory is mirrored with
|
||||
# `rsync --delete` on every deploy, and this media is not always
|
||||
# reproducible — if a source instance deletes a file, our copy is the only
|
||||
# one left. Living on the app mount puts it physically outside the delete.
|
||||
#
|
||||
# Filenames are the content hash, so a changed file gets a new name and the
|
||||
# immutable cache lifetime is honest.
|
||||
handle_path /media/* {
|
||||
root * /srv/catcrafts-app/media
|
||||
header Cache-Control "public, max-age=31536000, immutable"
|
||||
file_server
|
||||
}
|
||||
|
||||
# ── everything else: server-rendered ─────────────────────────────────
|
||||
#
|
||||
# Pages, /feed.xml, /sitemap.xml and later /api/*. The backend sets its own
|
||||
# Cache-Control and returns real status codes — a 404 for an unknown path and
|
||||
# a 301 for the retired /blog URLs, which a client-side router cannot do.
|
||||
handle {
|
||||
reverse_proxy 127.0.0.1:8081 {
|
||||
health_uri /api/healthz
|
||||
|
||||
# If the backend is down, fall back to the static wasm shell so the
|
||||
# site degrades to a client-rendered app rather than a Caddy 502.
|
||||
# Content still renders; only real status codes and SSR are lost.
|
||||
@down status 502 503 504
|
||||
handle_response @down {
|
||||
rewrite * /index.html
|
||||
header Cache-Control "no-store"
|
||||
file_server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue