76 lines
3.5 KiB
Caddyfile
76 lines
3.5 KiB
Caddyfile
# Caddy config for serving the standalone Nosterm client SPA.
|
|
#
|
|
# In production, replace `:80` with your domain to get automatic HTTPS, e.g.:
|
|
# nosterm.example.com { ... }
|
|
#
|
|
# The `/relay*` proxy is OPTIONAL. It lets the client reach a relay on the same
|
|
# origin (ws://<host>/relay), which sidesteps mixed-content and CORS concerns.
|
|
# The upstream is configurable via the RELAY_UPSTREAM env var (default
|
|
# `relay:3334`, the service name in this dir's docker-compose.yml). If you point
|
|
# the client directly at an external relay via PUBLIC_DEFAULT_RELAYS, you can
|
|
# delete the `handle /relay*` block.
|
|
|
|
:80 {
|
|
encode gzip zstd
|
|
|
|
# Tor-overlay relay bridge: proxy to a clearnet→onion bridge sidecar that
|
|
# forwards through Tor to an onion-only relay. Exposing it at a same-origin
|
|
# wss:// path lets a plain browser reach the onion relay without Tor Browser
|
|
# and without an HTTPS-page/insecure-ws mixed-content block. Only wired when
|
|
# RELAY_TOR_UPSTREAM is set (the demo deploy sets it); otherwise it points at
|
|
# a dead default and simply 502s, which is harmless if unused. MUST precede
|
|
# the /relay* block below, which would otherwise swallow this prefix.
|
|
handle /relay-tor* {
|
|
reverse_proxy {$RELAY_TOR_UPSTREAM:tor-bridge:3335}
|
|
}
|
|
|
|
# Home relay: proxy WebSocket + NIP-11 requests to the configured relay.
|
|
handle /relay* {
|
|
reverse_proxy {$RELAY_UPSTREAM:relay:3334}
|
|
}
|
|
|
|
# Runtime client config: regenerated by the entrypoint from env on startup.
|
|
# Never cache it so per-deployment relay changes take effect immediately.
|
|
handle /config.json {
|
|
root * /srv
|
|
header Cache-Control "no-store"
|
|
file_server
|
|
}
|
|
|
|
# Everything else: serve the static SPA with client-side-routing fallback.
|
|
handle {
|
|
root * /srv
|
|
try_files {path} /index.html
|
|
file_server
|
|
}
|
|
|
|
# Baseline security headers. No third-party analytics are ever included.
|
|
header {
|
|
X-Content-Type-Options nosniff
|
|
X-Frame-Options DENY
|
|
Referrer-Policy no-referrer
|
|
|
|
# Content-Security-Policy for a client-only SPA:
|
|
# - default-src 'self' only same-origin by default
|
|
# - connect-src wss:/ws: reach ANY relay the user configures (core)
|
|
# - connect-src https: NIP-05 verification fetches a domain's
|
|
# /.well-known/nostr.json over HTTPS. Read-only
|
|
# JSON GETs; no credentials are ever sent.
|
|
# - script-src 'unsafe-inline' required for SvelteKit's hydration
|
|
# bootstrap + the anti-FOUC theme script,
|
|
# which are inlined into the static fallback
|
|
# page (not prerendered, so hashes cannot be
|
|
# pinned at build time).
|
|
# - script-src 'unsafe-eval' required by NDK's event-emitter dependency
|
|
# (tseep), which JIT-compiles listener
|
|
# dispatch via `new Function`. Only triggers
|
|
# once a relay subscription opens. No REMOTE
|
|
# scripts are ever allowed, and remote Nostr
|
|
# content is never rendered as HTML, so it
|
|
# cannot inject code.
|
|
# - object-src 'none' no plugins
|
|
Content-Security-Policy "default-src 'self'; connect-src 'self' wss: ws: https:; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
|
|
-Server
|
|
}
|
|
}
|