62 lines
2.5 KiB
Markdown
62 lines
2.5 KiB
Markdown
# Hosting the static build
|
|
|
|
Tera's map view is a static bundle that needs a file server and nothing else.
|
|
No API, no keys, no account: the sun and moon are computed locally by
|
|
`src/engine/solar.ts`, the traffic is simulated, the minimap is drawn from the
|
|
city pack, and the office is a data file.
|
|
|
|
It does make **two** requests at boot, and both are meant to fail on a plain
|
|
static host: `GET /api/v1/health` and `GET /api/v1/session`, which is how
|
|
`src/access.ts` works out whether this deployment has accounts at all. Nothing
|
|
answering means nothing to sign in to, so the visitor gets the full public
|
|
experience and no sign-in link — see that file's header for why an *unreachable*
|
|
API and an API that answered `5xx` are deliberately not the same case. Your
|
|
server log will show two 404s per load; that is the zero-config path working,
|
|
not a misconfiguration.
|
|
|
|
```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'"
|
|
# Screen sharing remains a per-action browser prompt. Webcam capture stays
|
|
# disabled until that separate feature is deliberately deployed.
|
|
Permissions-Policy "display-capture=(self), camera=(), microphone=(), geolocation=(), payment=(), usb=()"
|
|
}
|
|
}
|
|
```
|
|
|
|
`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.
|