Helpful end-to-end walkthrough. The WebSocket section is where I usually see production surprises after HTTPS is already fine. Upgrade and Connection headers have to land on the location that actually serves the socket path; if a catch-all proxy_pass sits in front without proxy_http_version 1.1 and the upgrade headers, browsers show a vague failure while curl to the HTTP API still looks healthy.
With Docker I also pin proxy_set_header Host and X-Forwarded-Proto carefully. Node apps that build absolute URLs from req.protocol will emit http:// links behind TLS termination if they never see X-Forwarded-Proto=https, which then breaks cookies or mixed-content checks. For containers, prefer the service name in upstream and keep the Node process listening on an internal port only — no published 3000 on the host if nginx is the only public entry. One more ops habit: after certbot or a compose recreate, run a quick wscat/browser check on the WS path, not just curl -I on /, because a bad Connection header often survives a successful TLS handshake.
Helpful end-to-end walkthrough. The WebSocket section is where I usually see production surprises after HTTPS is already fine. Upgrade and Connection headers have to land on the location that actually serves the socket path; if a catch-all proxy_pass sits in front without proxy_http_version 1.1 and the upgrade headers, browsers show a vague failure while curl to the HTTP API still looks healthy.
With Docker I also pin proxy_set_header Host and X-Forwarded-Proto carefully. Node apps that build absolute URLs from req.protocol will emit http:// links behind TLS termination if they never see X-Forwarded-Proto=https, which then breaks cookies or mixed-content checks. For containers, prefer the service name in upstream and keep the Node process listening on an internal port only — no published 3000 on the host if nginx is the only public entry. One more ops habit: after certbot or a compose recreate, run a quick wscat/browser check on the WS path, not just curl -I on /, because a bad Connection header often survives a successful TLS handshake.