diff options
Diffstat (limited to 'site/src/docs/apache.page')
-rw-r--r-- | site/src/docs/apache.page | 556 |
1 files changed, 0 insertions, 556 deletions
diff --git a/site/src/docs/apache.page b/site/src/docs/apache.page deleted file mode 100644 index 28ebe3c..0000000 --- a/site/src/docs/apache.page +++ /dev/null @@ -1,556 +0,0 @@ ---- -title: Apache -inMenu: true -directoryName: Apache ---- - -h1. Apache Best Practice Deployment - -h3. By Charles Brian Quinn - -The preferred setup (for now) is to put Mongrel behind an Apache 2.2.x -server running mod_proxy_balancer. Apache is a proven web server, runs -half the Internet, and is a pain to configure. These instructions should -get you started, but refer to the Apache folks for anything more complex -or weird. - -When you're just starting out, don't bother with doing anything but -running just Mongrel. Mongrel is slower than Apache, but not so slow that -small installations will notice it. The worst thing you can do is -try to learn Apache configuration when you're also trying to learn Ruby on Rails -and Mongrel too. Start small, then *when you need*, build up to the big stuff. - -h2. A simple single mongrel configuration - -Start up a single mongrel instance on port 8000: - -<pre><code> - $ mongrel_rails start -d -p 8000 \ - -e production -P /full/path/to/log/mongrel-1.pid -</code></pre> - -Now, we'll tell Apache to simply proxy all requests to the mongrel server -running on port 8000. Simply add the following to your httpd.conf or in -a vhost.conf file: - -<pre><code> - <VirtualHost *:80> - ServerName myapp.com - ServerAlias www.myapp.com - - ProxyPass / http://www.myapp.com:8000/ - ProxyPassReverse / http://www.myapp.com:8000 - ProxyPreserveHost on - </VirtualHost> -</code></pre> - -That's it, in a nutshell. Several things to note in this configuration: - -1) This configuration forwards all traffic to mongrel. This means mongrel -will serve images, javascript, files, and everything else. It's quite fast -at this, but Apache can do it better. - -Here are some basic proxypass rules you can add to tell the ProxyPass not -to forward on requests to certain documents/requests: - -<pre><code> -ProxyPass /images ! -ProxyPass /stylesheets ! -#continue with other static files that should be served by apache - -Alias /images /path/to/public/images -Alias /stylesheets /path/to/public/stylesheets -#continue with aliases for static content -</code></pre> - -For a more detailed set of rules for forwarding on all dynamic content to mongrel, -see the more detailed configuration below for more details. - -2) In this configuration, it is entirely possible that two users (web -requests) could hit your application at the exact same time, and one would -have to wait literally milliseconds until the first request is finished -before having a turn at the mongrel instance. Unless you've got some really -long HTTP processes, the nature of the HTTP protocol is pretty good at waiting -in line. Only you can determine ("through metrics":http://mongrel.rubyforge.org/docs/how_many_mongrels.html) how long and -how many users will come at your application at the exact same time. - -Sufficient to say, if you're ready to start scaling with multiple mongrel -instances, read on. - -h2. Using multiple mongrel instances with mod_proxy_balancer - -First, let's start up a few mongrel instances (linux/freesd): - -<pre><code> -$ mongrel_rails start -d -p 8001 \ - -e production -P log/mongrel-1.pid -$ mongrel_rails start -d -p 8002 \ - -e production -P log/mongrel-2.pid -$ mongrel_rails start -d -p 8003 \ - -e production -P log/mongrel-3.pid -$ mongrel_rails start -d -p 8004 \ - -e production -P log/mongrel-4.pid -</code></pre> - -You can also use "mongrel_cluster":http://mongrel.rubyforge.org/docs/mongrel_cluster.html by "Bradley Taylor":http://fluxura.com/ for -managing several mongrel instances with a configuration file (and sysv init -scripts for -nix-flavor servers). - -We're going to be requiring the use of mod_proxy_balancer, a "new feature":http://httpd.apache.org/docs/2.2/new_features_2_2.html in -Apache 2.1/2.2 and above to proxy requests to -our mongrel instances. This software based HTTP load balancer will distribute -requests evenly (applying a weighting and selection algorithm) to our mongrel -instance(s). It even comes with a swell load-balancing manager page for -monitoring incoming requests. For more information, see: -"Apache's mod_proxy_balancer Documentation":http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html. - -h2. Obtaining Apache 2(.1+) - -I won't go into too many details, as windows and the various linux -distributions all have several methods for obtaining apache2, but you will need -the use of the following modules: - - * mod_proxy, mod_proxy-html, and mod_proxy_balancer - * mod_rewrite - * mod_deflate - * mod_headers - * (optional) mod_cache and one of mod_memcache or mod_filecache - * (optional) mod_ssl - -If you're compiling from source, this configuration should do the trick: - -<pre><code> -#./configure --enable-deflate --enable-proxy --enable-proxy-html \ ---enable-proxy-balancer --enable-rewrite --enable-cache \ ---enable-mem-cache --enable-ssl --enable-headers -</code></pre> - -Note: If you're going to be serving only Mongrel instances (Mongrel -serving up Ruby on Rails or any other ActiveRecord containing framework), -some have noted better performance and stability using the MPM worker class -instead of the pre-fork. If you don't know what this means, it's safe to -ignore. - -Essentially, in the default pre-fork worker mode, Apache will spawn several -processes when it starts up (pre-forking) and will spawn more if more requests -come in that need to be handled. On a heavily trafficked, very dynamic (not -much cached content/assets) Rails site, if you are doing nothing but servicing -Rails, it doesn't make sense to spawn 20 apache processes, in front of 3 -Mongrel processes, as Mongrel will be queuing them up, anyways. - -h2. Configuring Apache2 - -A good practice is the separation of apache configuration files. Recommended -by several other good guides, we'll be storing information for our application -in several different files. Put these files somewhere that apache2 knows -about. Apache is quite good about scanning for all .conf files in certain -directories. - -h3. myapp.common - -Apache lets you include common configuration items into another configuration -so you can cut down on repetition. What we're going to do is make a file -that has all the common junk that every Mongrel application needs to -work at all, then we'll just include this in little .conf files for -any application we deploy. - -Notice that this file doesn't end in .conf since it's not a real configuration -file, but you can name it however you wish. - -<b>Important Update: "typo fixed in IE deflate rules":http://rubyforge.org/pipermail/mongrel-users/2006-October/001868.html</b> - -<pre><code> - ServerName myapp.com - DocumentRoot /var/www/myapp.com/current/public - - <Directory "/var/www/myapp.com/current/public"> - Options FollowSymLinks - AllowOverride None - Order allow,deny - Allow from all - </Directory> - - RewriteEngine On - - # Uncomment for rewrite debugging - #RewriteLog logs/myapp_rewrite_log - #RewriteLogLevel 9 - - # Check for maintenance file and redirect all requests - # ( this is for use with Capistrano's disable_web task ) - RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f - RewriteCond %{SCRIPT_FILENAME} !maintenance.html - RewriteRule ^.*$ /system/maintenance.html [L] - - # Rewrite index to check for static - RewriteRule ^/$ /index.html [QSA] - - # Rewrite to check for Rails cached page - RewriteRule ^([^.]+)$ $1.html [QSA] - - # Redirect all non-static requests to cluster - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L] - - # Deflate - AddOutputFilterByType DEFLATE text/html text/plain text/css - # ... text/xml application/xml application/xhtml+xml text/javascript - BrowserMatch ^Mozilla/4 gzip-only-text/html - BrowserMatch ^Mozilla/4.0[678] no-gzip - BrowserMatch \bMSIE !no-gzip !gzip-only-text/html - - # Uncomment for deflate debugging - #DeflateFilterNote Input input_info - #DeflateFilterNote Output output_info - #DeflateFilterNote Ratio ratio_info - #LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate - #CustomLog logs/myapp_deflate_log deflate -</code></pre> - -h3. myapp.conf - -We then take the above commmon file and include it in our configuration file -for this application deployment. - -If you're using virtual hosting (a pretty good idea, even when you're the only -one on the server), your sample configuration can be this simple: - -<pre><code> - <VirtualHost *:80> - Include /etc/httpd/conf.d/myapp.common - - ErrorLog logs/myapp_errors_log - CustomLog logs/myapp_log combined - </VirtualHost> -</code></pre> - -h3. myapp.proxy_cluster.conf - -This is the meat of our configuration, and goes hand in hand with our mongrel -(or mongrel_cluster) configuration. This configuration tells the apache2 -mod_proxy_balancer to proxy requests to 3 mongrel instances running on ports -8000, 8001, and 8002. - -<pre><code> - <Proxy balancer://mongrel_cluster> - BalancerMember http://127.0.0.1:8000 - BalancerMember http://127.0.0.1:8001 - BalancerMember http://127.0.0.1:8002 - </Proxy> -</code></pre> - -If you had an seperate application server, you could balance to it easily by -replacing the 127.0.0.1 with the ip or hostname of your application server, but -be sure to make them listen on an external interface (rather than 127.0.0.1). - -When you add an additional mongrel to your mongrel_cluster, you can simply add -an additional BalancerMember to this file, restart apache (or reload) and -you're all set. - -h3. (optional) myapp.proxy_frontend.conf - -This optional file will setup the balancer-manager -- a simple front-end for -viewing how your requests are being handled. This balancer in the -configuration below will only work from the localhost, so no one else (or -possibly you) can view it unless you alter the "Deny" and "Allow" lines. - -<pre><code> -Listen 8080 -<VirtualHost *:8080> - <Location /> - SetHandler balancer-manager - Deny from all - Allow from localhost - </Location> -</VirtualHost> -</code></pre> - -h3. SSL Requirements - -In order for mongrel to know that this request has a forwarded protocol of -https, we'll need to add a special header (hence the addition of mod_header, -included in most apache2 builds). - -<pre><code> - Include /etc/httpd/conf.d/myapp.common - - # This is required to convince Rails (via mod_proxy_balancer) that we're - # actually using HTTPS. - RequestHeader set X_FORWARDED_PROTO 'https' -</code></pre> - -You need this mostly so that redirects go back to https and so you can -spot when people are coming through SSL or not. - -h2. Automation, Automation, Automation - -There are several great tools that automate the setup of Apache for use with -mongrel and mongrel_cluster. The "RailsMachine gem":https://support.railsmachine.com/index.php?pg=kb.chapter&id=18 can -automate an entire setup of a Rails application. Also, "Slingshot Hosting":http://www.slingshothosting.com/ has -a sample set of "Capistrano recipes":http://www.slingshothosting.com/support/capistrano that automatically setup Apache2 and mongrel -through the @rake remote:setup@ task. Be sure to check out both for some ideas. - -h2. Running Multiple Rails Apps with Mongrel - -The newest version of Mongrel supports multiple Rails applications through -the use of the --prefix command. The Apache magic for proxying a -single application is here assuming your prefix is app1: - -<pre><code> -ProxyPass /app1 http://127.0.0.1:3000/app1 -ProxyPassReverse /app1 http://127.0.0.1:3000/app1 -</code></pre> - -You need to have the proxy pass the new directory name. - -Thanks to Joey Geiger and others of the mongrel list for these -instructions. - -h2. Success Stories - -Martins on the mongrel-list has submitted this simple apache configuration. It serves up static content with apache, and forwards dynamic content on to mongrel using ProxyPass. Thanks Martins: - -<pre><code> -<VirtualHost *> - ServerName myapp.tld - ServerAlias www.myapp.tld - - DocumentRoot /var/www/sites/myapp/current/public - - <Directory "/var/www/sites/myapp/current/public"> - Options FollowSymLinks - AllowOverride None - Order allow,deny - Allow from all - </Directory> - - RewriteEngine On - - # Check for maintenance file. Let apache load it if it exists - RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f - RewriteRule . /system/maintenance.html [L] - - # Let apache serve static files - RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f - RewriteRule (.*) $1 [L] - - # Don't do forward proxying - ProxyRequests Off - - # Enable reverse proxying - <Proxy *> - Order deny,allow - Allow from all - </Proxy> - - # Pass other requests to mongrel instance - ProxyPass / http://127.0.0.1:8200/ - ProxyPassReverse / http://127.0.0.1:8200/ - -</VirtualHost> -</code></pre> - -Phillip Hallstrom has submitted this apache configuration, which includes support for having static directories handled by Apache, php support, and hiding svn directories. - -<pre><code> -<VirtualHost *:80> - - ServerName myserver.com - DocumentRoot /path/to/my/app/public - - <Directory "/path/to/my/app/public"> - Options FollowSymLinks - AllowOverride None - Order allow,deny - Allow from all - </Directory> - - <Proxy balancer://mongrel_cluster> - BalancerMember http://127.0.0.1:8805 - </Proxy> - - RewriteEngine On - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} -d - RewriteRule ^(.+[^/])$ $1/ [R] - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} \.php - RewriteRule ^(.*)$ $1 [QSA,L] - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}/index.html -f - RewriteRule ^(.*)$ $1/index.html [QSA,L] - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}/index.php -f - RewriteRule ^(.*)$ $1/index.php [QSA,L] - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} -d - RewriteRule ^(.*)[^/]$ $1/ [QSA,L] - - RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f - RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L] - - AddOutputFilterByType DEFLATE text/html - AddOutputFilterByType DEFLATE application/x-javascript - AddOutputFilterByType DEFLATE text/css - AddOutputFilterByType DEFLATE text/plain - AddOutputFilterByType DEFLATE text/xml - AddOutputFilterByType DEFLATE application/xml - AddOutputFilterByType DEFLATE application/xhtml+xml - - BrowserMatch ^Mozilla/4 gzip-only-text/html - BrowserMatch ^Mozilla/4.0[678] no-gzip - BrowserMatch bMSIE !no-gzip !gzip-only-text/html - - php_value include_path /path/to/my/app/php:/usr/local/lib/php:. - php_value auto_prepend_file /path/to/my/app/php/auto_prepend.php - - # this not only blocks access to .svn directories, but makes it appear - # as though they aren't even there, not just that they are forbidden - <DirectoryMatch "^/.*/\.svn/"> - ErrorDocument 403 /404.html - Order allow,deny - Deny from all - Satisfy All - </DirectoryMatch> - -</VirtualHost> -</code></pre> - -Jens Kraemer reports this differing proxy setup that uses the P option in Rewrite rules so as not to use the ProxyPass directive: - -<pre><code> - # Don't do forward proxying - ProxyRequests Off - - # Enable reverse proxying - <Proxy *> - Order deny,allow - Allow from all - </Proxy> - - RewriteEngine On - - # Check for maintenance file. Let apache load it if it exists - RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f - RewriteRule . /system/maintenance.html [L] - - # Rewrite index to check for static - RewriteRule ^/$ /index.html [QSA] - - # Let apache serve static files (send everything via mod_proxy that - # is *no* static file (!-f) - RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f - RewriteRule .* http://127.0.0.1:8200%{REQUEST_URI} [L,P,QSA] -</code></pre> - -the P option to the last rule replaces the ProxyPass and -ProxyPassReverse directives. - - -h2. SVN Security - -If you use svn to issue checkouts instead of exports, you'll need to hide those pesky .svn directories. This works: - -<pre><code> -# this not only blocks access to .svn directories, but makes it appear - # as though they aren't even there, not just that they are forbidden - <DirectoryMatch "^/.*/\.svn/"> - ErrorDocument 403 /404.html - Order allow,deny - Deny from all - Satisfy All - </DirectoryMatch> - -</VirtualHost> -</code></pre> - -h2. Sending Environment variables to mongrel through proxy - -Jon Reads reports successfully reading the REMOTE_USER variable: - -<blockquote> -After many hours trying to solve the same problem I found this post: "Forcing a proxied host to generate REMOTE_USER":http://www.nabble.com/Forcing-a-proxied-host-to-generate-REMOTE_USER-tf1114364.html#a2914465 - -and can confirm that the following works for me when put in the Proxy directive on Apache 2: -</blockquote> - -<pre><code> - RewriteEngine On - RewriteCond %{LA-U:REMOTE_USER} (.+) - RewriteRule . - [E=RU:%1] - RequestHeader add X-Forwarded-User %{RU}e -</code></pre> - -*Update:* - -Satya reports that this works better: - -<pre><code> -RewriteEngine On -RewriteCond %{IS_SUBREQ} ^false$ -RewriteCond %{LA-U:REMOTE_USER} (.+) -RewriteRule . - [E=RU:%1] -RequestHeader add Remote-User %{RU}e -</code></pre> - -His explanation: - -<blockquote> -Note the first RewriteCond. The LA-U in the 2nd RewriteCond causes an -internal subrequest, which causes inf recursion inside apache. Apache -eventually catches it, but it does bog down the server (and crashed our -shib, but that's not your problem). I think the 1st RewriteCond fixes -it. -</blockquote> - -Peer Allen reports that you can send any environment variable through to mongrel: - -<blockquote> -Here is the Apache config I used to forward the GEOIP_COUNTRY_CODE from the -Maxmind mod_geoip module. It is basically the same as the REMOTE_USER -forwarding, but since the GEOIP variable is an environment variable in -Apache you have to access it differently in the RewriteCond with the "ENV" -prefix. See the mod_rewrite documentation for this: -</blockquote> - -<pre><code> -2. %\{ENV:variable}, where variable can be any environment variable, is -also available. This is looked-up via internal Apache structures and (if not -found there) via getenv() from the Apache server process. -</code></pre> ---"http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#RewriteRule":http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#RewriteRule - -<pre><code> -# Forward the GEOIP_COUNTRY_CODE -RewriteCond %\{ENV:GEOIP_COUNTRY_CODE} (.+) -RewriteRule . - [E=RU:%1] -RequestHeader add X-Forwarded-GeoIP %{RU}e -</code></pre> - -h2. Caveats - -Jason Hoffman reports: - -<blockquote> -Apache's mod_proxy_balancer module is a fully blocking module and with -the default httpd.conf you're going to max out in the 120-160 requests/ -second range on a decent box. You can tune up its proxying to about a -1000 req/sec. - -So yes the net result is that you can really only put a couple of -mongrels behind apache's proxy engine (about 2 "hello world" rails -mongrels). -</blockquote> - -h2. References and Other Guides - -[1] "Time For A Grown-Up Server: Rails, Mongrel, Apache, Capistrano and You":http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/ - -[2] "Bradley Taylor's Fluxura":http://fluxura.com/ and "RailsMachine":http://www.railsmachine.com/ - -[3] "Slingshot Hosting Automated Capistrano Recipe":http://www.slingshothosting.com/support/capistrano - -Thanks to many users on the mongrel list for making it easy for me to compile all these tips and tricks as they come across the list. - |