diff options
| author | godosa <godosa@godosa.eu> | 2026-10-07 00:14:38 +0200 |
|---|---|---|
| committer | godosa <godosa@godosa.eu> | 2026-10-07 00:14:38 +0200 |
| commit | 3443c1c65e9f1753e1e656b35d08416c1fa298f2 (patch) | |
| tree | 4e43236f460145a4d75d1b4616dcb7aa6ef08f51 /deploy/README.md | |
| download | worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.tar.gz worldmap-viewer-3443c1c65e9f1753e1e656b35d08416c1fa298f2.zip | |
worldmap-viewer: initial public history
Diffstat (limited to 'deploy/README.md')
| -rw-r--r-- | deploy/README.md | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..4ce6a0a --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,101 @@ +# Public map server (container) + +A read-only map for anyone, on a small shared machine. Worlds are **built elsewhere** (a build needs far more memory +and time than serving) and copied over; the container holds only code. + +## 1. Build the image + +From the folder that holds `worldgen/` and `worldmap-viewer/`: + +```sh +podman build -f worldmap-viewer/deploy/Containerfile --ignorefile worldmap-viewer/deploy/.containerignore \ + -t worldmap-viewer . +``` + +`requirements.lock` pins the libraries the worlds were built and checked with (same numbers → the same tiles as on +the build machine). + +## 2. Copy a world + +```sh +python deploy.py bundle WORLD_DIR server:/srv/data/map/WORLD_NAME [--res N] # --dry-run lists it first +``` + +Copies `config/`, `places/regions.json` and `out/r<N>/`, leaving out: + +- pins, exports, lore notes and build inputs, which a public server never serves; +- refined areas and tiles of earlier builds. + +It uses `rsync -a`, which keeps modification times. The build fingerprint depends on them; without them, the +server would rebuild every refined area. Nothing is deleted on the server: it prunes what it no longer uses at +start, and keeps the tiles it rendered. + +Then, on the server, let the eras' serve caches share their identical blocks again (a copy loses that; ≈ half +their size on btrfs or reflink XFS): + +```sh +podman exec worldmap-viewer python deploy.py dedupe /data/WORLD_NAME +``` + +Data disk: btrfs with `compress=zstd:1`, normal copy-on-write (no `chattr +C`/`nodatacow`: that turns off both +compression and block sharing). Back up nothing under `out/`: it can all be copied again. + +## 3. Run it + +Settings come from `WORLDMAP_<OPTION>` variables (every `serve.py` option; a command-line flag wins). The image +sets `WORLDMAP_PUBLIC=1`, `WORLDMAP_BIND=0.0.0.0`, `WORLDMAP_PORT=8765`. + +| Variable | Meaning | +|---|---| +| `WORLDMAP_WORLD` | world folder(s) in the container, comma separated (the first opens by default) | +| `WORLDMAP_RES` | build resolution to serve | +| `WORLDMAP_ALLOW_HOST` | the public name(s) the proxy passes on, e.g. `maps.example.org` | +| `WORLDMAP_WORKERS` | render processes (≈ one core each while rendering) | +| `WORLDMAP_MAX_RENDERS` | tiles rendering or waiting at once; more → 503 + `Retry-After` (default 4 × workers) | +| `WORLDMAP_TILE_CACHE_GB` | cap on saved tiles; the least recently used go first | +| `WORLDMAP_TILE_KEEP_Z` | relief + mesh tiles to this zoom are never deleted nor counted (a shipped prerender) | + +Example Quadlet (`/etc/containers/systemd/worldmap-viewer.container`). This sizing is for a 4-core, 16 GB machine shared +with other services: + +```ini +[Unit] +Description=Public world map + +[Container] +Image=localhost/worldmap-viewer:latest +ContainerName=worldmap-viewer +Volume=/srv/data/map:/data:Z +Environment=WORLDMAP_WORLD=/data/world-a,/data/world-b,/data/world-c +Environment=WORLDMAP_ALLOW_HOST=maps.example.org +Environment=WORLDMAP_WORKERS=4 +Environment=WORLDMAP_TILE_CACHE_GB=140 +Environment=WORLDMAP_TILE_KEEP_Z=9 +PublishPort=127.0.0.1:8765:8765 +HealthCmd=python -c "import os, urllib.request as u; u.urlopen('http://127.0.0.1:' + os.environ['WORLDMAP_PORT'] + '/api/worlds', timeout=8)" +HealthStartPeriod=10m + +[Service] +MemoryHigh=7G +MemoryMax=8G +CPUWeight=50 +Restart=on-failure + +[Install] +WantedBy=multi-user.target +``` + +Keep `%` out of Quadlet lines: systemd expands `%s`, `%h` and the like (write `%%` for a literal `%`). The `HealthCmd` +above builds its URL without one. + +Leave `WORLDMAP_RES` unset when the worlds differ: each then serves its final build (world-a r5, the others r4). +A set `WORLDMAP_RES` applies to every world. + +The image runs as uid 8765. `/srv/data/map` must be writable by that user as the container maps it: the server +writes tiles and serve caches there. `:U` would do this, but it re-chowns every file at each start, which is slow +with millions of tiles. Set the ownership once instead. + +The first start after a new copy can take minutes, while the server loads or builds its serve caches. Ship them +built (they are part of `out/r<N>/`) and it starts in about half a minute. + +Single-disk machines: set a smaller `WORLDMAP_TILE_CACHE_GB` (e.g. 20). |
