Files
tera/deploy/STATIC.md
T
Karti Tripathi 8bcb391455 Deploy notes for the static map, now that one is actually serving
tera.lumbridgecorp.com is live and the Phaser 2D world at world1 is retired —
301 to Tera, containers stopped rather than removed so the decision is
reversible for as long as the images exist.

Worth writing down what the deploy actually needs, because it is almost nothing:
a file server and a default-src 'self' policy. No API, no keys, no account. The
one non-obvious header is img-src needing data: and blob:, and that is a
consequence of a licensing choice rather than a technical one — every texture is
drawn on a canvas at runtime because a texture that is code has no provenance
question.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 00:20:30 -07:00

50 lines
1.7 KiB
Markdown

# Hosting the static build
Tera's map view is a static bundle. It makes **no network calls at all** — the
sun is computed locally by `src/engine/solar.ts`, the traffic is simulated, and
the office is a data file — so it needs a file server and nothing else. No API,
no keys, no account.
```bash
npm ci
npm run build # -> dist/
```
Serve `dist/` from anything. A Content-Security-Policy of `default-src 'self'`
is sufficient; the build references no external fonts, CDNs or images.
## Caddy
```
tera.example.com {
root * /var/www/tera
encode zstd gzip
try_files {path} {path}/index.html /index.html
file_server
header {
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'"
}
}
```
`try_files … /index.html` matters if you add client-side routes later: without
it a route that exists only in JavaScript 404s for anyone who types it or
refreshes on it.
`img-src` needs `data:` and `blob:` because every texture in the asset library
is drawn on a canvas at runtime rather than shipped as a file — see
ARCHITECTURE.md §3.1 for why that is a licensing decision and not a technical
one.
## Serving the API too
Only needed for live weather, real ADS-B, or markers from an external source.
The map runs fully without it. See `deploy/tera-api.service`,
`deploy/Caddyfile.snippet` and `deploy/docker-compose.yml`.
## Base path
Deployed at a subdomain root, no configuration is needed. Under a subpath, set
`TERA_BASE` at build time (`TERA_BASE=/tera/ npm run build`) — the trailing
slash matters, since every asset URL resolves against it.