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!