Skip to content

1.0-25 — Dashboard live streams behind nginx

Choose a tag to compare

@github-actions github-actions released this 04 Sep 15:15
· 20 commits to master since this release

Dashboard live streams survive a reverse proxy

The dashboard log tails went silent behind nginx and filled its error log with

upstream timed out (110: Connection timed out) while reading response header from upstream,
request: "GET /deploy/dashboard/agentlog/events"

No configuration change is needed. Upgrading the server jar is enough; nginx defaults
(proxy_read_timeout 60s, proxy_buffering on) now work as they are.

What was wrong

/deploy/dashboard/agentlog/events and /deploy/dashboard/log/events staged their response headers
and then wrote nothing until a new log line appeared. Vert.x flushes the status line and the headers
together with the first body write, so on a quiet server not a single byte left the socket. nginx
waited out its proxy_read_timeout and dropped the connection while still reading the response
header
, the browser's EventSource reconnected, and the loop repeated for as long as the dashboard
stayed open. The Live screen was never affected: it pushes a full card snapshot on connect and
on every tick.

What changed

All three streams ({DASHBOARD_PATH}/events, /log/events, /agentlog/events) now:

  • open with a : connected comment, which flushes the status line and headers immediately;
  • send a : keepalive comment after 15 s of silence, four times inside the 60 s nginx default, so an
    idle tail never trips a proxy idle timeout;
  • set X-Accel-Buffering: no, so nginx streams the events through instead of buffering them.

SSE comments are ignored by EventSource, so the vendored htmx client is unchanged.

Behind a second proxy

If the deploy server sits behind an outer proxy as well, that one must also pass the stream through
unbuffered — it either honours X-Accel-Buffering or needs proxy_buffering off. Otherwise the
events still arrive, but in bursts. A minimal location:

location /deploy {
    proxy_pass http://127.0.0.1:9090;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering off;
}

See Behind a reverse proxy
in the docs.

Verification

An integration test now asserts that both tail endpoints answer 200 text/event-stream with
X-Accel-Buffering: no and deliver their opening comment while the logs are still empty — the exact
case that used to hang until the proxy timed out.