Staging and previews
koala runs private copies of the product. Every tenant keeps its identity under a fake top-level domain that only exists on the tailnet:
http://reittikartta.net.tehas/is the standing stack. It followsdev.http://reittikartta.net.pr-123.tehas/is the preview of pull request 123.http://admin.tehas/andhttp://admin.pr-123.tehas/are the admin of each.
Every live tenant works the same way: production domain plus .tehas, or plus
.pr-<number>.tehas. The set of tenants tracks the product repo's tenant
registry (shared/lib/tenant.ts); there is no fixed count here. Path-prefix
tenants keep their prefix
(http://waysur.com.tehas/es/, http://routeplanner.app.tehas/uk/).
Plain HTTP only. Features that need a secure context (service worker, geolocation, offline saved routes) cannot be tested here.
Reaching it from your own device
Your device has to send the tehas domain to koala's resolver. In the Tailscale
admin console: DNS, add nameserver 100.110.200.91, restrict to domain tehas
(split DNS). Until that is set, the names resolve only from koala and from
inside the sandbox.
Check: nslookup reittikartta.net.tehas should answer 100.110.200.91. Type
the full http:// address the first time; a browser treats an unknown ending as
a search.
Links always point at production
The product is told nothing about staging. Canonical tags, sitemaps, share links and every absolute URL it renders name the production domain, also on a staging host. So:
- navigation inside a page stays on staging as long as the links are relative,
- an absolute link takes you to the live site. Look at the address bar.
Two gates keep staging hosts out of production:
| Gate | Where | What it does |
|---|---|---|
scripts/check-no-tehas-hosts.sh |
every tehas cycle (verify gate) and scripts/tag-release.sh before a tag |
Fails if any file outside the tehas tooling names a .tehas host |
| Smoke run of every stack | tehas-stack smoke |
Fails a page whose HTML contains .tehas at all, or whose canonical is not the tenant's production URL |
What a stack is
Four containers (api, frontend v3, frontend v4, admin_v2) built from one commit, on a private clone of last night's production snapshot. The image builds run the project's own check and test steps, as a production build does.
A stack is inert towards the outside world:
- its database is a throwaway clone; nothing reaches production data,
- no background sync, harvest, sitemap submission, cache purge or search console job is configured,
- beacons and analytics events are dropped, ads render in test mode,
- no LLM backend is configured,
- geocoding and Overpass go to koala's own map stack.
Routing and map tiles still use the public production services: koala has no OSRM router and the tile host must be HTTPS. That is read-only traffic of the kind any visitor's browser makes.
Who starts and stops them
The dispatcher does, at every poll:
- dev stack: redeployed when
origin/devmoves. A build that fails is not retried untildevmoves again; the previous stack keeps serving. - previews: built when a tehas cycle opens a pull request. The links and the smoke table are posted on the pull request. Removed, with its database, when the pull request is merged or closed. At most 3 at a time.
By hand:
tehas-stack list
tehas-stack up dev
tehas-stack up pr-123
tehas-stack urls pr-123 # where to click, incl. the admin
tehas-stack smoke pr-123
tehas-stack down pr-123
The first build of a commit takes several minutes because of the test suites; a
rebuild of the same commit takes about a minute. The admin login is user tehas
with the password in ~/tehas/stacks/<name>/env on koala.
Screenshots and page checks
koala has no browser of its own; Chromium lives in the sandbox image and
tehas-probe runs it there.
tehas-probe http://reittikartta.net.tehas/ --shot fi-landing.png
tehas-probe https://reittikartta.net/helsinki/tampere --shot route.png --mobile
Files land in ~/tehas/shots; each stack's smoke screenshots are in
~/tehas/shots/<name>/. Copy one to your machine with
scp janit-or@koala:tehas/shots/dev/fi_.png ..
Agents use the same probe through the routemap-browser-probe skill.