So I tried to set up a rails app using Bryan Bate's private_pub gem (a wrapper for the faye gem) to create chat channels. It works great on my local machine in dev mode.
I'm also booting up the private_pub server on port 8080 at the same time my rails app starts by including a initializer file with the lines:
Thread.new do
system("rackup private_pub.ru -s thin -E production -p 8080")
end
however, after deploying to aws ec2 ubuntu instance with the nginx webserver and puma app sever, the chrome console keeps showing this every 2 seconds, and the real time chat features don't work.
GET http://localhost:8080/faye.js net::ERR_CONNECTION_REFUSED
If I open port 8080 in my aws security group, I can see the big chunk of javascript code in faye.js using curl from localhost:8080/faye.js when I ssh into the instance. I can also access it from my browser if I go to http://my.apps.public.ip:8080/faye.js. I can't access it if I remove 8080 from the security group, so I don't think this is an firewall problem.
Also, if I change the address from localhost to 0.0.0.0 or the public ip for my ec2 instance, the chrome console error is gone, but the real time chat is still not working.
I suspect I might have to do more configuration to nginx because all I have done so far to configure the nginx server is in /etc/nginx/sites-available/default, I have:
upstream app {
server unix:/home/deploy/myappname/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/myappname/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;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
But maybe this has nothing to do with nginx either, I'm pretty lost. Has anyone experienced this or could suggest an alternative solution? I could post any additional config files here if needed.
Solved
first I took Ian's advice and set server_name to my public ip
then
based on guide from http://www.johng.co.uk/2014/02/18/running-faye-on-port-80/
I added the location block
location ^~ /faye {
proxy_pass http://127.0.0.1:9292/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;
}
finally, for my private_pub.yml I set the faye entry point for production:
production:
server: "http://my.public.ip:80/faye/faye"
secret_token: "mysecrettoken"
signature_expiration: 3600 # one hour
and now the chatting in my app responds much faster than when I was using the remote standalone chat server I put on on heroku because both the chat server and my main app is running in the same instance.
Related
I'm setting up a web app, with a react frontend that I want to expose and some local backend modules, all deployed in docker-compose. Everything works fine in localhost.
Now, I need to use nginx to proxy the requests to my purchased domain, using a cloudflare website, and later using https. In Cloudflare, the SSL/TLS encryption mode is Off, for testing with http. Everything has been setup in cloudflare, according to some docs that I read. Unfortunatly, my nginx configuration is only working for localhost, preventing me from doing a https configuration. (getting 522 error when loading the page using my domain).
This is my nginx config file:
server {
listen 80;
server_name mydomain;
root /usr/share/nginx/html;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
location /statsmodule {
proxy_pass http://statsmodule:3020;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
}
location /auth {
proxy_pass http://auth:3003;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
}
(...)
# the other location blocks for the other services are similar to this
}
What am I missing?
What config.action_cable.url should be configured for websockets / Rails / Kubernetes /Minukube with Nginx?
When running "docker-compose" locally an Nginx processes in front of a Rails process (not API only, but with SSR) and a standalone Cable process (cf the guides), the websockets work fine by passing the following server-side (in say "/config/application.rb", with action_cable_meta_tag set in the layouts):
config.action_cable.url = 'ws://localhost:28080'
I am targetting Kubernetes with Minikube locally: I deployed Nginx in front of a Rails deployment (RAILS_ENV=production) along with a Cable deployment but I can't make it work. The Cable service is internal of type "ClusterIP", with "port" and "targetPort". I tried several variations.
Any advice?
Note that I use Nginx -> Rails + Cable on Minikube, and the entry-point is the Nginx service, external of kind LoadBalancer where I used:
upstream rails {
server rails-svc:3000;
}
server {
listen 9000 default_server;
root /usr/share/nginx/html;
try_files $uri #rails;
add_header Cache-Control public;
add_header Last-Modified "";
add_header Etag "";
location #rails {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Host $http_host;
proxy_pass_header Set-Cookie;
proxy_redirect off;
proxy_pass http://rails;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
To allow any origin, I also set:
config.action_cable.disable_request_forgery_protection = true
I have an answer: in a Minikube cluster, don't put anything and disable forgery protection, Rails will default the correct value. When Nginx is front of a Rails pod and a standalone ActionCable/websocket pod (the Rails image is launched with bundle exec puma -p 28080 cable/config.ru), if I name "cable-svc" the service that exposes the ActionCable container, and "rails-svc" the one for the Rails container, you need to:
in K8, don't set the config for CABLE_URI
in the Rails backend, you don't have the URL (unknown 127.0.0.1:some_port), do:
# config.action_cable.url <-- comment this
config.action_cable.disable_request_forgery_protection=true
in the Nginx config, add a specific location for the "/cable" path:
upstream rails {
server rails-svc:3000;
}
server {
[...root, location #rails {...}]
location /cable {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass "http://cable-svc:28080";
}
}
Check the logs, no more WebSockets in Rails, and Cable responds.
I am using websocket-rails gem for handling messaging service for my application.
Tech Stack: Rails 4.2.5, Ruby 2.3.0p0, Passenger as app-server(Also tried with Puma), Thin as websocket server on port 3001, ngnix as web server and
Websocket patch of gem 'websocket-rails', github: 'moaa/websocket-rails', branch: 'sync_fixes'
When an client hits the websocket server, it actively triggers the server event of client_connected and I can see on websocket_rails_server.log the message that I print, i.e.
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
"+++++++++++ WebsocketRails Client CONNECTED ++++++++++++++"
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
But, on client end it abruptly ends with response:
WebSocket connection to 'ws://beta.server.com/websocket' failed: Error during WebSocket handshake: Unexpected response code: 504
I have tried with every solution on Github issues as well as Stackoverflow related question, but no help yet.
My nginx config is as follows(if that's needed anyway):
server {
listen 80;
server_name beta.server.com;
root /var/www/server-rails/current/public;
proxy_cache_bypass 1;
proxy_no_cache 1;
location /websocket {
proxy_pass http://localhost:3001/websocket;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
add_header Access-Control-Allow-Origin *;
proxy_set_header Upgrade websocket;
proxy_set_header Connection upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
passenger_enabled on;
passenger_sticky_sessions on;
passenger_app_env staging;
}
I'm trying to introduce chatting to my Rails app. For this purpose I used gem private_pub and it works perfectly in development mode.
In production I was using Apache + Passenger, but I couldn't configure Faye with it, so I changed Apache to Nginx. My main app is still on Apache server, and this demo on Nginx with port 8080 (just for test).
I'm able to connect to faye.js by entering http://chat.mysite.com:8080/faye.js, but the connection from app throws an error (browser console).
WebSocket connection to 'ws://localhost:9292/faye' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
After this error, another error appears every 5 seconds.
faye.js:2 GET http://localhost:9292/faye?message=%5B%7B%22channel%22%3A%22%2Fmeta%2Fhands…22%2C%22callback-polling%22%5D%2C%22id%22%3A%221%22%7D%5D&jsonp=jsonp2 net::ERR_CONNECTION_REFUSED
My private_pub.yml
production:
server: "http://localhost:9292/faye"
secret_token: "mysecret"
signature_expiration: 3600 # one hour
My private_pub.ru
require "bundler/setup"
require "yaml"
require "faye"
require "private_pub"
Faye::WebSocket.load_adapter('thin')
PrivatePub.load_config(File.expand_path("../config/private_pub.yml", __FILE__), ENV["RAILS_ENV"] || "development")
run PrivatePub.faye_app
My nginx site.conf
server {
listen 8080;
server_name www.chat.mysite.com;
passenger_enabled on;
passenger_app_env production;
root /var/www/mysite/public;
location ^~ /faye {
proxy_pass http://127.0.0.1:9292;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_buffering off;
proxy_redirect off;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
#proxy_set_header X-Forwarded-Proto https;
proxy_cache_bypass $http_pragma $http_authorization;
proxy_no_cache $http_pragma $http_authorization;
break;
}
}
If I change private_pub.yml to http://localhost:9292/faye/faye, I saw error like "can't load resource /faye/faye.js".
How should I change my Nginx conf or app yml to resolve websocket error?
I see private_pub is quite similar to ActionCable in its design. Before you go too far down the road, you may want read my blog post on "ActionAcable - The good and bad parts" as it addresses suitable use cases when a system like private_pub is good, and when it's not.
If of course you are aware of the shortcomings already, then good luck!
I tried to configure my private_pub.yml as #niceman said. Now all is working good.
production:
server: "http://my-ip:8080/faye"
I'm trying to make my Rails app with Puma run with Nginx.
I use rails s and localhost:3000 work just fine.
But when I go to http://rails_host/, it returns
The server at rails_host can't be found, because the DNS lookup failed. DNS is the network service that translates a website's name to its Internet address
From my nginx.conf
http {
include rails.conf;
....
}
Here's my rails.conf file config
upstream rails_test {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name rails_host;
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_redirect off;
proxy_pass http://rails_test;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
And I just don't know if can I run multi rails app (right now only 1 app a time at port 3000), is there any way to run multi rails app with only subdomain, like rails_host/rails_app_1 and rails_host/rails_app_2 ...
Thanks!
DNS lookup failed for 'rails_test', kind-of a simple thing ain't it?
by default rails app use ssl in production mode. Your app is running in production mode. Disable force_ssl in environtments/production.rb to false and it will work