1
0
This repository has been archived on 2026-08-25. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tera/deploy/STATIC.md
T

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.