<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>geek# &#187; MVC</title>
	<atom:link href="http://geeksharp.com/tag/mvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://geeksharp.com</link>
	<description>techno-babble for the masses</description>
	<lastBuildDate>Thu, 27 May 2010 14:57:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Nginx and Rails and PHP, Oh My!</title>
		<link>http://geeksharp.com/2009/12/09/nginx-and-rails-and-php-oh-my/</link>
		<comments>http://geeksharp.com/2009/12/09/nginx-and-rails-and-php-oh-my/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 05:45:14 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://geeksharp.com/?p=39</guid>
		<description><![CDATA[As you could probably guess, my blog (and several sites of my friends) are hosted on a lovely Linux VPS provided by Linode.  I honestly can’t say enough nice things about the service and reliability I’ve received from Linode (and no they don’t pay me to speak highly of them!).  But that’s not really the [...]]]></description>
			<content:encoded><![CDATA[<p>As you could probably guess, my blog (and several sites of my friends) are hosted on a lovely Linux VPS provided by <a href="http://www.linode.com/" target="_blank">Linode</a>.  I honestly can’t say enough nice things about the service and reliability I’ve received from Linode (and no they don’t pay me to speak highly of them!).  But that’s not really the point of this post.  The point is actually quite simple:  My VPS doesn’t have a lot of memory, and I’m always wary of my resource consumption.  A few months ago, I moved from <a href="http://www.apache.org/" target="_blank">Apache</a> to <a href="http://www.lighttpd.net/" target="_blank">lighttpd</a> for this reason, alone.  Let’s face it… Apache is a memory hog, and that problem is well-documented, so I won’t really go into details here.  “Lighty” has served me well for the past few months, but for reasons I’m about to explain, I felt the need to move to a different platform.</p>
<p>So earlier this year I wrote a post about how I wanted to learn <a href="http://rubyonrails.org/" target="_blank">Ruby on Rails</a>.  For a while now, I’ve put that project on the back burner.  I decided after my last post on the subject that <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a> was more fitting for me because, let’s face it, I’m a .NET developer right?  And aren’t .NET developers supposed to stick with .NET stuff?  After deploying my first site using ASP.NET MVC, I came away with a feeling that it was a little heavier than I’d like it to be, and I really don’t like paying for another separate Windows VPS just to host one website!  There’s also the fact that Linux is way more efficient in limited resource deployments (like VPS’s).  All of this boils down to the fact that Rails called to me once again, and I decided that if I was going to do Rails development, I needed to figure out the deployment environment.</p>
<p>After doing some research, <a href="http://www.rubyenterpriseedition.com/" target="_blank">Ruby Enterprise Edition</a> and <a href="http://www.modrails.com/" target="_blank">Phusion Passenger</a> seemed like the obvious choice for production Rails deployment.  Both products value resource management in environments just like mine, and the numbers they claim to achieve were very impressive!  If you want to run Phusion Passenger, however, your choices in a web server are limited to Apache or <a href="http://nginx.net/" target="_blank">Nginx</a>.  Considering my previous encounters with Apache, I decided Nginx was the way to go.  That said, after hours of fussing getting this environment set up properly, I decided that it would be best if I contributed a guide to the community.  This wasn’t the easiest process in the world, and I hope this tutorial can help someone else avoid the headaches that I faced.</p>
<h4>Step 1: Environment and pre-requisites</h4>
<p>First and foremost, I use a 32-bit version of Ubuntu 9.10 Karmic Koala on my VPS.  the instructions you see are specific to my environment, but I’m sure they could be adapted for use in others.  On my server, there were some packages that were necessary pre-requisites.  Here are the steps to install them:</p>
<p>First, edit your /etc/apt/sources.list and remove the comment marks (#) in front of the universe repository lines</p>
<pre class="brush: plain;">deb http://us.archive.ubuntu.com/ubuntu/ karmic universe
deb-src http://us.archive.ubuntu.com/ubuntu/ karmic universe
deb http://us.archive.ubuntu.com/ubuntu/ karmic-updates universe
deb-src http://us.archive.ubuntu.com/ubuntu/ karmic-updates universe
deb http://security.ubuntu.com/ubuntu karmic-security universe
deb-src http://security.ubuntu.com/ubuntu karmic-security universe</pre>
<p>Next you need to issue the following commands to get all the rest of the packages you need:</p>
<pre class="brush: plain;">sudo apt-get update
sudo apt-get install build-essential libxml2-dev libssl-dev libbz2-dev curl libcurl4-openssl-dev libpng12-dev libmcrypt-dev mysql-server libmysqlclient-dev libxslt1-dev autoconf2.13 libltdl-dev libreadline5-dev libsqlite3-ruby postgresql-server-dev-8.4 libpcre3-dev</pre>
<p>Next you need to install libevent.  There is a version of this in the repository, but it&#8217;s pretty out of date, and PHP-FPM prefers the newer version.  For this requirement, I decided to compile from source.  Use the following commands to get this installed.</p>
<pre class="brush: plain;">wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./configure
make &amp;&amp; sudo make install</pre>
<h4>Step 2: Compiling PHP  from source with Suhosin and PHP-FPM</h4>
<p>So the reason I decided to compile PHP from source is because it&#8217;s the easiest way (for me) to apply the PHP-FPM patch and make sure I have everything I need.  I realize that there may be some Ubuntu packages out there at some point, but there weren&#8217;t any that were easily found when I performed these steps.  That said, our first step is to snag the PHP source and then apply the Suhosin patch.</p>
<pre class="brush: plain;">wget http://us2.php.net/get/php-5.3.1.tar.bz2/from/this/mirror
bzip2 -dc php-5.3.1.tar.bz2 | tar xf -
wget http://download.suhosin.org/suhosin-patch-5.3.1-0.9.8.patch.gz
gunzip suhosin-patch-5.3.1-0.9.8.patch.gz
patch -d php-5.3.1 -p1 &lt; suhosin-patch-5.3.1-0.9.8.patch</pre>
<p>Now we have to install the PHP-FPM patch.  In order to do this, we actually need a legacy version of autoconf and autoheader, because the PHP buildconf script relies on them.  Luckily, they were installed earlier when we grabbed stuff from the Ubuntu repositories.  All we have to do is set some environment variables to force the legacy versions to be used.  Then we can just apply the patch and compile PHP.</p>
<pre class="brush: plain;">export PHP_AUTOCONF=/usr/bin/autoconf2.13
export PHP_AUTOHEADER=/usr/bin/autoheader2.13
wget http://launchpad.net/php-fpm/master/0.6/+download/php-fpm-0.6~5.3.1.tar.gz
tar -zxf php-fpm-0.6~5.3.1.tar.gz
php-fpm-0.6-5.3.1/generate-fpm-patch
patch -d php-5.3.1 -p1 &lt; fpm.patch
cd php-5.3.1
./buildconf --force
./configure --enable-bcmath --with-bz2 --enable-calendar --with-fpm --with-libevent=shared --with-curl --enable-dba --enable-exif --enable-ftp --with-gd --with-gettext --enable-mbstring --with-mysql --with-mysqli --with-pdo-mysql --with-openssl --with-pcre-regex --enable-shmop --enable-soap --enable-sockets --enable-sysvmsg --enable-wddx --enable-zip --with-zlib --enable-sysvsem --enable-sysvshm --with-mcrypt --enable-pcntl --enable-mbregex --with-mhash --with-xsl
sudo make all install</pre>
<h4>Step 3: Compiling Ruby Enterprise Edition and Nginx</h4>
<p>Now that PHP-FPM is installed, we need to get Nginx up and running.  The good part is that Ruby Enterprise Edition comes bundled with Phusion Passenger which will handle compiling Nginx for us.  We do, however, need to download the Nginx source manually because there are some options that we&#8217;d like to pass to the Nginx configure script.</p>
<pre class="brush: plain;">cd ..
wget http://sysoev.ru/nginx/nginx-0.7.64.tar.gz
tar -zxf nginx-0.7.64.tar.gz
wget http://rubyforge.org/frs/download.php/66162/ruby-enterprise-1.8.7-2009.10.tar.gz
tar -zxf ruby-enterprise-1.8.7-2009.10.tar.gz
sudo ruby-enterprise-1.8.7-2009.10/installer</pre>
<p>The cool part about Ruby Enterprise Edition is that it&#8217;s completely isolated from the rest of your system, and it installs most of the default gems for you.  As a matter of fact, the only thing left to do is to actually install Nginx with Phusion Passenger support, and that&#8217;s exactly what we&#8217;re doing next!</p>
<pre class="brush: plain;">sudo /opt/ruby-enterprise-1.8.7-2009.10/bin/passenger-install-nginx-module</pre>
<p>While running through this installer, there are a series of prompts.  Be sure you answer the following:</p>
<pre class="brush: plain;">Enter your choice (1 or 2) or press Ctrl-C to abort: 2
Please specify the directory: &lt;enter your directory, in my case it was /home/scott/nginx-0.7.64&gt;
Please specify a prefix directory [/opt/nginx]: /usr/local/nginx
Extra arguments to pass to configure script: --sbin-path=/usr/local/sbin --with-http_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_gzip_static_module</pre>
<h4>Step 4: Configuration of PHP-FPM and Nginx</h4>
<p>Sweet!  At this point you should have a shiny new Nginx install.  Before we can start it up, though, there are a few configuration files we have to mess with.  First we need to configure PHP-FPM to run as the proper user and place a default php.ini file in the appropriate directory.  First, let&#8217;s edit php-fpm.conf.  There are 4 lines we need to change, so just search through the file and make sure they look like this:</p>
<pre class="brush: plain;">&lt;value name="owner"&gt;www-data&lt;/value&gt;
&lt;value name="group"&gt;www-data&lt;/value&gt;
&lt;value name="user"&gt;www-data&lt;/value&gt;
&lt;value name="group"&gt;www-data&lt;/value&gt;</pre>
<p>Next we need to copy in the default php.ini file from the source directory.</p>
<pre class="brush: plain;">sudo cp php-5.3.1/php.ini-production /usr/local/etc/php.ini</pre>
<p>Finally, we need to configure Nginx.  I don&#8217;t like having one huge configuration file, so I really like to split things up.  You can edit this to your liking, but here&#8217;s basically how I set my default config (found at /usr/local/nginx/conf/nginx.conf):</p>
<pre class="brush: plain;">user  www-data;
worker_processes  6;

events {
 worker_connections  1024;
}

http {
 include       mime.types;
 default_type  application/octet-stream;
 sendfile        on;
 keepalive_timeout  10 10;

 passenger_root /opt/ruby-enterprise-1.8.7-2009.10/lib/ruby/gems/1.8/gems/passenger-2.2.7;
 passenger_ruby /opt/ruby-enterprise-1.8.7-2009.10/bin/ruby;

 gzip  on;
 gzip_comp_level 1;
 gzip_proxied any;
 gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

 log_format main '$remote_addr - $remote_user [$time_local] '
 '"$request" $status  $body_bytes_sent "$http_referer" '
 '"$http_user_agent" "$http_x_forwarded_for"';

 access_log  /var/log/nginx_access.log main;

 error_log  /var/log/nginx_error.log crit;

 include /usr/local/nginx/sites-enabled/*;
}</pre>
<p>Now we need to set some default fastcgi options in /usr/local/nginx/conf/fastgci_params.  I just appended these to the end of the file.</p>
<pre class="brush: plain;">fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;</pre>
<p>Next, I like to create a &#8220;/usr/local/nginx/sites-enabled&#8221; directory that houses each website&#8217;s configuration details.  First I&#8217;ll show the configuration I used to handle URL rewrites for WordPress (this blog).  I called the file /usr/local/nginx/sites-enabled/geeksharp.com.</p>
<pre class="brush: plain;">server {
 listen 80;
 server_name *.geeksharp.com *.geeksharp.info *.geeksharp.org geeksharp.info geeksharp.org;
 rewrite ^(.*) http://geeksharp.com$1 permanent;
}

server {
 listen 80;
 server_name geeksharp.com;
 location / {
 root   /var/www;  # absolute path to your WordPress installation
 index  index.php index.html index.htm;

 # this serves static files that exist without running other rewrite tests
 if (-f $request_filename) {
 expires 30d;
 break;
 }

 # this sends all non-existing file or directory requests to index.php
 if (!-e $request_filename) {
 rewrite ^(.+)$ /index.php?q=$1 last;
 }
 }

 location ~ \.php$ {
 fastcgi_pass 127.0.0.1:9000;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
 include fastcgi_params;
 }
}</pre>
<p>Here&#8217;s how I&#8217;d set up a rails site.  In this example, the file is called /usr/local/nginx/sites-enabled/geeksharp.net.</p>
<pre class="brush: plain;">server {
 listen 80;
 server_name *.geeksharp.net;
 rewrite ^(.*) http://geeksharp.net$1 permanent;
}

server {
 listen 80;
 server_name geeksharp.net;
 root /home/scott/geeksharp.net/public;
 passenger_enabled on;
 access_log /home/scott/geeksharp.net-access.log;
 error_log /home/scott/geeksharp.net-error.log;
}</pre>
<h4>Step 5: Startup scripts</h4>
<p>Finally, I like to ensure that all my stuff comes up when the system reboots, so here&#8217;s a neato Nginx init.d script that I found.  Place this file at /etc/init.d/nginx, and make sure you give it execute permissions (chmod +x!)</p>
<pre class="brush: plain;">#! /bin/sh

### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the nginx web server
# Description:       starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sbin/nginx
NAME=nginx
DESC=nginx

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
 . /etc/default/nginx
fi

set -e

case "$1" in
 start)
 echo -n "Starting $DESC: "
 start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON -- $DAEMON_OPTS
 echo "$NAME."
 ;;
 stop)
 echo -n "Stopping $DESC: "
 start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON
 echo "$NAME."
 ;;
 restart|force-reload)
 echo -n "Restarting $DESC: "
 start-stop-daemon --stop --quiet --pidfile \
 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON
 sleep 1
 start-stop-daemon --start --quiet --pidfile \
 /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
 echo "$NAME."
 ;;
 reload)
 echo -n "Reloading $DESC configuration: "
 start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \
 --exec $DAEMON
 echo "$NAME."
 ;;
 *)
 N=/etc/init.d/$NAME
 echo "Usage: $N {start|stop|restart|force-reload}" &gt;&amp;2
 exit 1
 ;;
esac

exit 0</pre>
<p>Finally, make sure you update your rc.d</p>
<pre class="brush: plain;">sudo update-rc.d nginx defaults
sudo update-rc.d php-fpm defaults</pre>
<p>Please note that if for some reason nginx won&#8217;t start, chances are you have a config issue.  When you issue a restart command, the config errors usually will not be displayed.  The best way to track them down is to is to simply issue a stop command followed by a start command, and your errors will be displayed.  If you ever need to restart your services manually, you can use these commands (I find that restart can be buggy, which is why I explicity stop and start each one):</p>
<pre class="brush: plain;">sudo /etc/init.d/php-fpm stop &amp;&amp; sudo /etc/init.d/php-fpm start
sudo /etc/init.d/nginx stop &amp;&amp; sudo /etc/init.d/nginx start</pre>
<p>So that&#8217;s it! I know this is an epic post, but I hope it helps someone. Leave comments if you have specific questions or if I left out something particularly useful. Again, I understand that there&#8217;s probably a better way to do something, so feel free to share your thoughts!  As a final thought, I would like to thank <a href="http://interfacelab.com/nginx-php-fpm-apc-awesome/" target="_blank">Joshua Dorkin</a> for providing a great article on which I based a lot of this material!</p>
]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2009/12/09/nginx-and-rails-and-php-oh-my/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Learning Rails (and Ruby too!)</title>
		<link>http://geeksharp.com/2009/06/06/learning-rails-and-ruby-too/</link>
		<comments>http://geeksharp.com/2009/06/06/learning-rails-and-ruby-too/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 04:16:19 +0000</pubDate>
		<dc:creator>Scott Anderson</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://geeksharp.com/2009/06/06/learning-rails-and-ruby-too/</guid>
		<description><![CDATA[Over the past couple days I’ve been reading what’s shaping up to be an excellent book about Ruby on Rails called “Agile Web Development with Rails (Third Edition).”&#160; This book takes a practical approach to teaching Rails by building a demonstration shopping cart application called “Depot.”&#160; I must say that, so far, learning Rails has [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past couple days I’ve been reading what’s shaping up to be an excellent book about <a href="http://rubyonrails.org/" target="_blank">Ruby on Rails</a> called “<a href="http://www.pragprog.com/titles/rails3/agile-web-development-with-rails-third-edition" target="_blank">Agile Web Development with Rails (Third Edition)</a>.”&#160; This book takes a practical approach to teaching Rails by building a demonstration shopping cart application called “Depot.”&#160; I must say that, so far, learning Rails has been a complete pleasure.&#160; I really enjoy the MVC methodology and the idea of “convention over configuration.”&#160; The basic idea behind Rails is that we (as web developers) generally know what we’re doing, and we can follow some simple default conventions to avoid the mountains of configuration files that are so common in other technologies and frameworks (ASP.NET is a prime example of those “other” technologies).</p>
<p>Over the next few weeks I plan on spending a lot more time with Rails and <a href="http://www.asp.net/mvc/" target="_blank">ASP.NET MVC</a>.&#160; My end goal is to present an overview of the benefits and faults of each technology, and hopefully I can provide a somewhat objective point of view for people new to MVC.&#160; Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://geeksharp.com/2009/06/06/learning-rails-and-ruby-too/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
