ActionCable stopped working after upgrading to Ruby 3.0 - ruby-on-rails

For context, my current production server runs on AWS EC2, with a Application Load Balancer in front, the server stack is Nginx + Passenger + Redis (5.0.6), currently running Ruby 2.7.7 using RBENV, I use ActionCable for some real time messaging on the "/cable" endpoint, and it works fine. The Rails version is 6.1.6.1
But after upgrading to Ruby 3.0.5, suddenly I am getting "Websocket is closed before the connection is established"
Here's the nginx error.log :
18:17:22 [error] 9475#9475:
*56 upstream prematurely closed connection while reading response header from upstream. client: 172.30.21.12
server: request:
"GET /cable HTTP/1.1". upstream: "passenger :unix:/tmp/passenger.AW7j1af/agents.s/core:".
My Nginx configuration currently looks like this :
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 60;
types_hash_max_size 2048;
client_body_buffer_size 20m;
client_max_body_size 50M;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
passenger_log_level 3;
passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /home/deploy/.rbenv/shims/ruby;
passenger_max_pool_size 5;
passenger_min_instances 5;
server {
listen 80 default_server;
passenger_enabled on;
passenger_app_env production;
passenger_max_request_queue_size 200;
root /var/www/my_app_name/current/public;
location /cable {
passenger_app_group_name myapp_name_production_websocket;
passenger_force_max_concurrent_requests_per_process 0;
}
}
}
The ActionCable related code is :
// app/assets/javascripts/cable.js
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
I have mounted "/cable" in the routes.rb :
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end
I have read all ActionCable + Nginx related questions in StackOverflow, and I have tried putting proxy headers in the Nginx config files like this :
location /cable {
passenger_app_group_name myapp_name_production_websocket;
passenger_force_max_concurrent_requests_per_process 0;
/* I have tried adding this, no effect */
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
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 X-Forwarded-Proto https;
proxy_set_header Host $http_host;
}
I restarted the server after adding these, but the same error still persists.
I have updated passenger gem and websocket-ruby gem to latest.
I have narrowed down the issue to be related to Ruby version changes, as when I revert back the Ruby version to 2.7.7, then everything works as usual, it stopped working when I upgrade Ruby to 3.0.5

Related

ERR_TOO_MANY_REDIRECTS Rails + Puma + Nginx (Dockerized)

I'm running a dockerized rails app with puma and nginx, however, I'm getting ERR_TOO_MANY_REDIRECTS when trying to access the application from a browser.
I have config.force_ssl = true on my application.rb and this is my nginx conf file:
upstream kisoul {
server rails:3000;
}
server {
listen 80;
listen 443 ssl;
root /usr/share/nginx/kisoul;
try_files $uri #kisoul;
location #kisoul {
proxy_pass_request_headers on;
proxy_ignore_headers Expires Cache-Control;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://kisoul;
}
ssl_certificate /etc/nginx/fullchain.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
}
I have already tried disabling force_ssl from rails and forcing the redirect through nginx, but then I get a problem with Origin header, saying that the origin header (https://localhost) didn't match request.base_url (HTTP://localhost)
I tried many different solutions already described here, but I couldn't find any solution

Ruby on Rails app with Nginx unreachable

I'm deploying my Ruby on Rails website on a remote server.
I put my code in /var/www/[websitename]
/opt/nginx/conf/nginx.conf is as follows:
worker_processes 1;
events {
worker_connections 1024;
}
http {
passenger_root /home/tamer/.rvm/gems/ruby-2.5.0#meraki/gems/passenger-5.2.0;
passenger_ruby /home/tamer/.rvm/gems/ruby-2.5.0#meraki/wrappers/ruby;
passenger_app_env development;
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name http://[my external ip];
# Tell Nginx and Passenger where your app's 'public' directory is
root /var/www/[my directory]/public;
index index.html index.htm;
# Static assets are served from the mentioned root directory
location / {
# root /var/www/APPNAME/current;
# index index.html index.htm;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
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-Real-Port $server_port;
# proxy_set_header X-Real-Scheme $scheme;
proxy_set_header X-NginX-Proxy true;
}
Then, I ran rails s -b 127.0.0.1 -p 3000
The code runs perfectly in my terminal.
However, the browser gives me "This site can’t be reached".
I get the same result with passenger start -a 127.0.0.1 -p 3000
How can I fix this problem
It worked after running iptables -F and restarting my rails appllication.
NOTE
your are connecting to your passenger instance localhost:3000
you should be able to connect via http://localhost IE default port 80 I think this is what you desire.
listen 80; <- > proxy_pass http://127.0.0.1:3000;

Connection Time Out: Private_Pub + SSL + Nginx

I have implemented Private_Pub with SSL and I am running that over port 4443 as recommended in: https://github.com/ryanb/private_pub#serving-faye-over-https-with-thin
However, whenever I actually use the private_pub service I receive the following error:
Errno::ETIMEDOUT: Connection timed out - connect(2) for "www.mysite.com" port 4443
The really odd thing is that it was working on another server before we migrated providers.
I have ensured port 4443 is open by telnet-ing to it successfully. I have played around with the nginx config without any luck. I have restarted the thin server several times just to see if I get lucky.
I am able to access: https://www.mysite.com:4443/faye/faye.js
Can anybody point me in the right direction here?
Edit: Added my nginx config file:
worker_processes 1;
error_log /var/log/nginx.log debug;
events {
worker_connections 1024;
}
http {
passenger_root /home/me/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.52;
passenger_ruby /home/me/.rvm/gems/ruby-2.1.2/wrappers/ruby;
passenger_app_env production;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
root /var/www/mysite/current/public;
rails_env production;
passenger_enabled on;
}
server {
listen 443;
root /var/www/mysite/current/public;
rails_env production;
proxy_read_timeout 1200;
client_max_body_size 20m;
error_log /var/log/nginx.log debug;
ssl on;
ssl_certificate /var/server.crt;
ssl_certificate_key /var/server.key;
proxy_set_header X-Forwarded-Proto: https;
passenger_pass_header X-Forwarded-Proto;
passenger_enabled on;
# Tried it also without this part to no avail
location /faye {
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_redirect off;
root /var/applications/current/faye;
proxy_pass http://127.0.0.1:4443;
break;
}
}
server {
listen 80;
listen 443;
server_name www.mysite.co mysite.co;
return 302 $scheme://www.mysite.com$request_uri;
}
}

Multiple Rails 4 app using nginx + unicorn [duplicate]

This question already has answers here:
multiple rails apps on nginx and unicorn
(3 answers)
Closed 8 years ago.
I'm looking for set up a nginx server with unicorn. I the first app is set but it's on the root "/". what i really want is type localhost/app1 and it would run, while if a just enter to the root, html or php pages are going to be open.
Any clue?
Here's the current nginx.config:
worker_processes 4;
user nobody nogroup; # for systems with a "nogroup"
pid /tmp/nginx.pid;
error_log /tmp/nginx.error.log;
events {
worker_connections 1024; # increase if you have lots of clients
accept_mutex off; # "on" if nginx worker_processes > 1
}
http {
include mime.types;
default_type application/octet-stream;
access_log /tmp/nginx.access.log combined;
sendfile on;
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
tcp_nodelay off; # on may be better for some Comet/long-poll stuff
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/html text/xml text/css
text/comma-separated-values
text/javascript application/x-javascript
application/atom+xml;
upstream sip {
server unix:/home/analista/www/sip/tmp/sockets/sip.unicorn.sock fail_timeout=0;
}
server {
listen 80 default deferred; # for Linux
client_max_body_size 4G;
server_name sip_server;
keepalive_timeout 5;
# path for static files
root /home/analista/www/sip/public;
try_files $uri/index.html $uri.html $uri #app;
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
# proxy_buffering off;
proxy_pass http://sip;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://sip;
break;
}
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/analista/www/sip/public;
}
}
}
I've got it!
Turns out it was really simple and I wrote a post about it on my blog. http://jrochelly.com/post/2013/08/nginx-unicorn-multiple-rails-apps/
Here's the content:
I'm using Ruby 2.0 and Rails 4.0. I suppose you already have nginx and unicorn installed. So, let's get started!
In you nginx.conf file we are going to make nginx point to a unicorn socket:
upstream unicorn_socket_for_myapp {
server unix:/home/coffeencoke/apps/myapp/current/tmp/sockets/unicorn.sock fail_timeout=0;
}
Then, with your server listening to port 80, add a location block that points to the subdirectory your rails app is (this code, must be inside server block):
location /myapp/ {
try_files $uri #unicorn_proxy;
}
location #unicorn_proxy {
proxy_pass http://unix:/home/coffeencoke/apps/myapp/current/tmp/sockets/unicorn.sock;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
Now you can just Unicorn as a Deamon:
sudo unicorn_rails -c config/unicorn.rb -D
The last thing to do, and the one I dug the most is to add a scope for your rails routes file, like this:
MyApp::Application.routes.draw do
scope '/myapp' do
root :to => 'welcome#home'
# other routes are always inside this block
# ...
end
end
This way, your app will map a link /myapp/welcome, intead of just /welcome
But there's a even better way
Well, the above will work on production server, but what about development? Are you going to develop normally then on deployment you change your rails config? For every single app? That's not needed.
So, you need to create a new module that we are going to put at lib/route_scoper.rb:
require 'rails/application'
module RouteScoper
def self.root
Rails.application.config.root_directory
rescue NameError
'/'
end
end
After that, in your routes.rb do this:
require_relative '../lib/route_scoper'
MyApp::Application.routes.draw do
scope RouteScoper.root do
root :to => 'welcome#home'
# other routes are always inside this block
# ...
end
end
What we are doing is to see if the root directory is specified, if so use it, otherwise, got to "/". Now we just need to point the root directory on config/enviroments/production.rb:
MyApp::Application.configure do
# Contains configurations for the production environment
# ...
# Serve the application at /myapp
config.root_directory = '/myapp'
end
In config/enviroments/development.rb I do not specify the config.root_directory. This way it uses the normal url root.

nginx + passenger + rails: do I need to start the rails server or just start nginx?

I'm trying to have my rails server listen on 2 different ports. One solution proposed to me was to use nginx. I installed nginx with sudo passenger-install-nginx-module and added the following to /etc/nginx/conf.d:
server {
listen 80;
listen 10000;
server_name www.myapp.com
passenger_enabled on;
root /root/myapp/public;}
When I went to www.myapp.com I got a 403 Forbidden error. I figured it was because there were no static html files in /public. I dropped a simple "hello world" html page in there and it loaded correctly. I then proceeded to start my rails app using passenger start -e production, which caused it to run in standalone phusion passenger mode on port 3000. I go to myapp.com:3000 and I get the app. However, myapp:80 and myapp:10000 still don't work. I'm confused on how to get my nginx to point to the rails server I'm running. Am I doing this completely wrong? Thanks!
Set nginx to forward to my rails server using this https://gist.github.com/jeffrafter/1229497
worker_processes 1;
error_log /usr/local/var/log/nginx.error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream dev {
server 127.0.0.1:3000;
}
server {
listen 80;
# You could put a server_name directive here (or multiple) if
# you have not setup wildcard DNS for *.dev domains
# See http://jessedearing.com/nodes/9-setting-up-wildcard-subdomains-on-os-x-10-6
# If we choose a root, then we can't switch things around easily
# Using /dev/null means that static assets are served through
# Rails instead, which for development is okay
root /dev/null;
index index.html index.htm;
try_files $uri/index.html $uri.html $uri #dev;
location #dev {
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_redirect off;
proxy_pass http://dev;
}
error_page 500 502 503 504 /50x.html;
}
}

Resources