How to Setup WS Reverse Proxy using Nginx

Written by: Bagus Facsi Aginsa
Published at: 07 Sep 2021


Sometimes you want to build a service using WebSocket (WS) transport and then you want to terminate the Secure Websocket (WSS) in the reverse proxy instead of your service. Or you just wanna terminate your WebSocket in reverse proxy so later you can load balance them. This is a very common use case for Nginx.

In this tutorial, we will help you build your Nginx WS reverse proxy as well as how to convert WSS to WS protocol.

Check Prerequisite

  1. Nginx Installed, if not installed yet, you can just use apt install nginx to install it.
  2. Sudo privileges, you need to have sudo privileges to edit the Nginx configuration. To make sure that we don’t have a permission issue, execute sudo su command before starting this tutorial.

Use Case

To demonstrate the WebSocket reverse proxy, will use this use case:

                        ___________              ____________
              wss      |           |     ws     |            |
     user -----------> |   Nginx   |----------> |    App     |
                       |___________|            |____________|

For example, this will be the spesification of each node:

  • Nginx:
    • port: 443
    • ip: 10.1.0.10/24
  • App:
    • port: 3000
    • ip: 10.2.0.20/24

Your App is using a plain WebSocket (ws), while Nginx will use a secure WebSocket (wss), and terminate the SSL. In this example, we will use this domain my.websocket.app.

Nginx Configuration

First, you need an Nginx that already running. Move our work directory to the Nginx configuration folder

cd /etc/nginx

Backup the default nginx configuration file

mv nginx.conf nginx.conf.old

Create a new configuration file

nano nginx.conf

Add this configuration to the configuration file

user www-data;
worker_processes auto;
worker_rlimit_nofile 8192;
pid /run/nginx.pid;

events {
    worker_connections 4096;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    # Sending fille Optimization
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # Keepalive Connection
    keepalive_timeout 65;

    server {
        listen 443 ssl http2;
        server_name my.websocket.app

        # Security and SSL
        ssl_protocols TLSv1.3 TLSv1.2;
        ssl_certificate /etc/ssl/cert_file.crt;
        ssl_certificate_key /etc/ssl/key_file.key;

        location / {
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_pass http://10.2.0.20:3000;
        }
    }
}

proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection "Upgrade" directives is needed when we want to use WS protocol instead of HTTP protocol for the upstream connection. And it is the core difference between the HTTP reverse proxy and WS reverse proxy.

WSS and WS protocol is only supported on HTTP version 1.1, so you must use the proxy_http_version 1.1 directive to make sure the Nginx works properly.

proxy_set_header Host $host is another mandatory directive if you want to use WSS and WS protocol. It takes the Host header on the request and passes it to the upstream server.

Lastly, We use the proxy_pass directive to tell the Nginx the upstream ws server, in this case, we will proxy the WSS request to our WS app in 10.2.0.20:3000.

If your domain is using plain WS then you can comment out ssl_protocols, ssl_certificate, and ssl_certificate_key directives, and also change the listen directive to 80 or whatever port that you want to use.

After the configuration is done, make sure that there is no error in the configuration by running this command

nginx -t

Reload the nginx so it uses the new configuration file

service nginx reload

You can check the nginx status by running this command

service nginx status

That’s it! Congratulation, now you can build your Websocket Reverse Proxy using Nginx.