Skip to content

Live-tail/SSE shows nothing behind your own proxy

Live-tail under Logs — and any other place that updates live via Server-Sent Events (SSE) — stays empty, or only updates in a burst every few minutes instead of continuously. This symptom appears almost exclusively when you run your own reverse proxy in front of Vesana (see TLS / Reverse Proxy) — directly against the Vesana stack without an additional proxy, SSE works without any extra configuration.

Cause: response buffering

SSE keeps an HTTP connection open and sends individual events as they occur. A reverse proxy buffers responses by default until a buffer fills up or the connection ends — for a stream that stays open for hours and only occasionally sends a few bytes, that means the client sees nothing until the proxy eventually flushes the buffer (or never does).

Fix in nginx: proxy_buffering off; for the affected location.

location /api/v1/logs/stream {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Connection '';
    proxy_buffering off;
    proxy_cache off;
    chunked_transfer_encoding off;
    proxy_read_timeout 3600s;
}

With Traefik this matches the default (no response buffering for normal proxy requests) — usually a sufficiently high timeout is enough there. With HAProxy: do NOT set option http-buffer-request and choose a generous timeout server. With Caddy, SSE is generally unproblematic without extra directives.

Two nginx layers — both need the flag

If you run the split-container mode vor-nginx (your own nginx/Caddy/Traefik terminates TLS in front of the Vesana stack, see Admin access & split container), there are two nginx layers between the browser and the backend: your own nginx in front, and the nginx inside the Vesana stack behind it. Both must have buffering disabled for the stream path — if it's only disabled in one place, the problem persists, because the other layer keeps buffering.

So check:

  1. Your own reverse-proxy config — proxy_buffering off for /api/v1/logs/stream (and any other stream route)
  2. The internal nginx in the Compose stack — should already have SSE routes configured correctly by default; if you've made custom changes to this config, check whether buffering was accidentally re-enabled

Diagnosis: is it really the proxy?

# Test directly against the Vesana stack (on the server itself, bypassing the proxy):
curl -N -H "Authorization: Bearer <JWT>" \
  "http://127.0.0.1:8080/api/v1/logs/stream?host=<host-id>"

If events keep arriving here, but not via the public domain name — the cause is 100 % the reverse proxy, not Vesana itself. -N (--no-buffer) matters here, otherwise curl itself buffers.

The "Vesana is starting …" splash during an update (see UI issues after an update) polls regular HTTP requests, not SSE — it isn't affected by buffering. If it hangs anyway, that's a different cause.

Checklist

  • [ ] proxy_buffering off on every proxy layer between the browser and Vesana for the stream route
  • [ ] proxy_read_timeout sufficiently high (the stream stays open for a long time)
  • [ ] A direct curl -N test against the stack shows events arriving?
  • [ ] With split-container vor-nginx: checked both nginx layers, not just your own

Next