How to Configure NGINX to Proxy WebSockets

Overview

In this tutorial, you will learn how to configure NGINX WebSocket connections between your client and backend services.

A typical HTTP request opens a connection between the client and the web server. The server then sends the requested data to the client and then closes the connection.

A WebSocket, on the other hand, creates a persistent two-way connection between the client and server.

Configuring Proxy Server

Create a new conf file for the Nginx server that will accept WebSocket requests.

sudo touch /etc/nginx/conf.d/00-websockets.conf

Add the following content to it

http {
  server {
    listen 3000;
    server_mame ws.serverlab.ca

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;

      proxy_pass http://ws-backend;

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
  }

  upstream ws-backend {
    # enable sticky session based on IP
    ip_hash;

    server server01:3000;
    server server02:3000;
    server server03:3000;
  }
}

Saving your settings and then restart the NGINX server will enable it to support WebSocket connections.

Understanding the Configuration

Let’s break the NGINX configuration apart to understand how the server handles WebSockets. The following configuration creates a virtual host within NGINX, which listens for requests on port 3000 for hostname ws.serverlab.ca.

  server {
    listen 3000;
    server_mame ws.serverlab.ca
    
    [ ... truncated ... ]
  }

Next is the location directive, within the server directive, matches request URIs to be processed. In the example, a ‘/’ represents a catchall for URIs sent.

    location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;

proxy_pass http://ws-backend;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

This is a typical reverse proxy configuration. It begins with setting headers that allow client information to pass through the proxy into the upstream WebSocket servers.

proxy_set_header X-Forwarded-For
Ensure the IP of the client sending requests to the NGINX is stored in the request header. This allows connections to be traced back to an origin. Without adding this header, all requests to the upstream WebSocket servers will have the NGINX server’s IP address as the source.

proxy_set_header Host $host
Sets the Host header to be that of the NGINX server.

proxy_pass
This directive instruct NGINX proxy all requests matching the location pattern to an upstream (backend) server. In the example given, ws-backend is used, however, this is actually the name of an upstream group created further down in the configuration.

The next few options are the magic that enable WebSocket support. These must exist for the NGINX to correctly proxy WebSocket requests to upstream WebSocket servers.

proxy_http_version 1.1
This directive converts the incoming connection to HTTP 1.1, which is required to support WebSockets. The older HTTP 1.0 spec does not provide support for WebSockets, and any requests using HTTP 1.0 will fail.

proxy_set_header Upgrade $http_upgrade
Converts the proxied connection to type Upgrade. WebSockets only communicate on Upgraded connections.

proxy_set_header Connection “upgrade”;
Ensure the Connection header value is upgrade

Balancing WebSocket Requests

The remaining configuration creates an upstream named ws-backend. Within this upstream are the backend WebSocket servers, which NGINX will balance traffic between.

  upstream ws-backend {
    # enable sticky session based on IP
    ip_hash;

    server ws-server01:3000;
    server ws-server02:3000;
    server ws-server03:3000;
  }

ip_hash
Enables sticky sessions based on an incoming client IP address. All further requests from the IP will be proxied to the first upstream server that handled its request. This is required for stateful services.

server ws-server##:3000
Each server listed is the hostname and port of an upstream WebSocket server.