Apache 2.0.x + Mongrel + mod_proxy + mod_rewrite configuration

When I decided to try the switch from fcgid to mod_proxy + mongrel for this blog (and now the majority of my projects at work), I discovered there was no example of such configuration or at least not all in one place.
This post will try to fill this lack of a complete example. The distro i’m using here is Debian, but the configuration should be easily ported to yours.

Thereafter I assume you already have a working configuration with :

- Apache 2.0.x - mod_proxy_http (thanks AMicky) - mod_proxy - mod_rewrite

mod_proxy configuration :

There’s not so much to change here, just allow proxying to anyone for local domains.

/etc/apache2/mods-available/proxy.conf

  <Proxy *>
Order deny,allow

  1. next line was Deny from all
    Allow from all
    </Proxy>

A sample vhost file

This configuration is intended to be used with a RubyOnRails application served by Mongrel and deployed with Capistrano.

So you should notice some nice things, like auto-disabling website with a personalized message when there’s a maintenance.html page found, serving static contents directly by apache (no uneeded hit on mongrel) and conserving access to cgi-bin directory (see my previous post about awstats).

/etc/apache2/sites-available/zone.mydomain.tld.conf

<VirtualHost *>

  1. Set the domain
    ServerName mydomain.tld
  2. Set domain aliases
    ServerAlias www.mydomain.tld
    ServerAlias web.mydomain.tld
  1. Set the DocumentRoot, this is where apache will look for static files
  2. This is the public directory of your rails application
  3. As previously stated, my app is deployed with Capistrano, so I set DocumentRoot to the current/public directory
    DocumentRoot /var/www/mydomain.tld/current/public/
  1. Set where you want apache put its logs
  2. note I use deflate as log format, this is because I use mod_deflate to compress all outputs
    CustomLog /var/www/mydomain.tld/logs/access.log deflate
    ErrorLog /var/www/mydomain.tld/logs/error.log
  1. if you want to have server-wide statistics,
  2. you can also tell apache to log in a common file shared by all your domains
    CustomLog /var/log/apache2/access.log deflate
    ErrorLog /var/log/apache2/error.log
  1. I use utf-8 for all my projects, so I force apache to send the good charset by default.
  2. This is needed if you use page caching and want apache serves these with the good charset.
    AddDefaultCharset utf-8
  1. Allow limited access to your public directory
  2. dont allow user to list directories
  3. allow apache to FollowSymlinks
    <Directory /var/www/mydomain.tld/current/public/>
    Options -Indexes FollowSymLinks
AllowOverride All Order allow,deny Allow from all </Directory>
  1. Be sure mod_rewrite is activated for you vhost
    RewriteEngine On
  1. If you use applications which resides in cgi-bin, like awstats
  2. the following mod_rewrite RewriteRule will allow apache to know it should not proxy these request and the PT switch will allow the ScriptAlias directive to work
    RewriteRule "^/cgi-bin/." "$0" [QSA,PT,L]
    RewriteRule "^/awstatsicon/.
    " "$0" [PT,L]
  1. Set a ScriptAlias for /cgi-bin/ url
  2. All url begining with /cgi-bin/ will be served from the specified cgi-bin deirectory
    ScriptAlias /cgi-bin/ /var/www/mydomain.tld/cgi-bin/
    <Directory /var/www/mydomain.tld/cgi-bin/>
    AllowOverride All
    Options ExecCGI FollowSymLinks
    Order allow,deny
    Allow from all
    </Directory>
  1. Do not allow open proxying, allow only requests starting with a /
    <LocationMatch "^[^/]">
    Deny from all
    </LocationMatch>
  1. Avoid open you server to proxying
    ProxyRequests Off
  1. Let apache correctly rewrite redirect
    ProxyPassReverse / http://localhost:8001/
  1. Let apache pass the original host not the ProxyPass one
    ProxyPreserveHost On
  1. As I mentioned earlier, Capistrano disable_web task allows you to disable your application
  2. In fact it only create a simple page named maintenance.html in the directory public/system/ of your application
  3. The following mod_rewrite rules will tell apache to directly serve the maintenance.html pages if it find it out.
    RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
    RewriteCond %{SCRIPT_FILENAME} !maintenance.html
    RewriteRule ^.*$ /system/maintenance.html [L]
  1. For static files it's good to avoid hitting your mongrel process
  2. so let apache knows it should serve it directly
  3. for a rails application it means, files in images / stylesheets / javascripts
    RewriteRule "^/(images|stylesheets|javascripts)/?(.*)" "$0" [L]
  4. Try to match a cached pages
    RewriteRule ([.]+)$ $1.html [QSA]
  5. if the cached page does not exists
    RewriteCond %{REQUEST_FILENAME} !-f
  6. proxy requests to your mongrel instance
    RewriteRule "^/(.*)" "http://localhost:8001/$1" [P,QSA,L]
    </VirtualHost>
[…]
Published on Wed, 26 Jul 2006 21:28
21 comments

RewriteRule for ScriptAlias with mod_proxy enabled

Since my switch to Apache2+mod_proxy+mongrel, I had some troubles figuring how to make urls defined by a ScriptAlias work.

As an example, take Awstats, tipically it’s configuration involve a ScriptAlias directive in you vhost configuration.

Something like :

ScriptAlias /awstats/ /var/www/your_site_dir/cgi-bin/awstats/
<Directory /var/www/your_site_dir/cgi-bin/awstats/>
   AllowOverride All
   Options ExecCGI FollowSymLinks
   Order allow,deny
   Allow from all
</Directory>

But when mod_proxy is enabled, all requests are proxied, ignoring your ScriptAlias directive.

A solution if you also use mod_rewrite is to write something like this :

RewriteRule "^/awstats/.*" "$0" [PT,L]

The magic switch is PT which enable rewrite rules to be shared between differents mods.[…]

Published on Wed, 26 Jul 2006 15:22
2 comments

Switch to Apache + mod_proxy + Mongrel

In my quest to find the best rails configuration, I decided to try a new alternative to Apache+FastCGI/Apache+FCGID/Lighttpd+FastCGI.

Everyone seems to be focused on Mongrel combined with Apache 2.2 + mod_proxy_balancer. It looks good but Apache 2.2 isn’t actually in Debian (not even in unstable), and as I choose to switch this blog from a Fedora Core 2 (ooch !) server to another server of mine powered by Debian, it really doesn’t fits my needs.

So I choosed to try a different approach and use Apache 2.0.x + mod_proxy + Mongrel. This solution, gives me the possibility to use mongrel_cluster for process management, even if actually I don’t have multiple mongrel instances, and add a load balancer (Pen/Balance/Pound) if needed.

This setup seems to be sufficient for this blog, which runs the latest Typo (3.99.3).

Let me know if you see any differences with the previous configuration.[…]

Published on Sat, 15 Jul 2006 12:29
3 comments

RSS