If you ever need to use Capistrano 2 with virtual hosts on Nginx this article may save you some time by automating the process.
The article assumes that for each vhost you want to define a nginx configuration file which gets placed in /etc/nginx/sites-available/
and symlinked to sites-enabled
. If you just want one big nginx file with all your vhosts in it, then this article won’t help!
What we want is for Capistrano to auto generate the nginx configuration using a shared configuration template and place it on the server. E.g.
For this config I’m using multiple mongrels. If you’re not using mongrel then you can just add your own custom settings to be used in the template. Make sure you use different mongrel ports for each application. The extra settings are in red
set :application, “subreview.com”
set :domain, application # for use in the template
set :mongrel_port, 8500 # starting port for the mongrels
set :mongrels, 2 #number of mongrels
set :public_html, ”/home/demo/public_html/” # folder where the apps are deployed to
set :deploy_to, ”#{public_html}#{application}”
set :nginx_remote_template, ”#{public_html}nginx.template”
set :nginx_remote_config,”#{public_html}nginx.#{application}”
set :spin_remote_template, ”#{public_html}spin.template”
set :spin_remote_config, ”#{deploy_to}/current/script/spin”
Above I configured the shared nginx.template file to be held in home/demo/public_html (you could place it anywhere). Here’s the template file…
# File generated on <%=Time.now().strftime("%d %b %y")%>
#upstream name has to be unique so add on the port number
<%upstream="mongrels_#{mongrel_port}"%>
#generate multiple mongrels
upstream <%=upstream %>{
<%mongrels.times do |n| %>
server 127.0.0.1:<%=n+mongrel_port%>;
<% end %>
}
# Redirect http://domain to http://www.domain
server {
listen 80;
server_name <%=domain %> ;
rewrite ^/(.*) http://www.<%=domain %> permanent;
}
server {
listen 80;
server_name www.<%=domain %>;
access_log <%=deploy_to%>/shared/log/access.log;
error_log <%=deploy_to%>/shared/log/error.log;
root <%=deploy_to%>/current/public/;
index index.html;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect false;
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (-f $request_filename.html) {
rewrite (.*) $1.html break;
}
if (!-f $request_filename) {
proxy_pass http://<%=upstream %>;
break;
}
}
}
We need to download the template, parse it and put the new file back on to the server. As this is a generic thing to do, you can just create a ruby function and add it your deploy.rb file.
#
# Get the template from the server,
# parse it, and place the new file back on the server
#
def RunTemplate(remote_file_to_get,remote_file_to_put)
require 'erb' #render not available in Capistrano 2
get(remote_file_to_get,"template.tmp") # get the remote file
template=File.read("template.tmp") # read it
buffer= ERB.new(template).result(binding) # parse it
put buffer,remote_file_to_put # put the result
end
task :configure_nginx do
# run the template
RunTemplate(nginx_remote_template,nginx_remote_config)
#move the config in to sites-available
sudo "mv #{nginx_remote_config} /etc/nginx/sites-available/#{application}"
#add a symlink into sites enabled
sudo "ln -s -f /etc/nginx/sites-available/#{application}
/etc/nginx/sites-enabled/#{application}"
end
cap configure_nginx
If you have a spin script to start the mongrel servers
(/script/process) like this
home/demo/public_html/subreview.com/current/script/process/spawner -p 8000 -i 2 -e production
you’ll notice that the port and number of instances are hard coded. Once again we’ll need to make another template file.
Create a file called spin.template and place it in the public_html folder on the server (change the setting spin_remote_template in deploy.rb to change the location) . The template should look like this:
<%=deploy_to%>/current/script/process/spawner -p <%=mongrel_port%>
-i <%=mongrels%> -e production
task :configure_spin do
RunTemplate(spin_remote_template,spin_remote_config)
end
It’s worth testing out the task with:
cap configure_spin
Check the file your_app/current/script/spin on the server to make sure it has been updated. You may have to add an extra command to configure_spin task to make sure it has the correct permissions set.
Add an extra line to the configure_nginx task to call configure_spin. Then set the configure_nginx task to be triggered when deploy:start or deploy:restart is called. You may want to change this so it occurs before a different deploy task.
task :configure_nginx do
RunTemplate(nginx_remote_template,nginx_remote_config)
......
configure_spin
end
before "deploy:restart","configure_nginx"
before "deploy:start","configure_nginx"
I also use another task called nginx_reload which is called after deploy, it’s detailed here.
If you now try cap deploy:cold it should go off and start your app (don’t forget to do cap deploy:setup if it’s your first time deploying it).
The custom tasks should really be put in to a separate file so you don’t have to duplicate them for each deploy.rb file.
If one of your domains needs some custom config in the nginx file, you can add something like this to the template
<% if domain="myspecial_domain" %>
... insert custom nginx config here
<%end %>
If you need help with Capistrano or nginx there are some good articles over at slicehost: nginx, capistrano.
At some point when creating a Flex application you will want to update an item in the database using Rails(e.g. the details about a film).
To update a resource using REST you need to use the HTTP verb PUT, so the code below should work if we’re updating a film with ID=1:
<mx:HTTPService id="UpdateFilm" method="PUT" url="films/1.xml" useProxy="false" ... </mx:HTTPService>
The manual states if useProxy=”false” you can only use GET or POST. Not particularly good if you want to get some rest in:-)
Luckily Rails has a work around for this, which is the detection of a _method parameter on the end of a URL. For example:
<mx:HTTPService id="UpdateFilm"
method="POST"
url="films/1.xml?_method=PUT
....
</mx:HTTPService>
SubReview was developed using Ruby on Rails v2, Flex and Yahoo YUI.
The software design behind the scenes is roughly based on a REST based architecture. If you’ve never heard of REST before then this site has a good explanation about it.
Some of the REST resources on this site are:
Latest Film reviews |
---|
Daisy (데이지) |
Casshern (キャシャーン) |
SPL, Sha Po Lang (殺破狼) |
Sky Blue (원더풀 데이즈) |
R-Point (알 포인트) |
Latest Gadget reviews |
---|
Powerbar |
Philips Sonicare B400 Series (HX6431/46) |
FlashSticks |
Nokia N76 |
Sony W880i |
Latest Game reviews |
---|
F1 2009 (Wii) (F1 2009) |
Resident Evil 4 (Wii Version) |
Latest Articles |
---|
OpenID now enabled by sub1 (06/05) |
Why is GTA IV not on the Wii? by nicos (12/04) |
Capistrano Nginx Mongrel VHost by sub1 (04/04) |
Flex HTTPService PUT method problem by sub1 (19/03) |
SubReview development by sub1 (17/03) |
Welcome by sub1 (11/03) |