Proxying custom Socket.IO namespaces with NGINX is not straightforward. Hopefully this will save time for the next person attempting it.

Proxy Custom Socket.IO Namespaces with NGINX

Justas Azna

A while ago I implemented a chat server based on Socket.IO for hopper.dk. In addition to the chat server, the system already had 2 HTTP servers: Gunicorn for our RESTful API and NGINX for serving AngularJS frontend. To make SSL management easier I decided to put all 3 servers behind a single NGINX host. It all went pretty smoothly except for 1 thing- my chat server with a custom namespace was unreachable through NGINX.

Let’s illustrate this with some code

Socket.IO Server

io = require('socket.io')();
io.listen(3000);

var myNamespace = io.of('/my-namespace');
myNamespace.on('connection', function(socket){
  console.log('someone connected');
  socket.emit('news', 'Hi there!!');
  myNamespace.emit('news', 'Someone joined the party!');
});

NGINX Host

server {
        listen 8080;

        server_name localhost;

        location ~/(my-namespace).*$ {
          proxy_pass         http://127.0.0.1:3000;
          proxy_http_version 1.1;
          proxy_set_header   Upgrade    $http_upgrade;
          proxy_set_header   Connection "upgrade";
        }
}

Connection attempts fail with HTTP 404

Client connection attempts fail

This setup results in Socket.IO client trying to establish a connection to the server with no success. After a bit of furious DuckDuckGoing and Googling, I gave up and decided to look for answers in Socket.IO’s code.

The solution is simple: in addition to proxying your custom namespace, you also have to proxy /socket.io resource to the Socket.IO server:

server {
        listen 8080;

        server_name localhost;

        location ~/(my-namespace|socket\.io).*$ {
          proxy_pass         http://127.0.0.1:3000;
          proxy_http_version 1.1;
          proxy_set_header   Upgrade    $http_upgrade;
          proxy_set_header   Connection "upgrade";
        }
}

Success

Client connection successfully established

I hope this helps.