Three fixes after the first cd-brouter run on the dedicated host: 1. **BRouter 1.7.8 → 1.7.9** (`docker/brouter/Dockerfile`). Planet RD5 segments on brouter.de are now version 11; 1.7.8's `lookups.dat` is v10, causing `lookup version mismatch (old rd5?) lookups.dat=10 E10_N45.rd5=11` on every route request. 2. **cd-brouter.yml: docker login to ghcr.io before pull**. ghcr.io/trails-cool/brouter is private, and the dedicated host's Docker daemon isn't logged in by default. Extract DEPLOY_GHCR_TOKEN from SOPS at runner side, pass to the SSH step via envs, and `docker login` before `docker compose pull`. Credential is `::add-mask::`-ed so it doesn't show in logs. 3. **Drop custom healthcheck** on the brouter service. The image strips wget/curl post-build, and /bin/sh in the base doesn't support /dev/tcp, so there's no in-image way to do an HTTP probe. Real health is observed via Caddy's upstream 502 behavior on outage and the Planner-side `brouter_request_duration_seconds` metric. caddy's `depends_on` drops from service_healthy to service_started. End-to-end verified on the dedicated host after applying the compose fix manually: - Caddy enforces auth: 403 without header, proxies with. - BRouter 1.7.9 will resolve the segment-version error once the image is rebuilt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| Caddyfile | ||
| docker-compose.yml | ||
| download-segments.sh | ||
| promtail-config.yml | ||
| README.md | ||
BRouter host compose project
Runs on a dedicated Hetzner Robot server (currently ullrich.is,
private IP 10.0.1.10 over vSwitch #80672), owned by the non-root
trails user. Services:
- brouter — the BRouter Java server, planet-scale segments, 8 GB JVM heap, no public port.
- caddy — thin sidecar enforcing the
X-BRouter-Authshared-secret header. Bound to10.0.1.10:17777(vSwitch IP only).
Public ingress is blocked at the host's UFW (port 17777 is only allowed
on the VLAN interface from 10.0.0.2, the flagship's vSwitch IP).
One-time provisioning
Operator (as root) — one-time firewall rules
The dedicated host's UFW policy rejects anything not explicitly allowed. Open the vSwitch ports the flagship needs:
# BRouter Caddy sidecar (already added during section 1.2):
# ufw allow in on enp4s0.4000 from 10.0.0.2 to any port 17777 proto tcp \
# comment 'trails brouter via flagship vSwitch'
# cAdvisor metrics endpoint (section 6) — add if not already:
ufw allow in on enp4s0.4000 from 10.0.0.2 to any port 8080 proto tcp \
comment 'trails brouter cadvisor via flagship vSwitch'
Application bring-up (as the trails user)
# 1. Land the compose project
cd ~
git clone https://github.com/trails-cool/trails.git repo
mkdir -p brouter
cp -r repo/infrastructure/brouter-host/* brouter/
cd brouter
# 2. Provide the shared secret (matches BROUTER_AUTH_TOKEN in SOPS)
# The CD workflow normally writes this file; for manual bring-up,
# do it yourself.
cat > .env <<'EOF'
BROUTER_AUTH_TOKEN=<paste value from sops -d infrastructure/secrets.app.env | grep BROUTER_AUTH_TOKEN>
EOF
chmod 0600 .env
# 3. Seed segments (multi-hour, ~60–80 GB)
./download-segments.sh
# 4. Start services
docker compose pull
docker compose up -d
# 5. Smoke test from the flagship (over vSwitch)
# Should return 200 with the token, 403 without.
# ssh root@trails.cool 'curl -sSf -H "X-BRouter-Auth: <TOKEN>" http://10.0.1.10:17777/brouter?lonlats=... '
Subsequent deploys
The cd-brouter GitHub Actions workflow handles routine updates:
it pulls the latest image, rewrites the compose file + Caddyfile from
the repo, and restarts.
Segment updates
Segments are refreshed by brouter.de weekly. To pull updates:
./download-segments.sh
docker compose restart brouter
Schedule via cron if you want automatic updates (not wired in this repo yet).
Token rotation
- Regenerate:
openssl rand -base64 32. - Update SOPS:
sops infrastructure/secrets.app.env(writer uses thesops -d | append | sops -epattern via the CD workflow; editing directly works too). - Merge the SOPS change to
main. cd-appsredeploys the Planner (sends the new token outbound).cd-brouterredeploys Caddy (matches on the new token).- Brief overlap window where Planner sends new token but Caddy still accepts old: both deploys should fire within a minute of each other, so a few 403s are the worst case.
Rollback
If BRouter is misbehaving and the flagship BRouter is still warm
(during the 48 h soak window post-cutover), flip BROUTER_URL in
infrastructure/secrets.app.env back to http://brouter:17777 and
redeploy the Planner. After the soak window, see the change's
design.md for the longer rollback path.
Logging
The dedicated host's Docker daemon default logging driver is loki
(the operator's personal Loki). Our compose file explicitly overrides
each service to json-file so logs stay local; a promtail sidecar
(section 6.3 of the relocate change) tails them and ships to
trails.cool's Loki over the vSwitch. If you disable that sidecar, the
BRouter logs will NOT flow to trails.cool's Grafana — they'll just
accumulate locally and eventually rotate.