3
votes

I've been trying to get ActionCable in a Ruby (2.5) on a Rails 5.2 app working on Production in an AWS, classic load balancer, Elastic Bean Stalk environment (passenger Amazon 64bit Linux 2.7.2, Postgresql) . At first, Redis wasn't working so I switched the adapter to postgresql which fixed a lot of page errors besides the two I currently have. The chat app is functioning properly except for the most important part of sending and receiving messages without refreshes. The ActionCable works just fine in Development, and I do not receive either errors. I am receiving one error in the logs and one repetitive error on the browser console.

Below is the error on Chrome, populating every few seconds.

application-d192ecfa7b18a37710113f3ff55fa53e559048f4f74047c1ac2895013f588b6e.js:22 WebSocket connection to 'wss://www.my-app.com/cable' failed: Error during WebSocket handshake: Unexpected response code: 404

Also in the logs, I receive this error:

E, [2018-12-01T00:09:22.806141 #8733] ERROR -- : [92c25112-2d7b-4ae5-8567-73f9f1eb73be] Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: keep-alive, HTTP_UPGRADE: )

Below are the relevant files for ActionCable. I have tried an awful lot of troubleshooting and different suggestions. I attempted to modify the nginx.conf file but whenever I put any passenger_* related directives, which a few sources recommended, restarting NGINX gave me an error saying [emerg] unknown directive. I tried other solutions inside this like specifying location /cable, a ton of guides, tutorials and SO posts like this one, in which I implemented and tried each: ActionCable - Failed to upgrade to WebSocket in production

cable.yml

development:
  adapter: postgresql

test:
  adapter: async

production:
  adapter: postgresql
  channel_prefix: production

Production.rb

  config.action_cable.mount_path = '/cable'
  config.action_cable.url = 'wss://mywebsite.com/cable'
  config.action_cable.allowed_request_origins = [ 'http://mywebsite.com',   'https://mywebsite.com' ]

cable.js

(function() {
  this.App || (this.App = {}); 

  App.cable = ActionCable.createConsumer("/cable");

}).call(this);

routes.rb

mount ActionCable.server => '/cable'

application_cable/connection.rb

module ApplicationCable
  class Connection < ActionCable::Connection::Base

    identified_by :current_admin

    def connect
      self.current_admin = find_verified_user
      logger.add_tags "ActionCable", "Admin: #{current_admin.email}"
    end 

    protected 

      def find_verified_user
        verified_user = Admin.find_by(id: cookies.signed['admin.id'])
        if verified_user
          verified_user
        else 
          reject_unauthorized_connection
        end 
      end 
    end
  end   

See update below for nginx configuration.

After running an nginx -t, this is the following readout:

nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied) 2018/12/10 20:33:52 [warn] 10587#0: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:5 2018/12/10 20:33:52 [warn] 10587#0: conflicting server name "localhost" on 0.0.0.0:80, ignored nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 2018/12/10 20:33:52 [emerg] 10587#0: open() "/var/run/nginx.pid" failed (13: Permission denied) nginx: configuration file /etc/nginx/nginx.conf test failed

Thank you so much for reading and any help.

UPDATE

Through the help of a Reddit user, (here's the link: reddit post ) I was able to resolve the Failed to upgrade Websocket error and the 404 Handshake Error response. This was accomplished by removing the nginx.conf configuration I have above and adding this to a default.conf file in the nginx/conf.d folder. Below is my new configuration.

 upstream backend {
        server unix:///var/run/puma/my_app.sock;
      }

      server {
        listen 80;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        large_client_header_buffers 8 32k;

        location / {
          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_set_header X-NginX-Proxy true;

          proxy_buffers 8 32k;
          proxy_buffer_size 64k;

          proxy_pass http://backend;
          proxy_redirect off;

          location /assets {
            root /var/app/current/public;
          }

          # enables WS support
          location /cable {
            proxy_pass http://backend;
            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;
          }
       }
    }

Now there are no errors in my production.log or on the browser console. However, I still have those nginx test errors and there is still an error in the nginx/error.log. That error is below:

2018/12/10 20:05:02 [error] 7640#0: *533 connect() to unix:///var/run/puma/my_app.sock failed (111: Connection refused) while connecting to upstream, client: 172.31.33.196, server: , request: "GET / HTTP/1.1", upstream: "http://unix:///var/run/puma/my_app.sock:/", host: "172.31.11.174"

Thanks again!

1
Hi, facing same error, did you find the solution?Divyang Desai
I'm sorry, DIv. I did not :( But here's a Reddit thread I started that might help somewhat. reddit.com/r/rails/comments/a44ji1/…Twistedben

1 Answers

0
votes
2018/12/10 20:05:02 [error] 7640#0: *533 connect() to unix:///var/run/puma/my_app.sock failed 
(111: Connection refused) while connecting to upstream, 
client: 172.31.33.196, server: , request: "GET / HTTP/1.1", upstream: "http://unix:///var/run/puma/my_app.sock:/", host: "172.31.11.174"

This error is due to the upstream did not find the my_app.sock file. You can just replace backend to ip:port in proxy_pass and error will go out. eg:

proxy_pass http://132.197.231.16:3000;