about summary refs log tree commit homepage
path: root/site/src/docs/apache.page
diff options
context:
space:
mode:
Diffstat (limited to 'site/src/docs/apache.page')
-rw-r--r--site/src/docs/apache.page481
1 files changed, 481 insertions, 0 deletions
diff --git a/site/src/docs/apache.page b/site/src/docs/apache.page
new file mode 100644
index 0000000..ab26510
--- /dev/null
+++ b/site/src/docs/apache.page
@@ -0,0 +1,481 @@
+---
+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.3
+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 install 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 (*nix-style):
+
+<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 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>
+
+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. Reading REMOTE_USER from mongrel through proxy
+
+Jon Reads reports successfully reading the REMOTE_USER variable:
+
+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:
+
+<pre><code>
+   RewriteEngine On
+   RewriteCond %{LA-U:REMOTE_USER} (.+)
+   RewriteRule . - [E=RU:%1]
+   RequestHeader add X-Forwarded-User %{RU}e
+</code></pre>
+
+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.
+