I'm creating realtime update chat app with Rails(api mode) and react using following technologies.
1.rails 5.2.1
2.puma 3.12.0
3.ruby 2.4.6
4.nginx 1.12.2
5.redis 4.0.10
6.aws elasticache
frontend/index.js
import ActionCable from 'actioncable'
ActionCable.createConsumer(`wss://myapp.com:3000/cable?authorization=${tokens['Authorization']}&firebaseUID=${tokens['FirebaseUID']}`)
config/environments/production.rb
config.action_cable.url = 'wss://myapp.com/cable:3000'
config.action_cable.allowed_request_origins = [ 'http://myapp.com', /http:\/\/myapp.*/, 'https://myapp.com', /https:\/\/myapp.*/ ]
nginx.conf
upstream puma {
server unix:///srv/myapp/tmp/sockets/puma.sock;
}
location / {
try_files $uri $uri/index.html $uri.html #webapp;
}
location #webapp {
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://puma;
}
location /cable {
proxy_pass http://puma/cable;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
config/cable.yml
production:
adapter: redis
url: ENV['ELASTIC_CACHE_URL']} <= endpoint of elasticache(redis4.0)
But I'm getting the following error.
main.js:89513 WebSocket connection to 'wss://myapp.com:3000/cable' failed: WebSocket is closed before the connection is established
Can somebody give me advice?
Related
I'm trying to connect to an ActionCable websocket and everything works fine running locally with just Puma and without nginx.
However, when I try to do the exact same thing on my staging environment, the connection is immediately closing after connecting. I am able to get the downstream welcome messages and maybe a ping.
However, the connection abruptly closes without any of the onClose callbacks so my guess is nginx is not letting the connection persist.
Here is my sites nginx configuration.
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/my-app/shared/tmp/sockets/puma.sock fail_timeout=60;
keepalive 60;
}
server {
listen 80;
server_name localhost;
# websocket_pass websocket;
root /home/deploy/my-app/current/public;
try_files $uri/index.html $uri #app;
location #app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
#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 also found this error in nginx error logs:
2019/02/11 21:08:35 [error] 10233#10233: *2 recv() failed (104: Connection reset by peer) while proxying upgraded connection, client: x.x.x.x, server: localhost, request: "GET /cable/ HTTP/1.1", upstream: "http://unix:/home/deploy/wr-api/shared/tmp/sockets/puma.sock:/cable/", host: "x.x.x.x"
So after some time, we noticed that the staging environment cable.yml had this value for url:
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
Removing that value and all other values except for adapter: staging fixed it for us.
New cable.yml staging config:
staging:
adapter: redis
Working!
This question has been asked many times but I am not able to figure out problem even after trying all solutions.
I am getting
[a9736d85-6b19-425f-b9b0-50070ad6ca5f] Started GET "/api/v1/notifications/"[non-WebSocket] for 172.18.0.8 at 2017-10-16 18:30:31 +0000
[a9736d85-6b19-425f-b9b0-50070ad6ca5f] Failed to upgrade to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: close, HTTP_UPGRADE: )
[a9736d85-6b19-425f-b9b0-50070ad6ca5f] Finished "/api/v1/notifications/"[non-WebSocket] for 172.18.0.8 at 2017-10-16 18:30:31 +0000
In my development.rb I have
config.action_cable.allowed_request_origins = [ 'http://172.18.0.8:3000', 'http://0.0.0.0:3000', '0.0.0.0', '0.0.0.0:3000']
In nginx.config, I have
location #rails {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
location /cable {
proxy_pass http://unicorn;
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;
}
}
cable.yml looks like
development:
adapter: redis
url: redis://localhost:6379/1
Please tell me why I am getting this error?
Thanks in advance.
I got it running (with Puma) using the following nginx.conf:
upstream app {
server app:3000 fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /usr/src/app/public;
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;
}
location /cable {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
break;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Trying to deploy super simple rails 5 application to AWS using beanstalk.
Everything works fine except actioncable. Browser can't connect to the cable server.
WebSocket connection to 'ws://prod.3x52xijcqx.us-west-1.elasticbeanstalk.com/cable' failed: Error during WebSocket handshake: Unexpected response code: 404
I found similar questions at stackoverflow but all of them were pointing to configure nginx using this template, however it didn't help me.
I customized nginx config using this script which I've put inside .ebextensions
files:
"/etc/nginx/conf.d/websockets.conf":
content: |
upstream backend {
server unix:///var/run/puma/my_app.sock;
}
server_names_hash_bucket_size 128;
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server_name prod.3x52xijcqx.us-west-1.elasticbeanstalk.com;
# prevents 502 bad gateway error
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;
# prevents 502 bad gateway error
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 $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
container_commands:
01_restart_nginx:
command: "service nginx restart"
Full app source is here
I'm trying to setup websockets on my rails application. My application works with iOS client that uses SocketRocker library.
As websockets backend i use faye-rails gem.
It is integrated to the rails app as rack middleware
config.middleware.delete Rack::Lock
config.middleware.use FayeRails::Middleware, mount: '/ws', server: 'passenger', engine: {type: Faye::Redis, uri: redis_uri}, :timeout => 25 do
map default: :block
end
It works perfect until i upload it to the production server with Nginx. I have tried a lot of solutions to pass websocket request to the backend, but with no luck. The main thing is there are two servers running, but i have just one. My idea was i just needed to proxify requests from /faye endpoint to /ws (to update headers). What is correct proxy_pass parameters should be in my case?
location /faye {
proxy_pass http://$server_name/ws;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
I had a similar problem and after struggling for a while, I finally could make it work.
I'm using nginx 1.8 with thin server with gem 'faye-rails' and my mount point is /faye
My nginx config looked like this:
upstream thin_server {
server 127.0.0.1:3000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
...
proxy_redirect off;
proxy_cache off;
location = /faye {
proxy_pass http://thin_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}
location / {
try_files $uri/index.html $uri.html $uri #proxy;
}
location #proxy {
proxy_pass http://thin_server;
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;
}
...
}
The final turn point for me to make it work was when I set the "location = /faye". Before I tried "location /faye" and "location ~ /faye" and it failed.
It looks like the equal sign "=" prevents nginx to mix with other location settings.
I've hosted my rails application on Digitalocean using Dokku. There's this need for my application to run real-time applications through Faye. I've been trying several ways like the shoreman plugin for Dokku and adding faye: bundle exec rackup faye.ru -s thin -E production to "Procfile" file. But no luck till now, need help on how I can get this Faye server running for my app.
You need to make several steps to have working faye server (e.g. on port 9292):
Your Procfile is OK
Expose port 9292 on Docker. I recommend install docker-options plugin and next dokku docker-options:add timer "-p 9292:9292"
Setup your app nginx.conf. Mine is here:
upstream app { server 127.0.0.1:49154; }
server {
listen [::]:80;
listen 80;
server_name app.dokku.mine;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Request-Start $msec;
}
location /faye {
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_buffering off;
proxy_cache_bypass $http_pragma $http_authorization;
proxy_no_cache $http_pragma $http_authorization;
proxy_pass http://localhost:9292;
}
}
I suggest to install nginx-alt plugin because config is overwritten on every deploy.