Reputation: 177
I have been studying Ruby on Rails for just over a month. I have deployed an app to a production VPS and am getting comfortable with Ruby/Rails in general. I am now trying to learn and build apps in one of the more recent Rails versions. Since multiple versions of Ruby/Rails is a commonplace concept among Rails developers, I figure I should play around with coding in different versions and maintaining those apps in a production environment.
It seems like from my googling and stackoverflow searches that what I am trying to do is not common. However, it forms the foundation for everything I want to do/learn about Rails and Passenger/Apache on my server (based on above goals). That is, hosting multiple Rails applications under the same domain name, some being the same ruby/rails version and others a different version. So:
mywebsite.com <--- Ruby 2.3.4 / Rails 4.2.5
mywebsite.com/profile <--- a separate app: Ruby 2.3.4 / Rails 4.2.5
mywebsite.com/cool-app <--- a separate app using the latest and greatest features: Ruby 2.5.0 / Rails 5.1.4
When I search stackoverflow for "multitenancy rails passenger", there are exactly 0 results. There is also this link: https://www.phusionpassenger.com/library/deploy/apache/
Which has an article called "Deploying multiple apps on a single server (multitenancy)", but it doesn't exist yet and says: "to-do"! I've been trying to stumble my way through it, but it seems like there is too much I don't understand to just copy and paste someone else's code and get it to work.
It seems like part of the trick to getting these things to work is with different VirtualHost setups.
Here is what I have tried for the above applications:
mywebsite.com (main site):
<VirtualHost *:80>
ServerName mywebsite.com
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/login_app/code/public
PassengerRuby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby
# Relax Apache security settings
<Directory /var/www/login_app/code/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
<Directory /var/www/login_app/code/public/profile>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
PassengerBaseURI /profile
</VirtualHost>
mywebsite.com/profile (same Ruby/Rails versions as main site)
<VirtualHost *:80>
ServerName mywebsite.com
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/test_app/code/public
PassengerAppRoot /var/www/test_app/code
PassengerRuby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby
# PassengerBaseURI /profile
# Relax Apache security settings
<Directory /var/www/test_app/code/public>
PassengerEnabled on
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
</VirtualHost>
Haven't even attempted to do a VirtualHost file for the 3rd app. I would assume that the PassengerRuby field would tell Passenger to use the correct/different Ruby interpreter. But again, I can't find anyone who does this, and I especially can't find any explanations for what is being done. When I find something even remotely close, it was from 6 years ago and the code is obsolete because Passenger supposedly handles this pretty easily now (but where are the examples?!).
It seems like when I go to mywebsite.com/profile, the main site app is still handling the route, as it logs to main_site_path/log/production.log (not the second app's log).
Any help would be appreciated, but since I know I should be specific, here are some specific things it might help me to know?:
Should there be a Passenger process running for each app when I do passenger-memory-stats, or just the main one?
How do I correctly define that /profile off my main domain should be handled by a different Rails App (different VirtualHost if applicable)?
Thanks.
Upvotes: 1
Views: 993
Reputation: 177
ZOMG it works! So a big thanks to tadman for suggesting that I use Nginx as a reverse proxy server. That is, one Nginx serves individual Apache processes for each app. I am able to go to mywebsite.com and get the main app. I go to mywebsite.com/subapp and get my second app (same Ruby/Rails version as the main one). I can go to mywebsite.com/mea and get a third app (that has a different Ruby and Rails version than the first two!).
Part of this is possible because both Nginx and Apache have a Passenger component that you can install, giving you all sorts of Directives you can use to specify what kind of app each url should serve up (passenger_ruby lets you tell Nginx which ruby interpreter to use). I've never seen documentation as comprehensive and beautiful as on Phusion's website.
Figuring this out was fun. Here is my setup so that you can see what I did. And please let me know if there's anything I could do better.
Nginx config: /etc/nginx/sites-enabled/apache
server {
listen 80;
server_name mywebsite.com www.mywebsite.com;
passenger_enabled on;
location / {
passenger_ruby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby;
proxy_pass http://my_website_ip:8080;
proxy_set_header Host $host;
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 $scheme;
}
location /subapp {
passenger_ruby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby;
proxy_pass http://my_website_ip:8081;
proxy_set_header Host $host;
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 $scheme;
}
location /mea {
passenger_ruby /usr/local/rvm/gems/ruby-2.5.0/wrappers/ruby;
proxy_pass http://my_website_ip:8082;
proxy_set_header Host $host;
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 $scheme;
}
}
My Ports file listens for the ports served by Nginx:
/etc/apache2/ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf
Listen 8080
Listen 8081
Listen 8082
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
My Apache VirtualHost definitions.
/etc/apache2/sites-enabled/login_app.conf
<VirtualHost *:8080>
ServerName mywebsite.com
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/login_app/code/public
PassengerRuby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby
# Relax Apache security settings
<Directory /var/www/login_app/code/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:8081>
ServerName mywebsite.com
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/second_app/code/public
PassengerRuby /usr/local/rvm/gems/ruby-2.3.4/wrappers/ruby
# Adding a subapp to the base url
Alias /subapp /var/www/second_app/code/public
<Location /subapp>
PassengerBaseURI /subapp
PassengerAppRoot /var/www/second_app/code
</Location>
# Relax Apache security settings
<Directory /var/www/second_app/code/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:8082>
ServerName mywebsite.com
# Tell Apache and Passenger where your app's 'public' directory is
DocumentRoot /var/www/third_app/code/public
PassengerRuby /usr/local/rvm/gems/ruby-2.5.0/wrappers/ruby
# Adding a subapp to the base url
Alias /mea /var/www/third_app/code/public
<Location /mea>
PassengerBaseURI /mea
PassengerAppRoot /var/www/third_app/code
</Location>
# Relax Apache security settings
<Directory /var/www/third_app/code/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
Require all granted
</Directory>
</VirtualHost>
And the processes produced, from the command line: passenger-memory-stats
Version: 5.2.0
Date : 2018-02-09 03:22:39 +0000
--------- Apache processes ----------
PID PPID VMSize Private Name
-------------------------------------
148.9 MB 0.4 MB /usr/sbin/apache2 -k start
813.3 MB 3.1 MB /usr/sbin/apache2 -k start
557.3 MB 3.2 MB /usr/sbin/apache2 -k start
### Processes: 3
### Total private dirty RSS: 6.74 MB
---------- Nginx processes -----------
PID PPID VMSize Private Name
--------------------------------------
174.8 MB 0.7 MB nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
174.8 MB 0.8 MB nginx: worker process
### Processes: 2
### Total private dirty RSS: 1.57 MB
----- Passenger processes -----
PID VMSize Private Name
-------------------------------
379.5 MB 4.7 MB Passenger watchdog
666.2 MB 7.1 MB Passenger core
378.9 MB 4.2 MB Passenger watchdog
662.5 MB 5.5 MB Passenger core
318.0 MB 63.0 MB Passenger RubyApp: /var/www/login_app/code (production)
314.5 MB 60.3 MB Passenger RubyApp: /var/www/third_app/code (production)
315.7 MB 61.4 MB Passenger RubyApp: /var/www/second_app/code (production)
### Processes: 7
### Total private dirty RSS: 206.14 MB
Upvotes: 3