Bird
Raised Fist0
Nginxdevops~10 mins

WebSocket proxying in Nginx - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - WebSocket proxying
Client sends WebSocket request
↓
Nginx receives request
↓
Check if request is WebSocket upgrade
↓
Set proxy headers
↓
Proxy to backend WebSocket server
↓
Backend responds and upgrades
↓
Nginx tunnels data between client and backend
↓
Connection open
Nginx checks if the incoming request wants to upgrade to WebSocket, sets special headers, then proxies the connection to the backend WebSocket server, allowing data to flow between client and server.
Execution Sample
Nginx
location /ws/ {
    proxy_pass http://backend_ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}
This config proxies WebSocket requests at /ws/ to the backend server, setting headers needed for WebSocket upgrade.
Process Table
StepActionRequest Header UpgradeConnection HeaderProxy Headers SetProxy Pass TargetResult
1Client sends request to /ws/websocketUpgradeNot set yetNot set yetRequest received by Nginx
2Nginx checks Upgrade headerwebsocketUpgradeNot set yetNot set yetUpgrade detected, proceed with WebSocket proxying
3Set proxy headerswebsocketUpgradeUpgrade=$http_upgrade, Connection=UpgradeNot set yetHeaders prepared for proxying
4Proxy pass to backend_wswebsocketUpgradeUpgrade=websocket, Connection=Upgradehttp://backend_wsRequest forwarded to backend
5Backend responds with 101 Switching ProtocolswebsocketUpgradeUpgrade=websocket, Connection=Upgradehttp://backend_wsConnection upgraded to WebSocket
6Nginx tunnels datawebsocketUpgradeUpgrade=websocket, Connection=Upgradehttp://backend_wsBidirectional data flow established
7Connection openwebsocketUpgradeUpgrade=websocket, Connection=Upgradehttp://backend_wsWebSocket connection active
💡 WebSocket connection established and data tunneled until closed
Status Tracker
VariableStartAfter Step 3After Step 4Final
$http_upgradewebsocketwebsocketwebsocketwebsocket
proxy_set_header Upgradeunsetwebsocketwebsocketwebsocket
proxy_set_header ConnectionunsetUpgradeUpgradeUpgrade
proxy_passunsetunsethttp://backend_wshttp://backend_ws
Key Moments - 3 Insights
Why do we need to set 'proxy_http_version 1.1;' for WebSocket proxying?
Because WebSocket requires HTTP/1.1 to support the Upgrade header. Without setting this, Nginx defaults to HTTP/1.0 which does not support connection upgrades. See execution_table step 3 where headers are set after specifying HTTP version.
What happens if we forget to set 'proxy_set_header Connection "upgrade";'?
The backend server will not recognize the request as a WebSocket upgrade request, so it won't switch protocols. This breaks the WebSocket handshake. Refer to execution_table step 3 where setting this header is crucial.
Why does Nginx tunnel data after the upgrade instead of buffering it?
Because WebSocket is a full-duplex connection needing real-time data flow. Nginx acts as a transparent tunnel after upgrade, forwarding data both ways without buffering. See execution_table steps 6 and 7.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step does Nginx detect the WebSocket upgrade request?
AStep 2
BStep 4
CStep 1
DStep 5
💡 Hint
Check the 'Action' and 'Result' columns in execution_table rows to see when upgrade is detected.
According to variable_tracker, what is the value of 'proxy_set_header Connection' after step 3?
Aunset
BUpgrade
Cupgrade
Dwebsocket
💡 Hint
Look at the 'proxy_set_header Connection' row in variable_tracker after step 3.
If 'proxy_http_version 1.1;' was omitted, what would likely happen?
ANginx would use HTTP/2 automatically
BConnection would still upgrade successfully
CWebSocket upgrade would fail
DBackend server would reject all requests
💡 Hint
Refer to key_moments about why HTTP/1.1 is required for upgrade headers.
Concept Snapshot
WebSocket proxying in Nginx:
- Use 'proxy_http_version 1.1;' to enable HTTP/1.1
- Set 'proxy_set_header Upgrade $http_upgrade;' to forward upgrade header
- Set 'proxy_set_header Connection "Upgrade";' to allow protocol switch
- Use 'proxy_pass' to backend WebSocket server
- Nginx tunnels data after 101 Switching Protocols response
- Ensures real-time bidirectional WebSocket communication
Full Transcript
When a client sends a WebSocket request, Nginx first checks if the request includes the Upgrade header indicating a WebSocket handshake. If yes, Nginx sets the HTTP version to 1.1 and sets proxy headers 'Upgrade' and 'Connection' to allow the protocol upgrade. Then it proxies the request to the backend WebSocket server. When the backend responds with a 101 Switching Protocols status, Nginx starts tunneling data between client and backend, enabling full-duplex WebSocket communication. This process continues until the connection closes.

Practice

(1/5)
1. What is the main reason to use proxy_set_header Upgrade $http_upgrade; in nginx when proxying WebSocket connections?
easy
A. To tell nginx to allow the connection to switch protocols to WebSocket
B. To set the client's IP address in the header
C. To enable gzip compression for WebSocket data
D. To disable caching for WebSocket requests

Solution

  1. Step 1: Understand the Upgrade header role

    The Upgrade header tells the server to switch from HTTP to another protocol, here WebSocket.
  2. Step 2: Recognize nginx's proxy_set_header usage

    Setting proxy_set_header Upgrade $http_upgrade; passes the client's Upgrade header to the backend, enabling protocol switching.
  3. Final Answer:

    To tell nginx to allow the connection to switch protocols to WebSocket -> Option A
  4. Quick Check:

    Upgrade header enables protocol switch = A [OK]
Hint: Upgrade header signals WebSocket protocol switch [OK]
Common Mistakes:
  • Confusing Upgrade with client IP headers
  • Thinking it enables compression
  • Assuming it disables caching
2. Which of the following nginx configuration snippets correctly enables WebSocket proxying?
easy
A. proxy_http_version 1.0; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
B. proxy_http_version 1.1; proxy_set_header Upgrade "websocket"; proxy_set_header Connection "close";
C. proxy_http_version 2.0; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "keep-alive";
D. proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";

Solution

  1. Step 1: Identify required HTTP version for WebSocket

    WebSocket proxying requires HTTP/1.1 because HTTP/1.0 does not support the Upgrade header properly.
  2. Step 2: Check correct headers for WebSocket

    The Upgrade header must be passed as $http_upgrade and Connection header must be "upgrade" to maintain the protocol switch.
  3. Final Answer:

    proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; -> Option D
  4. Quick Check:

    HTTP/1.1 + Upgrade + Connection upgrade = B [OK]
Hint: Use HTTP/1.1 and set Upgrade and Connection headers correctly [OK]
Common Mistakes:
  • Using HTTP/1.0 instead of 1.1
  • Setting Connection to keep-alive or close
  • Hardcoding Upgrade header instead of using $http_upgrade
3. Given this nginx config snippet inside a location block:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://backend_server;

What will happen if a client tries to establish a WebSocket connection through nginx?
medium
A. The connection will be cached by nginx, causing stale data.
B. The WebSocket connection will be successfully proxied to the backend server.
C. The connection will be proxied but without protocol upgrade, causing failure.
D. The connection will fail because HTTP/2 is required for WebSocket.

Solution

  1. Step 1: Analyze HTTP version and headers

    The config uses HTTP/1.1 and sets Upgrade and Connection headers correctly for WebSocket proxying.
  2. Step 2: Understand nginx behavior with this config

    nginx will forward the WebSocket upgrade request to the backend, enabling a successful WebSocket connection.
  3. Final Answer:

    The WebSocket connection will be successfully proxied to the backend server. -> Option B
  4. Quick Check:

    Correct HTTP version and headers = successful proxy [OK]
Hint: HTTP/1.1 + Upgrade + Connection upgrade = success [OK]
Common Mistakes:
  • Thinking HTTP/2 is required for WebSocket
  • Assuming protocol upgrade is automatic without headers
  • Believing nginx caches WebSocket connections
4. You have this nginx config for WebSocket proxying:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "keep-alive";
proxy_pass http://backend;

Why might WebSocket connections fail with this setup?
medium
A. Because Connection header should be "upgrade" not "keep-alive" for WebSocket
B. Because proxy_http_version should be 1.0 for WebSocket
C. Because Upgrade header should be hardcoded to "websocket"
D. Because proxy_pass URL is missing a trailing slash

Solution

  1. Step 1: Check Connection header value

    For WebSocket proxying, Connection header must be "upgrade" to signal protocol switch.
  2. Step 2: Identify impact of incorrect Connection header

    Using "keep-alive" prevents the protocol upgrade, causing WebSocket connection failure.
  3. Final Answer:

    Because Connection header should be "upgrade" not "keep-alive" for WebSocket -> Option A
  4. Quick Check:

    Connection header must be upgrade for WebSocket [OK]
Hint: Connection header must be "upgrade" for WebSocket [OK]
Common Mistakes:
  • Using keep-alive instead of upgrade
  • Setting HTTP version to 1.0
  • Hardcoding Upgrade header instead of using $http_upgrade
5. You want to proxy WebSocket connections through nginx to two backend servers for load balancing. Which configuration snippet correctly supports WebSocket proxying with load balancing?
hard
A. upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "close"; }
B. upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 1.0; proxy_set_header Upgrade websocket; proxy_set_header Connection "keep-alive"; }
C. upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
D. upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 2.0; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }

Solution

  1. Step 1: Confirm HTTP version and headers for WebSocket

    HTTP/1.1 is required, and headers Upgrade and Connection must be set to allow protocol upgrade.
  2. Step 2: Check load balancing setup and header correctness

    upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } uses correct HTTP version, headers, and defines upstream servers for load balancing properly.
  3. Final Answer:

    upstream ws_backend { server backend1.example.com; server backend2.example.com; } location /ws/ { proxy_pass http://ws_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } -> Option C
  4. Quick Check:

    HTTP/1.1 + Upgrade + Connection upgrade + upstream = A [OK]
Hint: Use HTTP/1.1, Upgrade and Connection headers plus upstream for load balancing [OK]
Common Mistakes:
  • Using HTTP/1.0 or 2.0 instead of 1.1
  • Setting Connection to keep-alive or close
  • Hardcoding Upgrade header instead of using $http_upgrade
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard