I've recently switched my rails project from Rails4 to 5.0.0.beta3 to use the awesome ActionCable.
My ActionCable server is run inside unicorn. In development all works fine. In production I have
Started GET "/cable" for xxx.xxx.xxx.xxx at 2016-03-28 18:06:38 +0300
Started GET "/cable/" [WebSocket] for xxx.xxx.xxx.xxx at 2016-03-28 18:06
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
Registered connection (189772ff-6229-48f1-ae7f-d9a96ad3a6c3)
Finished "/cable/" [WebSocket] for xxx.xxx.xxx.xxx at 2016-03-28 18:06:35
And this message repeats again and again in a loop.
I've tried a lot of options at stackoverflow to handle this but nothing helps.
My nginx config:
upstream unicorn {
server unix:/tmp/unicorn.my_app.sock fail_timeout=0;
}
server {
server_name www.my_app.com;
return 301 $scheme://my_app.com$request_uri;
}
server {
listen 80 default deferred;
server_name my_app.com;
root /var/www/my_app/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
location /cable {
proxy_pass http://unicorn/cable;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
error_page 500 502 503 504 /500.html;
keepalive_timeout 5;
}
To be sure that request is allowed I've temporarily use this code in initializers:
ActionCable.server.config.disable_request_forgery_protection = true
My cable.coffee
file
@App ||= {}
App.cable = ActionCable.createConsumer "/cable"
My config/cable.yml
file
production:
adapter: redis
url: redis://localhost:6379/1
I'm not so experienced at this question, so any help would be great.
In the location /cable
section need to add a line proxy_set_header Host $http_host;
Should be:
location /cable {
proxy_pass http://unicorn/cable;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
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;
}
I implemented rack-timeout. Setting the correct timeouts corrected my problem. The proper method to set those variables is in a config.ru use statement as follows:
use Rack::Timeout, service_timeout: 5
This is config that I use for my website, and it seems to be working fine (Rails 5 + Nginx + Unicorn + Capistrano). Includes you see in the snippet are from h5bp/server-configs-nginx, but I don't think they could be a reason why your configuration does not work.
upstream example_app {
server unix:/home/username/www/example.com/current/tmp/sockets/unicorn.example.com.sock fail_timeout=0;
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
include h5bp/directive-only/ssl.conf;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
include h5bp/directive-only/ssl.conf;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
root /home/username/www/example.com/current/public;
# Set maximum request body size for uploads
client_max_body_size 25m;
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_pass http://example_app;
}
location /cable {
proxy_pass http://example_app;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
access_log /var/log/nginx/example.com/access.log;
error_log /var/log/nginx/example.com/error.log;
charset utf-8;
server_tokens off;
error_page 404 /404.html;
include h5bp/basic.conf;
}
cable.yml
production:
adapter: redis
url: redis://localhost:6379/1
cable.js
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);