Rails/Puma with Apache HTTPD proxy? - ruby-on-rails

I want to use Puma with HTTPD to serve my Rails application. As far as I can tell there aren't very many examples of people doing such a thing. I know nginx has some benefits over HTTPD, and that Passenger makes a lot of things easy, but is there a reason to not use Puma/HTTPD?
I've skimmed through a few examples online and put together an HTTPD config block that I like and that seems to be working fine (though I haven't done any performance testing). Am I missing anything? This seems easier/more simple than most Puma/nginx or Passenger/HTTPD setups, which makes me a little worried.
<VirtualHost *:3008>
DocumentRoot MY_RAILS_ROOT/public
ProxyPass /favicon.ico !
ProxyPass /robots.txt !
ProxyPassMatch ^/(404|422|500).html$ !
ProxyPass /assets/ !
ProxyPass / http://127.0.0.1:9292/ # Puma bind address
ProxyPassReverse / http://127.0.0.1:9292/
</VirtualHost>

This is a fairly common usage of Apache HTTPD as a reverse proxy, so there are no particular issues. Are you running both the web server and puma on the same machine? It might be a good idea to split them to prevent issues with memory consumption, the TCP stack and any other contention that may occur under high load.
If you have multiple puma nodes then you can use HTTPD to perform load balancing across all nodes like this:
<VirtualHost example.org:80>
ServerName example.org
ServerAlias www.example.org
ErrorLog /srv/www/example.org/logs/error.log
CustomLog /srv/www/example.org/logs/access.log combined
DocumentRoot MY_RAILS_ROOT/public
<Proxy balancer://cluster>
BalancerMember http://app1.example.org
BalancerMember http://app2.example.org
</Proxy>
ProxyPass /favicon.ico !
ProxyPass /robots.txt !
ProxyPassMatch ^/(404|422|500).html$ !
ProxyPass /assets/ !
ProxyPass / balancer://cluster/
# enumerate all nodes for proxypassreverse since it adds a trailing slash :( bugid 51982
ProxyPassReverse / http://app1.example.org
ProxyPassReverse / http://app2.example.org
# ProxyPass / balancer://cluster/ lbmethod=byrequests
# ProxyPass / balancer://cluster/ lbmethod=bytraffic
# ProxyPass / balancer://cluster/ lbmethod=bybusyness
</VirtualHost>
Although if you have a better HA option (ie AWS ELBs, HAProxy, Varnish or anything ) then I would prefer that as you get Layer 7 availability checks for free

Related

Rails action cable with apache 2.4

I am trying to get a chat application working using rails action cable and apache. I am trying to make this work https://github.com/ScotchSource/ActionCableUploading, but no luck just yet.
Apache config
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
# I have tried many different URI to be proxied, but still no luck
ProxyPass /test-app/cable ws://servername:7521/test-app/cable
ProxyPassReverse /test-app/cable ws://servername:7521/test-app/cable
Alias /test-app /var/www/test-app/public
<Location /test-app>
PassengerBaseURI /test-app
PassengerAppRoot /var/www/test-app
</Location>
<Directory /var/www/test-app/public>
Allow from all
Options -MultiViews
Require all granted
</Directory>
</VirtualHost>
Made a few changes and tried different URLs in config.action_cable.url in environment/development.rb to point to the correct proxy in apache config.
I have read many blog posts and articles and tried different setups. Some people manage to make it work, but when I tried their solution it does not work. Any ideas/suggestions would be appreciate it.

Rails, Apache, Thin on Windows. Better configuration for httpd.conf

I'm using this configuration with the lines in this good answer (Rails Deployment Environment on Windows):
<VirtualHost *:82>
# Your server's web or IP address goes here.
# You can leave at localhost if deploying to
# company intranet or some such thing.
ServerName localhost
# Customize the next two lines with your app's public directory
DocumentRoot "C:/RubyStack-3.2.5-0/projects/app_name/public"
<Directory "C:/RubyStack-3.2.5-0/projects/app_name/public">
Allow from all
Options -MultiViews
</Directory>
RewriteEngine On
# Redirect all non-static requests to Rails server,
# but serve static assets via Apache
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://app_balancers%{REQUEST_URI} [P,QSA,L]
# Serves dynamic rails assets from multiple servers
# to improve performance. A Rails server such as
# thin or WEBrick must be running on at least one of
# these ports in order for Apache to serve your site
<Proxy balancer://app_balancers>
BalancerMember http://localhost:3001/
BalancerMember http://localhost:3002/
</Proxy>
# Support for far-futures expires header
<LocationMatch "^/assets/.*$">
Header unset ETag
FileETag None
# RFC says only cache for 1 year
ExpiresActive On
ExpiresDefault "access plus 1 year"
</LocationMatch>
</VirtualHost>
But browsing, I found other articles and other questions of other people who have configured Apache httpd in a different way, by adding or subtracting configuration lines.
Like here: http://www.varyonic.com/2011/06/using-apache-with-mongrel-or-thin-and-rails-3/#.VK5OhyuG9G6
What is it?:
ProxyPreserveHost On
ProxyPass /images !
ProxyPass /stylesheets !
ProxyPass /javascripts !
ProxyPass / balancer://thinservers/
ProxyPassReverse / balancer://thinservers/
Now, of course, I'm here to ask you: what is best for Rails 4 on Windows 8.1 / Windows 10?
The server Thin is the best for Windows 8.1/10? Mongrel? Other?
Alternatives to Apache for stability and speed?
The operating system is Windows and I can not change it.

How do you use apache to route different subdomains to different ports / servers?

On my dev machine, I want to be able to have an SSL server, and a non-SSL server (both running off the same code... but running both servers is the easy part.)
For my regular server: I want it to be sub1.mydomain.com
so, I've modified my VirtualHost such that instead of saying
mydomain.com
*.mydomain.com,
it says
sub1.mydomain.com
*.sub1.mydomain.com
and then for the SSL server, I just said
sub2.mydomain.com
*.sub2.mydomain.com
except, whenever I got to a sub2.mydomain url, the server attached to sub1 processes the request.
What am I doing wrong here?
I'm using ruby on rails, and apache.
EDIT: added the actual virtual hosts
<VirtualHost *:80>
DocumentRoot "/Users/me/projects/myproject/public"
ServerName reg.mydomain.com
#ServerAlias *.reg.mydomain.com
ProxyPass / http://localhost:3001/
ProxyPassReverse / http://localhost:3001
</VirtualHost>
<VirtualHost *:443>
SSLEngine on
SSLProxyEngine On
RequestHeader set Front-End-Https "On"
CacheDisable *
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
DocumentRoot "/Users/me/projects/myproject/public"
ServerName ssl.mydomain.com
#ServerAlias *.ssl.mydomain.com
SSLCertificateKeyFile "/private/etc/apache2/certs/server.key"
SSLCertificateFile "/private/etc/apache2/certs/server.crt"
ProxyPass / https://localhost:3002/
ProxyPassReverse / https://localhost:3002
ProxyPreserveHost on
</VirtualHost>
It sounds like you're trying to do named virtual hosts?
http://httpd.apache.org/docs/2.2/vhosts/name-based.html
Assuming that rails isn't doing anything too funky, you can try having a virtual host that looks like this:
NameVirtualHost *
<VirtualHost *>
ServerName sub1.mydomain.com
DocumentRoot /var/www/sub1 or point this to the server instead.
</VirtualHost>
<VirtualHost *>
ServerName sub2.mydomain.com
DocumentRoot /var/www/sub2 or point this to the server instead.
</VirtualHost>

Passenger: RailsBaseURI case sensitive?

I used Passenger to deploy a RoR app to a sub URI on my domain. The problem I'm facing is that the sub URI seems to be case sensitive. Navigating to http://mydomain.com/RailsApp resolves fine. However, if I go to http://mydomain.com/railsapp, http://mydomain.com/railsApp, or any other variation, I get a 404 error. How can these requests using different casings get resolved correctly?
Here is my Apache configuration file:
<VirtualHost *:80>
ServerName mydomain.com
ServerAlias www.mydomain.com
DocumentRoot /www/mydomain/public
<Directory "/www/mydomain/public">
RailsEnv "production"
Order allow,deny
Allow from all
</Directory>
RailsBaseURI /RailsApp
<Directory "/www/RailsApp/public">
RailsEnv "development"
Options -MultiViews
</Directory>
</VirtualHost>
Any help is much appreciated. Thanks!
You could look into using mod_rewrite and matching it case insensitive there.
Some links to get you started :)
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
http://httpd.apache.org/docs/2.2/misc/rewriteguide.html
Thanks ba for pointing me in the right direction.
I did some research and found the mod_speling module. This not only makes the URL case-insensitive but also checks for spelling errors.
To enable mod_speling:
sudo /usr/sbin/a2enmod speling
sudo /etc/init.d/apache2 force-reload
sudo /etc/init.d/apache2 restart
To use mod_speling, include the directive CheckSpelling on in your virtual host section:
<VirtualHost *:80>
CheckSpelling on
...
</VirtualHost>

Configuring Ruby On Rails App in a subdirectory under Apache

I've got apache2.2 on windows. I'm trying to serve both subversion (/svn) and redmine (/redmine). I have svn running fine with this config:
<Location /svn>
DAV svn
SVNParentPath C:/svn_repository
...
</Location>
This is working great--my svn users can hit http://mybox/svn just fine.
Now I want to add another directory for a rails app (RedMine):
I followed the advice in this question to setup a mongrel server and have apache proxy clients through to it. It works fine if I make it the root--but I'm having trouble making it in a subdirectory:
<Location /redmine>
ProxyPass http://localhost:3000/
ProxyPassReverse http://localhost:3000/
</Location>
Any suggestions?
Here's what I had to change:
I removed the trailing slash:
<Location /redmine>
ProxyPass http://localhost:3000
ProxyPassReverse http://localhost:3000/
</Location>
And in my rails app:
# added to end of file C:\redmine\config\environment.rb
ActionController::AbstractRequest.relative_url_root = "/redmine"
Now it's working!
I wasn't completely happy with this approach--I ran into some redirect issues. This is another attempt which seems to be working well so far.
Fast CGI and Fast CGI without VirtualHosts
Tuning Fast CGI
This second approach seems better.
UPDATE:
As noted in the comments, for more recent apps running on Rails 2.3.2+, use this instead:
config.action_controller.relative_url_root = '/redmine'
I put it in the new additional_environment.rb file.
In case you still wish to use Mongrel + Apache using a reverse proxy here is how I solved the same issue on our system (Win2k3, Apache 2.2, trunk of Redmine). The secret is to install your mongrel service using --prefix /redmine which tells it to serve it from http://localhost:port/redmine
In Apache httpd.conf (or suitable include file):
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<IfModule mod_proxy.c>
ProxyRequests Off
#No need to forward on static content - let apache do it faster
ProxyPass /redmine/images !
ProxyPass /redmine/stylesheets !
ProxyPass /redmine/javascript !
# Remove the following entry on public sites as this is insecure
ProxyPass /redmine/plugin_assets !
ProxyPass /redmine/help !
ProxyPass /redmine http://localhost:4000/redmine
ProxyPassReverse /redmine http://localhost:4000/redmine
ProxyPreserveHost On
#continue with other static files that should be served by apache
Alias /redmine/images C:/Repositories/redmine/public/images/
Alias /redmine/stylesheets C:/Repositories/redmine/public/stylesheets/
Alias /redmine/javascript C:/Repositories/redmine/public/javascript/
# Remove the following on public sites as this is insecure
Alias /redmine/plugin_assets C:/Repositories/redmine/public/plugin_assets/
Alias /redmine/help C:/Repositories/redmine/public/help/
</IfModule>
# Make sure apache can see public and all subfolders - not suitable for public sites
<Directory "C:/Repositories/redmine/public/">
Allow from all
Order allow,deny
</Directory>
Mongrel is installed as such:
mongrel_rails service::install --prefix /redmine -N redmine_prod -p 4000 -e production -c C:\Repositories\redmine
Hope that helps someone. Initially, I tried setting up Apache + fastcgi etc but I lost more precious hair - it's not Windows friendly.
P.s. I found this PDF a very useful referene: http://www.napcsweb.com/howto/rails/deployment/RailsWithApacheAndMongrel.pdf
/Damien
Passenger (http://modrails.com) is a better alternative to fastcgi because it's very easy to configure I would recommend using this for hosting your rails apps using a similar configuration to what you have now
I agree with Radar. Passenger is really easy to set up, lets Rails apps share memory, removes the burden of managing a cluster of mongrels and requires virtually no configuration. All you need are a special 'config.ru' file with a RackUp config and a DocumentRoot pointing to RAILS_ROOT/public set in Apache.

Resources