Using Nginx + Passenger as your development environment
Posted: September 17th, 2009 | Author: Josh Kalderimis | Filed under: Mac, Rails, Ruby, Web Development | Tags: development, Rails, Ruby, server | 3 Comments »As a rails developer you are blessed early on with the fantastic script/server for starting a local development server. Rails is smart enough that it will even suggest you install the Mongrel gem as it is a faster alternative to the basic stock standard WEBrick. But as time passes and your skills improve and the amount of projects you are working on increases, you may find yourself looking for a simpler solution than having to start up an individual script/server on different ports for each project. Or you may just want to have an app run in the background waiting for you to access one of the sites and start it up automatically. What ever the case, there are some very nice solutions available.
99% percent of people who have deployed a rails app have undoubtedly come across Passenger (modrails) from the fantastic guys at Phusion. Simple put, this allows you to config and run your rails app with (initially) Apache or (as of lately) Nginx while also taking advantage of their supplier static assets serving capabilities.
So why would you choose Nginx over Apache in you development environment? For me the reasons for using Nginx was simple and quick configuration, very very very low memory usage, and it mimics my deployment server setup.
So waffle aside, how do we install and setup Nginx, including for you development environment
installing nginx and passenger
Passenger is nice enough to offer to install Nginx for you automagically, including downloading Nginx 0.7.61, but this is already an old version, so the plan is to :
- download the latest stable version of nginx
- extract to /usr/local/src/nginx
- install the latest version of passenger via gem
- have passenger configure, compile and install nginx for us
- tweak the nginx configs
- putting it all together
so lets get started….
1. and 2. download the latest stable version of nginx and extract it
sudo mkdir src
cd src
wget http://sysoev.ru/nginx/nginx-0.7.62.tar.gz (latest verion at time of writing)
tar -zxvf nginx-0.7.62.tar.gz
3. and 4. install passenger via gem and configure, compile and install nginx
sudo passenger-install-nginx-module
during the installer program enter the following information
answer /usr/local/src/nginx-0.7.62
answer /usr/local/nginx
answer --with-http_ssl_module
answer yes
Ok, now nginx and passenger are installed with ssl support baked in, what to do from here…
5. tweak the nginx configs
The default nginx config file is pretty basic, which is excellent, because its all you really need, but a few tweaks here and there can make a great thing even better. Slicehost has an excellent write up on some recommended changes here, but as this is your development environment and not production, I suggest not changing worker_processes or keepalive_timeout.
In the end, this is what my server nginx.conf looks like:
events {
worker_connections 1024;
}
http {
passenger_root /opt/local/lib/ruby/gems/1.8/gems/passenger-2.2.5;
passenger_ruby /opt/local/bin/ruby;
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
keepalive_timeout 65;
gzip on;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# All the virtual hosts exist here
include /usr/local/nginx/sites-enabled/*;
}
(I have taken out all the commented out lines)
You will notice the passenger_root and passenger_ruby properties/directives in the conf file. These are required for passenger to start, but you don’t need to worry about inserting them as the passenger nginx installer does it for you.
This is what my virtual server file looks like:
listen 80;
server_name lotsoffunstuff.local;
root /Users/me/Development/ruby-workspace/pet-projects/lotsoffunstuff.com/public;
passenger_enabled on;
rails_env development;
}
And thats it, an nginx server + one virtual host all ready to run via:
I also added an alias to me ~/.profile file
alias stopnginx='sudo /usr/local/nginx/sbin/nginx -s stop'
now you can just use nginx and stopnginx.
6. putting it all together
ok, the title is a little deceptive as it all seems to be together, but there is one very important change yet to be made, making sure passenger can reach and read your source code.
I ran into this problem when I was setting up my environment, and it all has to do with how passenger and nginx works. As per any good webserver, you need to start it as root so it can access the right ports (80) and directories (pid files), but its worker processes should run as nobody or www-data to restrict unneeded access to other resources. For Nginx to know if the server is a rails app or not, its worker process needs to be able to access the document root, in this case public, and every single one of its parent directories. As I keep my development files within my home directory, nginx would throw a 403 error and add a non-descriptive error message to the error.log file.
Two options are available to fix this:
- add read access to all the parent directories to everyone (chmod o+r -R .)(I think)
- have the nginx worker processes run as a privileged user which can access all the directories in the path
I choose option two and had the nginx worker processes run as myself. Although you could argue this is insecure, as I only have the server running when I need to, and nginx and passenger have a great track record, I think this is better than setting my home directory to read for everyone.
And there we are, all set up and ready to develop! And all in under 30 mins!
some good links and tips
important for deployment : rails maintenance pages done right
init script for ubuntu : nginx-init-ubuntu
1.9 + nginx + passenger : ruby-rails-nginx-passenger
excellent config details : ubuntu-intrepid-nginx-configuration
nginx + vhosts : ubuntu-intrepid-nginx-virtual-hosts
docs galore : http://nginx.net/ and http://wiki.nginx.net/
special mention to slicehost for all the fantastic server and service related articles known to man
absolutely agree with that slicehost contains excellent articles on setting up your server
This is excellent, thanks… quick question. How did you change the user the worker processes nginx runs under? I changed the user directive in nginx.conf to my user account but I get an error when starting nginx: [emerg]: getgrnam(”dan”) failed in /usr/local/nginx/conf/nginx.conf:2
Did you face this?
user www www;