Deploying your Production application on Linux with Apache and Mongrel
I've given up on shared hosting - too many variables. Instead I've invested in a VPS - meaning I have had to delve into the world of Linux (Fedora 6) administration.
First off, I had to set up my applications to run under mongrel (rather than the FCGI of your typical shared host). I followed the instructions in the "Agile Web Development" book - basically gem install mongrel and gem install mongrel_cluster on both your development box and the server. I also created a new user on the server that mongrel would run under - we wouldn't want your application running as root would we? Add require 'mongrel/recipes' to your Capistrano script and include the line set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml". If you are using my staging server instructions then you will probably need to change this - for example I have a mongrel_cluster_live.yml and a mongrel_cluster_test.yml. To create the mongrel_cluster configuration file go to your rails root folder and type mongrel_rails cluster::configure -e production -a 127.0.0.1 -N 3 -p 8000 -c /home/user/applications/current. This creates your mongrel_cluster.yml file - in this case with the production environment, listening to (the server's) local address, with three processes starting on port 8000 (so 8000, 8001, 8002) deployed to /home/user/applications on the server (the current is the symlink that Capistrano creates).
Run through your normal Capistrano deployment procedure - you should see that the last stage is mongrel_rails cluster::start - in the example above it will attempt to start three mongrel processes on the server on ports 8000, 8001 and 8002. If all has gone well you should be able to point your browser at those three ports and see your application.
Next up is getting your front-end web-server to connect to these mongrel processes. I'm using Apache 2.2 with mod_load_balancer (again as described in the Agile Web Development book) - this is so that requests for myapp.com on port 80 get routed to one of the mongrel processes. This requires editing /etc/httpd/conf/httpd.conf (back this file up before touching it!). Firstly, tell Apache about your mongrel processes:
Proxy balancer://myapp_mongrel
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
BalancerMember http://127.0.0.1:8002
/Proxy
This attaches the name myapp_mongrel to the three mongrel processes we set up earlier. Then we create a virtual host with the following RewriteRule attached:
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://myapp_mongrel{REQUEST_URI} [P,QSA,L]
This means that any request coming to Apache for myapp.com (or whatever your virtual host is called) is dealt with dynamically (Apache cannot find a static file to serve up in its place) is automatically passed to myapp_mongrel - which we have defined as http://127.0.0.1:8000..8002. So Apache forwards the request to one of your three mongrel processes which deals with it and returns the response back to Apache. Note that we could even set up the Mongrel processes to run on one or more different servers if we desired, spreading any really heavy loads across multiple machines.
This is all good, and nothing too unusual - as I say it's mostly taken directly from the Agile Web Development book.
However, I also wanted my mongrel processes to start up automatically, should I need to restart the server. So I added some scripts to /etc/init.d. As I said before I had created a separate user for the mongrel processes - I don't want any security issues compromising the entire server if I could help it. So my start up script (/etc/init.d/myapp - and don't forget to chmod +x) was slightly different to most.
#!/bin/bash
case "$1" in
start)
echo "starting myapp"
su - user -c "mongrel_rails cluster::start -C /home/user/application/current/config/mongrel_cluster.yml" >> /var/log/messages
;;
stop)
echo "stopping myapp"
su - user -c "mongrel_rails cluster::stop -C /home/user/application/current/config/mongrel_cluster.yml" >> /var/log/messages
;;
restart)
echo "restarting myapp"
su - user -c "mongrel_rails cluster::restart -C /home/user/application/current/config/mongrel_cluster.yml" >> /var/log/messages
;;
esac
Log in as root and try /etc/init.d/myapp restart - you should see mongrel stopping and then restarting. A quick ps aux should reveal your mongrel processes running under the correct user. Genius.
What is happening here is the use of su (switch user). By using su - username (the hypen is important) the script switches user to "username" and loads username's environment. Then the mongrel_rails command is run - explicitly passing it the configuration file that it needs to use. All output is passed to /var/log/messages for analysis later.
Lastly, we need to tell Fedora to run our script on startup.
Edit /etc/rc.local
/etc/init.d/myapp start
And that is it - getting your application deployed on linux using mongrel and apache. My only other step was to firewall off all ports except SSH and Web - so that no-one could access the mongrel processes directly.
No comments:
Post a Comment