Published on Oct 1, 2011

Setup NginX Web Server (Not Apache!) on Ubuntu 10.04

NGINX HTTP Web Server Program

NGINX HTTP Web Server Program

I know you are already puzzled why I’m referring to use Nginx (pronounced engine x) instead of the well known Apache. You might already have asked yourself, isn’t Apache the best webserver? Yes certainly it is, but you won’t like an elephant to stay at your home while you can be enough satisfied with your little pet and especially if you don’t have a house with a lot of free space, right? Nginx is sometimes much faster and reliable in low memory and CPU constraint environments. An ideal example is a VPS with 512MB RAM. Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. Let’s have a deeper look at the following comparison to understand the reasoning to prefer Nginx than Apache for a VPS.

Nginx is better than Apache?

Nginx is one of a handful of servers written to address the C10K problem. Unlike traditional servers, Nginx doesn’t rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture. This architecture uses small, but more importantly, predictable amounts of memory under load. Even if you don’t expect to handle thousands of simultaneous requests, you can still benefit from Nginx’s high-performance and small memory footprint. Nginx scales in all directions: from the smallest VPS all the way up to clusters of servers.

I want to quote from Chris Lea here so you can understand where lies the strength of Nginx:

Apache is like Microsoft Word, it has a million options but you only need six. Nginx does those six things, and it does five of them 50 times faster than Apache.

Now let’s see some benchmark comparisons to know how well Nginx performs than Apache:

  1. http://blog.webfaction.com/a-little-holiday-present
  2. http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/
  3. http://www.webandblog.com/reviews/apache-vs-nginx-testing-performance-under-heavy-load/

And here is a comparison wiki http://www.wikivs.com/wiki/Apache_vs_nginx

These advantages might be the reason why several high-visibility sites, such as Facebook, Zappos, Groupon, LivingSocial, Hulu, TechCrunch, Dropbox, WordPress, Github, Ohloh, SourceForge and many more are using Nginx for their web servers. Nginx now hosts nearly 12.18% (22.2M) of all domains worldwide. Got convinced? Now let’s install and configure Nginx and Make it work with PHP-FastCGI.

Install Nginx

To install nginx web server at first you need to add the PPA repository for it’s stable version and then use apt to install Nginx. To do so, use the following commands:

sudo -s
apt-get install python-software-properties
add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx

Configure Nginx HTTP Web Server

Now it’s time to configure Nginx as a standalone HTTP Web Server to enable it to serve web pages and downloadable files. To do so you need to first edit the file /etc/nginx/nginx.conf using the following command:

sudo vi /etc/nginx/nginx.conf

The configurations are self explanatory and here is also a reference to the core configuration directives with a full list of other directives available here. So I think you will be able to dig-up the best configuration for your system. Still if you are a bit lazy, then here is a sample configuration you may start with (optimized for VPS with Quad Core Processor and 512MB RAM):

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events
{
worker_connections 1024;
# multi_accept on;
}

http
{
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;

include /etc/nginx/mime.types;
default_type application/octet-stream;

# Default webpage
index index.php index.html index.htm;

##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

}

Now save the configuration file by pressing “ESC” and then typing the command :x and hit Enter. Then you need to configure the default website directory for your server from where web pages and files will be served. To do this at-first create the necessary directories. Say the main domain you want to configure with your server is example.com. Then create the following directories in your server for Nginx to serve files from. Apply the following commands:

sudo mkdir /var/www/example.com
sudo mkdir /var/www/example.com/logs
sudo mkdir /var/www/example.com/public_html
sudo mkdir /var/www/example.com/public_html/adminpanel
sudo mkdir /var/www/example.com/public_html/errorpages
sudo chown -R www-data /var/www/example.com/logs

Now edit the file /etc/nginx/sites-available/default with the following command:

sudo vi /etc/nginx/sites-available/default

Remove everything in the file by pressing “ESC” and then typing :1,$d. Then copy the following configuration and paste the copied content into vi by right clicking on top of vi editor. Then save and exit vi (press “ESC” then type :x and then hit enter).

server
{
listen        80;
server_name   www.example.com;

access_log /var/www/example.com/logs/access.log;
error_log /var/www/example.com/logs/error.log;

root /var/www/example.com/public_html/;

error_page  401 /errorpages/401.html;
error_page  403  /errorpages/403.html;
error_page  404  /errorpages/404.html;
error_page  500 502 503 504  /errorpages/500.html;

location /
{
try_files $uri $uri/ /index.php?$args;
}

# rewrite adminpanel to use https
rewrite ^/adminpanel(.*)$ https://$host$uri permanent;

# Add trailing slash to */wp-admin requests. Needed if wordpress is installed later
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# Directives to send expires headers
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$
{
expires 30d;
}

# Deny all attempts to access hidden files such as .htaccess, .htpasswd
location ~ /\.
{
deny all;
access_log off;
log_not_found off;
}

location ~ \.php$
{
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:6000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example.com/public_html$fastcgi_script_name;
}
}

Now let’s see if there is already a link created as /etc/nginx/sites-enabled/default. If not then we need to create a symbolic link to the file we’ve just edited to enable the site configuration. To do that use the following command:

sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

Now let me explain the configuration settings here. With the above configuration Nginx will listen to port 80 which is the default http port for web servers. Then the server name, access log and error log file locations are defined. Then the web root directory for example.com is defined. The later configurations in this file will use locations relative to the web root directory. Then the custom error pages are defined for the corresponding http error codes. For example if someone requests for a file or link that do not exist in your server, then the server will return the error code 404 and if custom 404 page is defined here then the user will receive that custom designed html error page instead of standard ugly looking 404 page. If you don’t want your error pages to look better, then you might remove these lines. Otherwise you need to place your custom designed html error pages in the defined location.

After that you are defining the location directive which is set to first look for the requested url, then adding a forward slash “/” to the url and then passing the arguments to the index file in the root folder. This setting will allow your server to handle permalinks properly. After that we are rewriting the admin panel folder to always use https instead of http for securing your admin panel file access. Then if you are planning to use wordpress later, then you need to also make sure that you rewrite your wordpress wp-admin requests to add a trailing slash to it.

After that you are configuring your server for the image and css files to send with an expiry parameter to the browsers, so that browsers can cache the image/css files and do not request your server every time a page is visited. This helps you to save valuable bandwidth and users can load the website much faster after their first visit. Here we set the expiry for 30 days. There is one tradeoff to consider, if your image/css file is changed and the name remains the same, then browsers may not update the image or the css before the amount of days you set here as expiry time. Browsers will update them if the user forcefully refresh the browser (i.e. Ctrl+F5) or 30 days have passed since the last visit.

After that we’ve set any hidden files to be inaccessible from the browser. In unix systems hidden file names starts with a dot. Then we’ve configured our web server not to directly serve .php files because doing so will only make your php source code available to the public. We’ve checked if the filename has .php extension and then are telling nginx to pass the request to the php-fastcgi process manager (which we will install later in this guide) to parse the php script and return the generated html file which nginx will serve to the end user. The try files directive inside this location is needed because if the php file in the requested url do not exist then it should send the correct 404 error code, otherwise it would generate a 500 internal server error. After this check we are passing this file to the php-fastcgi manager. Here we assume that your php installation will be in the same machine (127.0.0.1) and listening to the port 6000. We will configure php later to listen to this port. With this configuration the process that will happen when a user enters your website through their browser is explained in the following picture:

How Server Handles PHP Requests

How Server Handles PHP Requests

I’ll introduce you with the other players Mr. PHP-FPM, Mr. MySQL and Mr. Memcache in other articles later. I’ve tried to give you an overview of how your server will ultimately work with all the players setup properly to serve web pages efficiently. After Mr. Nginx get the generated html file, he then sends it back to the user’s browser. The browser then requests other static files linked in the html page (images and css files) and Mr. Nginx is smart enough to serve them all saying, “Mr. Browser please save those images and css files in your cache for next 30 days and please don’t bug me for the same thing again and again”.

Whatever let’s get back to the server configuration of nginx. Remember that you’ll find many insecure server configurations on the web that are vulnerable to hacking attempts. So whatever configuration is suitable for your server, you need to check and verify that your configuration is free from known vulnerabilities.

Now as you’ve configured everything to run NginX web server. Now you need to restart nginx for the settings to take effect. To do so type the following command in your vps terminal:

sudo service nginx restart

if that doesn’t work, then try the following:

sudo /etc/init.d/nginx restart

after your nginx is restarted without any errors, then you can test if your web server is working properly. To test this create a sample html file using vi or create with any other tool and then upload it to the server using sftp client like FileZilla. You need to create or upload an index.html file to the web root directory you’ve defined (in this case it’s /var/www/example.com/public_html/). Then goto your favorite browser and type in the ip-address of your system. You should see your html page you’ve just placed. Voila! your web server is working! You can also try uploading any file and download it by using http://your-ip-address/your-file-name.

Now you’ve seen your server can serve any static files placed in the web root directory or even any sub-directory. We’ll point our domain(www.example.com) to this server after we setup everything. It’s better not to show your website to the world while you’re playing with your server configurations :)

So let’s configure this server for handling https and also dynamic web pages using PHP and MySQL Database. The next articles will be discussing about these things. And remember one thing, if you want to install wordpress after the PHP and MySQL installation, everything will work just fine along with wordpress pretty urls (permalinks) without the need of .htaccess configuration. Just remember to install the wordpress nginx compatibility plugin that will help all your 301 redirects in wordpress to work properly. Also if you like to install web log analyzers like awstats, then you will be happy to know that NginX default web log formats are fully compatible with awstats and you can simply follow the Apache procedures described here to install awstats for NginX.

Articles in this Step by Step VPS Setup Guide

Getting Started with VPS – The Beginners Tutorial
Introductory concepts on web servers and virtual private servers. Introducing you to the world wide web from a technical point of view.

Shared Hosting, VPS, Dedicated and Cloud Servers
Comparing the popular server hosting solutions. Basic understanding of shared, dedicated, vps and cloud servers.

Deploy a Linux VPS Server using Linode
Tutorial on deploying your linux distribution in your VPS server and setting up hostname and initial configurations

Setup NginX Web Server (Not Apache!) on Ubuntu 10.04
Analyzing why NginX web server is better for you instead of the mostly used Apache. Demonstration on how to setup and configure NginX on Ubuntu server.

Enable HTTPS (HTTP+SSL) in NginX Web Server
Tutorial on enabling secure http connections for NginX web server. Demonstrating how to self sign your SSL certificate for the VPS server.

NginX Password Protect Web Directory
Helping you to protect specific web directories with passwords for restricting access to administration section or important private files that need to be accessed through the web.

Setup PHP-FPM with APC on Ubuntu 10.04 for Faster Performance
Installing and Configuring PHP5 with Fast CGI Process Manager along with the excellent op-code cache solution APC for faster and optimized PHP backend.

Setup MySQL with PHPMyAdmin on Ubuntu 10.04
Setting up MySQL database server and configuring for better performance in low memory environment. Also setup a web based database management front-end named PHPMyAdmin.

Configure Domains and Subdomains in your VPS Running NginX
Tutorial on DNS setup for adding additional domains and subdomains. Also configuring NginX for handling each domains/subdomains.

Domain Emails for Free Using Google Apps
Setup domain specific email addresses without installing any email server in your VPS. Google Apps seems to be a better solution in this regard.

5 Comments + Add Comment

  • Machbio

    December 28, 2011 at 4:33 am

    you get this error when you have installed it on ubuntu 11.04  - Restarting nginx: nginx: [emerg] unknown “server_https” variable

    • Masum

      December 28, 2011 at 9:08 am

      What’s your nginx version? Is it the latest one? The latest nginx needs to have an additional configuration setting inside the http block of the nginx.conf file like the following:

      map $scheme $server_https { default off; https on; }

  • shamir shakir

    April 13, 2012 at 9:34 am

    After a successful recovery from the problem quoted by Machblo, I came up with another problem. It’s like I’m getting 404 error when going to localhost or my ip directly. Can you help?

    • Masum

      April 14, 2012 at 5:36 am

      You need to add two more server block in your configuration to add localhost and the ip address as the server name like the following:

      server
      {
      listen 80;
      server_name localhost;

      … /* Other configurations */
      }

  • Arfan

    August 1, 2013 at 6:20 am

    I have an error in Nginx Image. My Image name is “my photo.jpg”. have a space its name. but Nginx is not showing the picture on screen. can any one help how to solve this problem

Leave a comment

Sponsored