Container logs¶
Stage container logs are at https://logs.evocase-iframe.io. Sign in with your
@evo-verse.com Google account — the same Cloudflare Access wall as the admin
panel and these docs. Nothing to install, no tunnel to start.
Access is by the same group as the admin panel (evocase-developers), not
by email domain: a company account alone is not enough, and if you can open the
admin panel you can open this. That is deliberate — see
Access is credential access below.
You get every container on the stage VM: games-api, bo-api, worker,
fe-backoffice, fe-embeds, postgres, redis, the
storage emulator and cloudflared. Live tail, per-container regex search, and
filtering by log level.
This is a live tail, not an archive
Docker keeps 30 MB of logs per container (max-size: 10m, max-file: 3)
and drops the rest. For a busy api that is hours, not days. If you are
looking for something from last night, it is already gone — see
When you need more history.
What you can do¶
| Follow a container live | pick it from the sidebar |
| Search within a container | / , or the search box — regex |
| Jump to a moment | scroll up, or /container/<id>/<timestamp> |
| Filter by level | the level chips above the stream |
| Several containers at once | shift-click in the sidebar |
Two limits worth knowing before they waste your time:
- No cross-container search. You cannot ask "where did trace id
abc123go" across several services at once. Search each in turn. - Scrolling far back can skip entries. There is a known Dozzle bug where a long scroll silently jumps over multi-hour gaps that do exist on disk. Treat a gap as "unknown", not as "nothing happened".
Access is credential access¶
The UI reads the Docker API, and that API exposes every container's
environment. On this stack that includes DOPPLER_TOKEN, which reads every
secret in the project — not just one database password, as on the other stacks.
Anyone who can open this page can
read the stage database credentials.
That is inherent to reading container logs, not something the setup got wrong. It is why the page sits behind Access with the same policy as the admin panel, and why "give them logs access" is the same conversation as "give them the database password". It is not a lighter-weight permission.
When you need more history¶
For anything older than the buffer, or a search across containers, you still have a shell on the VM:
ssh deploy@evocases-iframe.taildb581b.ts.net
docker compose -f /srv/evocases-iframe/docker-compose.yml logs --since 2h api
Same Tailscale membership as Database and Redis. This
reads the same 30 MB buffer, so it does not reach further back — it just lets
you grep across services and pipe the result somewhere.
If "what happened last night" becomes a regular question, the fix is a log
shipper to a hosted backend rather than a bigger buffer on a disk that Postgres
shares. That is written up in notes/logging.md in the infra repo, with the
volume estimate and current pricing.
Running it locally¶
cd infra
make logs-ui-up # http://localhost:3003
make logs-ui-down
Local has no Access in front of it, so authentication is switched off entirely
and there is no login — the bind to 127.0.0.1 is the only thing protecting it.
Do not publish that port on a shared machine.
When it does not work¶
| Symptom | Cause |
|---|---|
| Google login loops, or "no policy" | Not in the evocase-developers Access group — the same membership the admin panel needs. Ask an admin to add you there, not to this page |
| Page loads but the sidebar is empty | The socket proxy is down; docker compose ps logs-socket-proxy on the VM |
| A container is missing from the list | It is not running — Dozzle lists live containers, not stopped ones |
| Logs stop updating mid-stream | The tunnel dropped the connection; reload the page |
| Reached the page without logging in | Report this. Access is not in front of the hostname — see below |
That last row is the one to take seriously. On the VM:
cd /srv/evocases-iframe && ./scripts/logs-ui-verify.sh
Nine checks: six that the UI cannot reach the Docker socket or publish a port, and three that an unauthenticated request — including one carrying a forged identity header — never reaches the origin. Run it after any change to the tunnel routes or the Access application. It exits with the number of failures, so it also works as a CI gate.