feat(train): the instance's own map tiles, drawn by Train's style (ADR 0030, D50)

Protomaps' basemap cut for Europe and served by pmtiles beside Train's server
(compose.maps.yaml), drawn by Train's own style, light and dark, which the
server serves. Only people signed in get tiles: map.source hands a key that
Caddy has the server check before each tile; nothing logs a tile.

Also fixes .dockerignore, which left apps/train/ out of the build context, so
Train's server's and BRouter's images couldn't have been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-29 16:04:05 +01:00
commit 190c3872f4
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

68
deploy/compose.maps.yaml Normal file
View file

@ -0,0 +1,68 @@
# The instance's own map for Halkyon Train (ADR 0030, D50), beside compose.train.yaml,
# which it needs: Protomaps' basemap cut for Europe, served by pmtiles as ordinary
# tiles, which Train's style (served by Train's server) draws. Switched on in .env:
#
# COMPOSE_FILE=compose.yaml:compose.train.yaml:compose.maps.yaml
# MAP_KEY_SECRET=<openssl rand -hex 32>
#
# Only people signed in to Train get tiles: Caddy asks Train's server about the key
# each tile comes with before passing it on (sidecars/train-maps.caddy). Neither
# logs a tile, as what was asked shows the area viewed. The cut (some 45 GB, to be
# measured) is in ./maps/tiles, renewed monthly, owned by a user ID of its own, which
# no person, no other container and not the CI runner uses. Setting it up:
# sidecars/README.md, Train's map.
services:
map-tiles:
build:
context: ..
dockerfile: deploy/maps/Dockerfile
image: halkyon-maps
restart: unless-stopped
user: "61178:61178"
read_only: true
volumes:
- ./maps/tiles:/tiles:ro
# Beside Caddy alone: no site of its own, no published port, no way out.
networks:
- tiles
mem_limit: 512m
# No log: a tile's address is where someone looked.
logging:
driver: none
map-tiles-refresh:
image: halkyon-maps
restart: unless-stopped
user: "61178:61178"
read_only: true
command: ["/app/tiles.sh"]
environment:
# `west,south,east,north`; Europe's.
MAP_REGION: ${MAP_REGION:--25,35,45,75}
volumes:
- ./maps/tiles:/tiles
# Out to Protomaps' builds alone; on a network of its own, beside nothing.
networks:
- downloads
mem_limit: 512m
logging:
driver: journald
train-server:
environment:
# The tiles as Caddy serves them, and the secret their keys are made with.
MAP_TILES_URL: https://${TRAIN_DOMAIN}/tiles/europe/{z}/{x}/{y}.mvt
SERVERPOD_PASSWORD_mapKeySecret: ${MAP_KEY_SECRET:?set MAP_KEY_SECRET in deploy/.env}
caddy:
volumes:
- ./sidecars/train-maps.caddy:/etc/caddy/train/maps.caddy:ro
networks:
tiles: {}
networks:
# Caddy and the tiles, without a way out.
tiles:
internal: true
downloads: