Moving From Apache to Nginx

This post is over six (6) months old. Some things on this page my be out of date or no longer applicable.

It seems more and more people are going to Nginx instead of Apache and rave about the speed. Since I'm not a system admin and never claimed to be one I figured I'd document my switch to Nginx

Me being a novice in relation to Nginx I was quite taken aback that you can't just enable modules like you can in Apache. In an Ubuntu Server install enabling a Module like Mod_Pagespeed is as simple as sudo dpkg -i mod-pagespeed-*.deb followed by sudo apt-get -f install . That's it and the Google Repository is added to your system and will keep Mod_PageSpeed up to date.

Adding the same module in Nginx is quite another process. You must first make sure you have all the dependencies installed for it to build, download the source, unpack it, then build it. Even then you aren't finished because you still have to build Nginx from source and enable the module there. That's a lot of work especially for someone like me who doesn't have a PhD in Unix.

Now for my warning:


My Current Setup

  1. Digital Ocean 1GB Droplet
  2. Ubuntu 14.04 LTS x64
  3. Apache 2.4.10
  4. Bolt CMS v1.6.13

I'll be moving to:

  1. Same Droplet
  2. Same OS
  3. Same CMS
  4. Nginx v 1.6.2

Getting Started

To keep my current site up and running I created a new droplet. I then wanted to see what Nginx had as a dependency aptitude show nginx-full for the full version of nginx. This will print to your terminal a lot of "things". Pay close attention to the depends part. Depending on the date and nginix version when you do this it will look similar to the following.

Depends: nginx-common (= 1.4.6-1ubuntu3.1), libc6 (>= 2.14), libexpat1 (>=
  2.0.1), libgd3 (>= 2.1.0~alpha~), libgeoip1, libpam0g (>=,
  libpcre3, libssl1.0.0 (>= 1.0.1), libxml2 (>= 2.7.4), libxslt1.1 (>=
  1.1.25), zlib1g (>= 1:1.2.0)

I'll need libc6, libexpat1, libgd3, libgeoip1, libpam0g, libpcre3, libssl1.0.0, libxml2, libxslt1.1, zlib1g. If you aren't going to go with the nginx-full version your dependencies will vary. I know I won't be using any XSLT so I won't be needing libxslt1.1 but for the sake of this write up and having satisfied all dependencies I'll install it. Chances are though that you'll already have many of these installed already and the current versions.

 apt-get install libc6 libexpat1 libgd3 libgeoip1 libpam0g libpcre3 libssl1.0.0 libxml2 libxslt1.1 zlib1g 

Now that the dependencies for Nginix are satisfied we can move on to actually downloading Nginx source files. As of this write up the Nginx version I am using is 1.6.2. We'll do that by typing into a terminal the following:

  Nginx VERSION=1.6.2
  wget${Nginx VERSION}.tar.gz
  tar -xvzf nginx-${Nginx VERSION}.tar.gz

I also want to take advantaged of another module called headers_more . You download that the same way as we did for Nginx source (substituting the release which is compatible with your Nginx version):

  tar -xvzf v0.25.tar.gz

Now is usually about the time I would download Google's PageSpeed Module source files. I won't be using this with my current Nginx setup right now. More on that here and I won't be using my old trusty standbye of ModSecurity security either. Quite frankly in my opinion...IT'S A PAIN IN THE ASS TO BUILD. I couldn't get ModSecurity for Nginx to build no matter what I tried. I followed the wiki instructions, installed dependencies and nada. Like I said I don't have a PhD in Unix. I'm a modest web developer. Anywho I installed Naxsi in it's place.

Naxsi on the other hand is fairly straight forward to install and build. The biggest caveat we have is the order in which we will compile it into Nginx Download Naxsi like so ( version numbers may change ).

  tar -xvzf 0.53-2.tar.gz

Building This Thing!

All our third party modules are downloaded and upacked and ready to go. The next step we will change into the Nginx directory cd nginx-1.6.2 . If you're unsure about where the directory is you can type ls in your terminal and it will list all the directories and or files from your current location. Once in the Nginx source directory we can begin to compile our server package. Nginx has a list of other third party modules that you can include. For any of those follow the same steps for getting headers_more and Naxsi. It also has a list of optional modules you can include during compile time found here . From the Optional Modules I'll be including stub_status, spdy_module, gzip_static and ssl modules. This list may seem long and hard but as of right now it's pretty much downhill from here.

Inside our nginx-1.6.2 directory will give it the compile command. All of this needs to typed on one line unless you escape it like in the code block below. The order of installing Naxsi is important. If you're just starting out and testing Nginx and Naxsi out put it first like in the code block below. More on why you should do this can be found at Naxsi Github Wiki

  ./configure \
  --add-module=$HOME/naxsi-0.53-2/naxsi_src \
  --prefix=/usr/share/nginx \
  --sbin-path=/usr/sbin/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --pid-path=/var/run/ \
  --lock-path=/var/lock/nginx.lock \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/access.log \
  --user=www-data \
  --group=www-data \
  --with-http_stub_status_module \
  --with-http_ssl_module \
  --with-http_spdy_module \
  --with-http_gzip_static_module \
  --add-module=$HOME/headers-more-nginx-module-0.25 \

Once this is complete give it the commands of:

  # you may need to do these as sudo if you aren't root
  make install

That's it. Nginx is now installed... well it's installed but we need to do a few more things.

Starting and Stopping Nginx

If you were to leave everything as it is you would need to start Nginx like sudo /usr/sbin/nginx start and then kill it with its PID. That's rather cumbersome in my opinion. So in order to start and stop it like you would Apache ( service apache2 start/stop/status etc ) we need to have an init script. I'm using this one with modifications to the nginx sbin paths, DAEMON paths, and conf paths that reflect the options in our compile time flags above.

Once that's finsihed we'll make sure Nginx starts up on a reboot of our server

  update-rc.d -f nginx defaults

Nginx should now be up and running with our modules. You can now move on to your virtualhosts and server setup. A rather good tutorial on this for Ubuntu can be found at DigitalOcean

Google's PageSpeed Module

I mentioned I wasn't going to use Google's Pagespeed Module. Reasoning behind this is I don't know if I bunked up my Apache setup but the Time To First Byte and overall load times with Pagespeed installed on Apache and Nginx were extremely different. For My Apache setup I used a setup of Passthrough and basically relied on pagespeeds image compressions, serving webp to user agents who accepted it and extending the caches of my resources.

Result Comparisons

Site Load times for each server configuration on with 5 runs each in Chrome from Dulles, Va.

First Run

Server Load Time First Byte Start Render Speed Index
Apache - Score Picture 0.684s 0.267s 0.493s 500
Nginx - Score Picture 0.640s 0.108s 0.293s 385

Second View

Server Load Time First Byte Start Render Speed Index
Apache - Score Picture 0.628s 0.184s 0.589s 600
NGINX - Score Picture 0.403s 0.082s 0.404s 400

Since a target Speed Index is under 1000 both servers did really well. I'm just not looking for the "meh its good enough". I want super dooper fast. NGINX gave that too me. In a few more blog posts I'll tinker with serving webp and jpegxr for better image handling. That post can now be found at Conditionally Serve Webp, JXR Images with Nginx.