Configuring the Websocket HTTP upgrade header

In our previous post, we talked websockets in general, and how to use them wisely. Websockets are easy to setup when you are running your server locally, but there are a couple of gotchas once you deploy your code to somewhere else.

If you are using Rails 5 with ActionCable, you will find soon enough that the out-of-the-box solutions won't work that you have used before. The reason being that websockets need to maintain an open connection for their communication channels, so you'll need to make sure there will be enough threads and processes handling them as well as your regular traffic.

The first thing to do with your Rails application is to - if you haven't done so before - switch to using puma or unicorn. Doublecheck your configuration to ensure you have enough processes to handle the increased traffic. 

The next thing is to take a look at your webservers. If you are using Apache, then you need to enable mod_proxy_wstunnel as well as configure the right endpoint - in Rails' case it's /cable, unless you have changed it.

In case you are running Nginx, then all you need to do is enable the HTTP upgrade by adding the following lines to your configuration file:

upstream websocket {
  server unix:/path/to/your/sockets/unicorn.sock fail_timeout=0;
}
server {
#...
  location /cable {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection Upgrade;
    proxy_http_version 1.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://websocket/cable;
    proxy_redirect off;
  }
  #...
}

Then all you need is a restart and watch the streams of data passing through your applications.

+ 1 Tip: If you're running more than one server behind a load balancer, make sure your port fowarding is setup as TCP to TCP, not the default HTTP (or HTTPS if you're using SSL). Without this, the HTTP Upgrade will fail.

Attributions