Using nginx as a proxy for WebSocket connections

by Samuel Attard

Some people just want their entire world to run through nginx :)
Well this is how you can get your WebSockets flowing through ports 80 and 443 with nginx.

Setting up the Server Configuration

By default your nginx configuration should be locations at /etc/nginx/sites-enabled/default and should already container a bit of config that looks kind of like this

server {  
    listen 80 default_server;
    server_name www.example.com;
    ...

    location / {
        ...
    }
} 

We are going to be adding another server configuration beneath this one that looks like this

server {  
        listen 80;
        #Only use this line if you want to enable wss:// connections
        listen 443 ssl;

        server_name socket.example.com;

        # These lines are only required if you enabled ssl above
        ssl_certificate /var/certs/socket.crt;
        ssl_certificate_key /var/certs/socket.key;

        location / {
                access_log off;

                proxy_pass http://localhost:[Port that your WebSocket is running on];
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                proxy_read_timeout 86400s;
                proxy_send_timeout 86400s;

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

Now for the explanation

Lets go through this configuration line by line
listen 80 - Pretty standard, tells nginx that this server will respond to requests on port 80
listen 443 - If you want to allow secure WebSocket connections (this will require an SSL certificate) server_name - This will be the URL that users will use to connect to the WebSocket, it must be a new sub-domain
ssl_certificate - The .crt file that came with your SSL certificate
ssl_certificate_key - The .key file that came with your SSL certificate

Here is where is gets fancy

proxy_pass - This is the URL that nginx will forward all connections to, so anyone accessing socket.example.com - will actually receive the content provided by this address
proxy_set_headers - These 3 lines set some headers that will be usefull for your WebSocket. Because your WebSocket will think all connections came from 127.0.0.1 we set a header that gives the the real IP address. And we set the appropriate Host and X-forwarded-for headers.

Now by default connections to an nginx server timeout after 60 seconds of inactivity, so for this server (because we might want WebSocket connections to persist a bit longer than that) we overide the proxy_reat_timeout and proxy_send_timeout to be 86400s (which is equal to one day)

The last 3 lines are WebSocket specific HTTP things that are just required to make the WebSocket work.