AWS: Ruby on Rails Deployment Part 1: Nginx Installation and Configuration

Over the course of this series of articles, I will cover the build and configuration of an Amazon EC2 Instance capable of serving Ruby on Rails applications. The series will cover the build and installation of Nginx from source, virtual host and proxy configuration within Nginx, installation of Ruby and RubyGems, installation of the Rails and Thin gems, and the deployment of a set of clustered Thin workers. I chose Nginx over Apache HTTPD as it is renowned for both performing very well as a reverse proxy as well as serving static content whilst having a very low memory footprint. Plus, I’m always interested in looking at “alternative” software solutions to common problems.

Read my article around EC2 instance management via the ec2-api-tools if you’d like to provision your instance(s) via the command line, otherwise just provision your instance(s) via the EC2 Management Console. This article presumes that you have an instance running and ready to go. I used ami-08df4961 (which is Ubuntu 12.10 i386 Server, EBS-backed). I’d use a RHEL instance but they are not eligible for the free tier due to licensing, plus the Ubuntu instances are very well supported by Canonical.

Installation of Nginx

Prior to downloading and compiling Nginx, I first installed the prerequisites via APT. I like to let package management tools take care of dependencies (so they are easily managed and updated), but install the major software components from source. This ensures that I always have the latest and greatest software release, and all functional and security patches are up-to-date. Anyway … those dependencies. First, I install dependencies I’ll need for general software build tasks:

Followed by the dependencies I need specifically for the Nginx build:

Obviously, all the packages I just installed had their own dependencies too, which APT handled and installed along with the specified packages.

Next, download the latest stable version of Nginx to /usr/local/src. This was 1.2.7 at the time of writing.

Extract the source:

Next, configure Nginx:

As you can see, I’ve defined a few things at the configure stage. I’m installing to /usr/local/nginx-1.2.7, and compiling in SSL support, whilst having Nginx look for its configuration file at /etc/nginx/nginx.conf by default.

Once configure completes successfully, compile and install the software:

Add a group and user for Nginx to run as. Nginx must still be started as root, but after successfully binding to any privileged ports, Nginx will drop privileges to the user and group created here (after appropriate configuration, of course).

I’ll be placing log files under /var/log/nginx, so I’ll create that directory now with appropriate ownership and permissions:

Nginx is now ready to start up – but before we do that, we need to configure it.

Configuring Nginx

Here is my /etc/nginx/nginx.conf. I’ve commented each directive so you can see what’s going on. The Nginx Documentation should be consulted if further clarity is required.

Even though I’m referring to virtual host specific configuration files under /etc/nginx/vhosts.d/*.conf at this point, there is no configuration there yet. I will create the directory, however.

Now, start Nginx:

Check for errors in /var/log/nginx/error.log (or whichever path you defined in your nginx.conf) – if there are none, the base setup is ready. Stop Nginx:

We can also have Nginx reload its configuration on the fly with the following commands:

As you can see, first the -t option is used to verify that the nginx.conf syntax is error-free, and then -s reload is passed to reload the configuration. Nginx even supports an upgrade of the nginx executable itself on-the-fly. See the Nginx Wiki for further information.

Conclusion

This article has walked through compiling Nginx from source, including the installation of prerequisite packages. It has also described the basic Nginx configuration in detail by way of a well-commented ngnix.conf file. Whilst the configuration is ready for the addition of virtual hosts (for example, the virtual host that will proxy back to the Thin workers), this is not yet done – at the moment Nginx is not serving anything – in fact it’s not even listening on a port yet.

Depending on your Operating System, you might want to create an init script or upstart job as appropriate so that you don’t have to start/stop Nginx manually on system reboot, for example.

Moving on from here, we need to install Ruby, RubyGems, Rails, Thin and finish the configuration of Nginx. All that is covered in the second article in this series.

Appendix – Upstart Script

Here is my well-commented upstart script for Nginx on Ubuntu. Install this to /etc/init/nginx.conf.

You can now use the start/stop/status/restart/reload commands to manage Nginx.

You can extend this script to add a call to $DAEMON -t, for example, to check the syntax of your Nginx configuration prior to attempting to (re)start the service.