Add a reverse proxy to heroku - ruby-on-rails

I have a rails app running on heroku at, e.g myapp.herokuapp.com.
Now I want to reverse proxy from myapp.heroku.com/proxy/ to somewhereelse.com/ (i.e: myapp.heroku.com/proxy/stuff is reverse proxifed to somewhereelse.com/stuff)
Is that possible on Heroku? How to achieve this?

For anyone coming to this question through a search, this can be done.
Check out https://github.com/ryandotsmith/nginx-buildpack to vendor nginx into your heroku instance. This will place nginx in front of your rails app, and allow you to reverse proxy requests on this domain, having your heroku app configured as apex and allowing somewhereelse.com/stuff go elsewhere.

You dont have access to frontend routing infrastructure so its not possible to do add something like nginx location based reverse proxying or apache's modproxy. From my understanding too you can only bind to one port (the $PORT) within the dyno so its not possible to shadow your Rails app with your own vendored version of nginx (unless it is possible to communicate over a non TCP/IP socket between nginx and your rack/rails app, if this is the case then perhaps you can get rack to listen to /tmp/mysocket.git and nginx to reverse proxy on this, this could be a no starter though, Im just throwing out ideas).
Which means the only probable option if you have to handle this yourself in your rails app, I have only a tiny tiny bit of rails/ruby experience, but if no proxy functionality exists in rails then you perhaps you can explicitly accept the route and then use a http client to invoke the other parts.

Related

Is it possible to extend api built in Ruby on Rails with NodeJs?

I am learning Node.Js and I already have some API built in Ruby.
Is there a way to add extra endpoints to that API using Node.Js?
Thanks
You have a few options:
Have your node app be a reverse proxy and listen to all calls, whatever routes it does not handle, forward it to the rails App.
Forward express js route to other server
Have your Rails app be a reverse proxy and forward the new routes to the node app.
How can I use Rails routes to redirect from one domain to another?
Using a a reverse proxy like ngnix or traefik. These would listen to all routes and send the request to the app you have configured. Traefik makes it really easy if you're already using docker. Traefik also has a binary file for windows/mac/linux that's also pretty easy to setup using the [File] config
https://docs.traefik.io/

What is the best practice for Nginx/ELB/Unicorn architecture on AWS?

We have an RoR application in AWS Beijing. AWS Beijing does not have Route 53 (We can't use Alias to apply ELB to Apex domain), so we must use a Front-end Server running Nginx in front of ELB.
Now our architecture likes below:
Front-end (Nginx) -- ELB --- App-(1~n) (Nginx--Unicorn)
We have noticed the words from Unicorn description below:
"Unicorn must never be exposed to slow clients, as it will never ever use new-fangled things like non-blocking socket I/O, threads, epoll or kqueue. Unicorn must be used with a fully-buffering reverse proxy such as nginx for slow clients."
So my question are:
1. Before Unicorn, do we need nginx on the App Server?
2. If we remove nginx on App Server, can nginx on Front-end Server play such the effect like unicorn describing?
I would recommend replacing the ELB with HAProxy in this scenario where you don't have the alias feature from Route53 to point to your apex domain. Putting a Nginx instance in front of the ELB doesn't seem to be a good idea because you are adding a new layer just because you can't reference the ELB on Route53. You also lose the benefit of high availably by putting a Nginx instance in front of it the ELB.
My suggestion is that you keep one instance of Nginx on each of your app servers in front of Unicorn and use HAProxy as load balancer: HAProxy > [Nginx > Unicorn]. In a simple setup of HAProxy you also don't have the same availability of the ELB but you can setup a high available configuration if needed.
1) Nginx must be always in front Unicorn because Unicorn can't deal with slow clients efficiently, it just locked by those clients
2) Never talk to Unicorn via network, it means each app server need to have its own Nginx. Nginx as Load Balancer is a way better than ELB black box.

Is anyone providing their own routing mesh with a reverse proxy back to Heroku as a backend?

I'm interested in having a Heroku backend i.e. application server, database server, workers, add ons, etc.
I would like to provide my own routing mesh though, and reverse proxy with Nginx and unicorn server for a Rails app.
Does this seem possible before I give it a shot. I would assume that I could just provide my apps Heroku domain in the upstream directive?
Thanks!
Heroku does not provide a way to configure this in their reverse proxy, but you can run your own, e.g. with nginx-buildpack (see also this answer).

Deploying Rails and Nodejs

I wrote a real-time web app that consists of the following:
Rails to serve the web pages (listens on port 80)
Nodejs to handle real-time logic (listens to port 8888)
So on a particular page served by my rails app, the JS will use socket.io to establish a connection to my nodejs instance to allow real time http push.
Currently Nodejs communicates with Rails simply by updating the rails database. (I know this is ghetto but it works).
What are my options for deployment?
I have deployed simple web apps on heroku before and I really like the simplicity.
I have also deployed a web app with similar functionality (except it's made up of django + nodejs). I used HAProxy to do reverse proxying to handle direction of traffic to the correct process on my machine. However, I deployed this on a VPS server instead.
Note: the ugliness will probably revolve around:
I am relying on a common db
These processes are listening on different ports
We had this exact issue. We deployed them to separate Heroku applications, but kept them within the same code base. http://techtime.getharvest.com/blog/deploying-multiple-heroku-apps-from-a-single-repo outlines how to do it.
Manually set the buildpack
Set a config variable that you can reuse in step #3.
Create a custom web script that your Procfile uses
A custom script in bin/web
#!/bin/bash
if [ "$RAILS_DEPLOYMENT" == "true" ]; then
bundle exec rails server -p $PORT
else
node node/index.js
fi
And the Procfile:
web: bin/web
I would consider setting these two applications up as separate Heroku applications on different subdomains and just having them both on port 80. The communication between them goes through a shared database so they don't need to reside on the same machine or even datacenter. Socket.io supports cross domain requests on all browsers, so that shouldn't cause any problems.

Serving web application without Lighttpd/Apache

As Rails applications default run on port 3000, would it be possible to start the application on port 80? Is it really required to have a fastcgi/mod_proxy enabled web server in front? My users won't be more than three at a time. If so, how would I be able to do so?
Thanks!
WARNING: This is not a general purpose description of how to set up a Ruby on Rails production environment. If you want to host a public Rails website, I highly recommend using Apache with Passenger, which is very easy to install and maintain.
From your description, it sounds like you are working with some kind of internal application to be used within your office or similar. For this particular purpose, hosting the application via Webrick (the built-in web server in Rails) might be a sufficient solution. To do this, start the server with a -p command line argument: ruby script/server -p 80
This obviously requires port 80 to be available (not bound by some other web server). Also, on most operating systems, you will need root privileges to bind to port 80. The security implications of running a web site as root are serious, so you really only want to do this if you know what you are doing, and are absolutely sure that the server is completely shielded from the Internet.
If there isn't some specific reason you're trying to run with mongrel, I would recommend using Phusion Passenger as it is significantly easier to configure and support than mod_proxy+mongrel.
mongrel - http://github.com/fauna/mongrel
thin - http://code.macournoyer.com/thin/

Resources