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:
WARNING WHAT FOLLOWS MIGHT MESS UP YOUR INSTALL DO THIS AT YOUR OWN RISK I TAKE NO RESPONSIBILITY TO WHAT YOU MESS UP AND I DON'T CLAIM THIS IS THE RIGHT WAY TO DO ANYTHING. IT'S ME...RAMBLING AWAY THROUGH MY SWITCH OVER :)
My Current Setup
- Digital Ocean 1GB Droplet
- Ubuntu 14.04 LTS x64
- Apache 2.4.10
- Bolt CMS v1.6.13
I'll be moving to:
- Same Droplet
- Same OS
- Same CMS
- 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 (>= 0.99.7.1),
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:
#cd
Nginx VERSION=1.6.2
wget http://nginx.org/download/nginx-${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):
wget https://github.com/openresty/headers-more-nginx-module/releases/tag/v0.25
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 ).
wget https://github.com/nbs-system/naxsi/archive/0.53-2.tar.gz
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/nginx.pid \
--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
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 webpagetest.org 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.