Rails5 Action Cable Nginx 404 and 502 errors
Asked Answered
B

2

3

Everyone :). I know people have already faced alot of problems related to mine. I have tried all but my issue has not been resolved. I have been working from past 3 days to fix this but I am unable to do it.

I am using ActionCable for the first time and on development server it is working fine. But in production where I am using Puma and Nginx I am facing terrible issues.

Initially when I had not (location /cable) settings in nginx configuration, server gives me 404 handshake error
i.e Error during WebSocket handshake: Unexpected response code: 404

Then after I add following location /cable configuration in nginx configuration I start getting 502 bad gateway error.

Note: I have not opened any port specifically for ActionCable. I assume it is not required. only port 80 is open on my server.

I need some expert to help me with this. I need quick help to get it fixed. Thanks in advance :)

I have these two lines present in my environment/production.rb

config.action_cable.url = "ws://my_linode_domain/cable"
config.action_cable.allowed_request_origins = [/http:\/\/*/, /https:\/\/*/]

This is my nginx config file

    upstream app {
      # Path to Puma SOCK file, as defined previously
      server unix:/home/deploy/artcrate/shared/tmp/sockets/puma.sock fail_timeout=0;
    }

    server {
      listen 80;
      #server_name localhost;
      server_name my_linode_domain

     # prevents 502 bad gateway error
     large_client_header_buffers 8 32k;

      root /home/deploy/artcrate/current/public;

      try_files $uri/index.html $uri @app;

      location / {
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Connection '';
        proxy_pass http://app;
      }
      location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
        gzip_static on;
        expires max;
        add_header Cache-Control public;
      }
    location /cable{
       proxy_pass http://app;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
     }

      error_page 500 502 503 504 /500.html;
      client_max_body_size 4G;
      keepalive_timeout 10;
    }

I have tried various proxy_pass options in location /cable settings but none worked.

Behah answered 4/5, 2017 at 2:4 Comment(0)
B
2

RAILS and RUBY version I am using for this project is

Rails 5.0.7

ruby 2.3.1p112

ok. So today I wanted to integrate Action Cable again in my project but faced the same issue again. I applied my above solution but it didn't work. Last time although it worked but I wasn't satisfied with the solution thinking that why would ActionCable work in single thread/worker on local machine.

But this time I focussed and figured out the culprit.

Culprit is NGINX configuration

Configuration when I was facing 404 handshake errors

location /cable {
proxy_pass http://example.com;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;

}

Configuration when all started working fine.

location /cable {
proxy_pass http://puma;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;

}

so the culprit line was:

proxy_pass http://example.com;

Here we are pointing it to NGINX which is wrong, it should point to our puma server path which in my configuration is represented by 'puma'.

Here is the Summary of my implementation of ActionCable and its working copy on Production Server

So to integrate Action Cable with Rails 5 you need to follow following steps:

  1. Setup Redis on default port.
  2. Add these lines in environments/staging.rb or environments/production.rb, depending on your application environment.

    config.action_cable.url = [/ws://*/, /wss://*/]

    config.action_cable.allowed_request_origins = [/http://*/, /https://*/]

  3. Finally setup you NGINX file as explained above. Here is my complete NGINX configuration in gist nginx.conf. I had replaced my site name with 'example.com' and project name with 'example'. So if you are copying anything, just make sure you replace those with yours otherwise nothing will work as paths will be broken.

I hope this will really release the pain while pushing ActionCable to live application and resolve this handshake error for anyone as this is very very tricky and technical thing and a lot of docs just mention to point action cable to your main site url and not puma server running behind your nginx.

Thanks.

Behah answered 26/6, 2018 at 17:55 Comment(2)
the configuration you're suggesting (especially the /ws://*/ and /http://*/ stuff) is highly insecure and should NEVER reside in any production environment. In any case, these adjustments are only needed, if the action-cable server does run as a separate instance.Progressive
i am facing a similar issue but see that it happens very sporadically, i am using passenger and nginx as a reverse proxy, any help on how to fix would be really great!Ambala
B
2

Everyone. :)

After a week of struggle, hardwork and constantly playing around with nginx and puma configuration files and keenly reading blogs again and again, I was able to figure out the issue.

My nginx configurations were correct. I had to add two more lines to puma.rb configuration which don't come with default configurations. Those two lines are:

workers 2
daemonize true

daemonize true: this tells puma to run in the background by spawning a subprocess and detaching it from the executing shell. If you don't use daemonize, you need to run the puma process via nohup and put it in the background explicitly.

I am not sure if I required workers 2 but I had added them while resolving my issue. So I let it there. But after adding above two lines my ActionCable started to work normally.

Behah answered 7/5, 2017 at 7:51 Comment(1)
Nice post, save my DAY!Thorma
B
2

RAILS and RUBY version I am using for this project is

Rails 5.0.7

ruby 2.3.1p112

ok. So today I wanted to integrate Action Cable again in my project but faced the same issue again. I applied my above solution but it didn't work. Last time although it worked but I wasn't satisfied with the solution thinking that why would ActionCable work in single thread/worker on local machine.

But this time I focussed and figured out the culprit.

Culprit is NGINX configuration

Configuration when I was facing 404 handshake errors

location /cable {
proxy_pass http://example.com;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;

}

Configuration when all started working fine.

location /cable {
proxy_pass http://puma;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;

}

so the culprit line was:

proxy_pass http://example.com;

Here we are pointing it to NGINX which is wrong, it should point to our puma server path which in my configuration is represented by 'puma'.

Here is the Summary of my implementation of ActionCable and its working copy on Production Server

So to integrate Action Cable with Rails 5 you need to follow following steps:

  1. Setup Redis on default port.
  2. Add these lines in environments/staging.rb or environments/production.rb, depending on your application environment.

    config.action_cable.url = [/ws://*/, /wss://*/]

    config.action_cable.allowed_request_origins = [/http://*/, /https://*/]

  3. Finally setup you NGINX file as explained above. Here is my complete NGINX configuration in gist nginx.conf. I had replaced my site name with 'example.com' and project name with 'example'. So if you are copying anything, just make sure you replace those with yours otherwise nothing will work as paths will be broken.

I hope this will really release the pain while pushing ActionCable to live application and resolve this handshake error for anyone as this is very very tricky and technical thing and a lot of docs just mention to point action cable to your main site url and not puma server running behind your nginx.

Thanks.

Behah answered 26/6, 2018 at 17:55 Comment(2)
the configuration you're suggesting (especially the /ws://*/ and /http://*/ stuff) is highly insecure and should NEVER reside in any production environment. In any case, these adjustments are only needed, if the action-cable server does run as a separate instance.Progressive
i am facing a similar issue but see that it happens very sporadically, i am using passenger and nginx as a reverse proxy, any help on how to fix would be really great!Ambala

© 2022 - 2024 — McMap. All rights reserved.