Two coupled changes that let every proxy_pass vhost serve both WS and
SSE without per-vhost flags or template conditionals:
1) nginx.conf: $connection_upgrade map is now always defined (drop
the % if has_websockets: gate), and the '' branch returns "" instead
of "close". With "" + proxy_http_version 1.1, nginx maintains
keep-alive to upstream for non-WS clients — which is what SSE
requires. WS clients still get Connection: upgrade as before.
2) data/nginx/proxy_pass.conf: drop the % if websockets: conditional.
Always set proxy_http_version 1.1 + Upgrade + Connection via the
map, plus proxy_buffering off and proxy_read_timeout 1h for SSE.
Effects on existing vhosts:
- home.server's Proxmox WS vhost: unchanged behavior (the WS branch
was already setting these headers). Gains the ability to also
serve SSE if ever needed.
- All other proxy_pass vhosts (Nextcloud, Freescout, YOURLS, Gitea,
etc.): get keep-alive to upstream (minor latency win) and unbuffered
pass-through (slight throughput cost on huge responses, neutral
for typical web app traffic).
Dead but harmless: bundles/nginx/metadata.py still defaults
nginx/has_websockets to False, and proxmox-ve/grafana still set it
to True. The flag is now a no-op; clean up in a separate pass.
Two things from the left4me-integration session worth pinning:
- 80.conf was orphaned in sites/ (not sites-enabled/) for an
unknown amount of time. Commit d49259f moved it; document the
resulting wiring so it's not re-broken accidentally.
- items.py reads node.metadata.get('vm/cores') with no default
for worker_processes; bare-metal nodes outside the vm group
raise at item-build time. Cost the agent ~10 min when
ovh.left4me first opted into webserver.
Also note the cross-namespace read on letsencrypt/domains.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The bundle was shipping 80.conf (HTTP-to-HTTPS redirect + acme-challenge
alias) to /etc/nginx/sites/80.conf, but nginx.conf only `include`s
/etc/nginx/sites-enabled/* (which is a symlink to sites-available).
The file was orphaned — no node had a working port-80 listener.
Move the destination to /etc/nginx/sites-available/80.conf so the
existing sites-enabled symlink picks it up. The /etc/nginx purge will
clean up any stale /etc/nginx/sites/80.conf on existing hosts.